View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.rules;
    5
    6   import java.util.Map;
    7
    8   import net.sourceforge.pmd.AbstractRule;
    9   import net.sourceforge.pmd.PropertyDescriptor;
    10  import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
    11  import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
    12  import net.sourceforge.pmd.ast.ASTCompilationUnit;
    13  import net.sourceforge.pmd.ast.ASTFieldDeclaration;
    14  import net.sourceforge.pmd.ast.ASTReferenceType;
    15  import net.sourceforge.pmd.ast.ASTPrimitiveType;
    16  import net.sourceforge.pmd.ast.ASTType;
    17  import net.sourceforge.pmd.ast.ASTVariableDeclarator;
    18  import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
    19  import net.sourceforge.pmd.properties.StringProperty;
    20
    21  public class VariableNamingConventions extends AbstractRule {
    22
    23      private String[] staticPrefixes;
    24      private String[] staticSuffixes;
    25      private String[] memberPrefixes;
    26      private String[] memberSuffixes;
    27
    28      private static final PropertyDescriptor staticPrefixesDescriptor = new StringProperty(
    29      	"staticPrefix", "Static prefixes", new String[] {""},	1.0f , ','
    30      	);
    31
    32      private static final PropertyDescriptor staticSuffixesDescriptor = new StringProperty(
    33         	"staticSuffix", "Static suffixes", new String[] {""},	2.0f , ','
    34         	);
    35
    36      private static final PropertyDescriptor memberPrefixesDescriptor = new StringProperty(
    37         	"memberPrefix", "Member prefixes", new String[] {""},	3.0f , ','
    38         	);
    39
    40      private static final PropertyDescriptor memberSuffixesDescriptor = new StringProperty(
    41         	"memberSuffix", "Member suffixes", new String[] {""},	4.0f , ','
    42         	);
    43
    44      private static final Map<String, PropertyDescriptor> propertyDescriptorsByName = asFixedMap( new PropertyDescriptor[] {
    45      	staticPrefixesDescriptor, staticSuffixesDescriptor,
    46      	memberPrefixesDescriptor, memberSuffixesDescriptor
    47  		});
    48
    49      /**
    50       * @return Map
    51       */
    52      protected Map<String, PropertyDescriptor> propertiesByName() {
    53      	return propertyDescriptorsByName;
    54      }
    55
    56      public Object visit(ASTCompilationUnit node, Object data) {
    57          init();
    58          return super.visit(node, data);
    59      }
    60
    61      protected void init() {
    62          staticPrefixes = getStringProperties(staticPrefixesDescriptor);
    63          staticSuffixes = getStringProperties(staticSuffixesDescriptor);
    64          memberPrefixes = getStringProperties(memberPrefixesDescriptor);
    65          memberSuffixes = getStringProperties(memberSuffixesDescriptor);
    66      }
    67
    68      public Object visit(ASTFieldDeclaration node, Object data) {
    69          return checkNames(node, data);
    70      }
    71
    72      private Object checkNames(ASTFieldDeclaration node, Object data) {
    73          ASTType childNodeType = (ASTType) node.jjtGetChild(0);
    74          String varType = "";
    75          if (childNodeType.jjtGetChild(0) instanceof ASTReferenceType ) {
    76              ASTReferenceType refType = ((ASTReferenceType) childNodeType.jjtGetChild(0));
    77  	    if ( refType.jjtGetChild(0) instanceof ASTClassOrInterfaceType ) {
    78  	    	varType = ((ASTClassOrInterfaceType)refType.jjtGetChild(0)).getImage();
    79  	    } else {
    80  	    	varType = "";
    81  	    }
    82  	} else if (childNodeType.jjtGetChild(0) instanceof ASTPrimitiveType) {
    83              varType = ((ASTPrimitiveType) childNodeType.jjtGetChild(0)).getImage();
    84          }
    85          if (varType != null && varType.length() > 0) {
    86              //Get the variable name
    87              ASTVariableDeclarator childNodeName = (ASTVariableDeclarator) node.jjtGetChild(1);
    88              ASTVariableDeclaratorId childNodeId = (ASTVariableDeclaratorId) childNodeName.jjtGetChild(0);
    89              String varName = childNodeId.getImage();
    90
    91              if (varName.equals("serialVersionUID") || (node.isFinal() && !node.isStatic() && !node.isInterfaceMember())) {
    92                  return data;
    93              }
    94
    95              // static finals (and interface fields, which are implicitly static and final) are
    96              // checked for uppercase
    97              if ((node.isStatic() && node.isFinal()) || (node.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTClassOrInterfaceDeclaration && ((ASTClassOrInterfaceDeclaration) node.jjtGetParent().jjtGetParent().jjtGetParent()).isInterface())) {
    98                  if (!varName.equals(varName.toUpperCase())) {
    99                      addViolationWithMessage(data, childNodeName, "Variables that are final and static should be in all caps.");
    100                 }
    101                 return data;
    102             }
    103
    104             String strippedVarName = null;
    105             if (node.isStatic()) {
    106                 strippedVarName = normalizeStaticVariableName(varName);
    107             } else {
    108                 strippedVarName = normalizeMemberVariableName(varName);
    109             }
    110
    111             if (strippedVarName.indexOf('_') >= 0) {
    112                 addViolationWithMessage(data, childNodeName, "Variables that are not final should not contain underscores (except for underscores in standard prefix/suffix).");
    113             }
    114             if (Character.isUpperCase(varName.charAt(0))) {
    115                 addViolationWithMessage(data, childNodeName, "Variables should start with a lowercase character");
    116             }
    117         }
    118         return data;
    119     }
    120
    121     private String normalizeMemberVariableName(String varName) {
    122         return stripSuffix(stripPrefix(varName, memberPrefixes), memberSuffixes);
    123     }
    124
    125     private String normalizeStaticVariableName(String varName) {
    126         return stripSuffix(stripPrefix(varName, staticPrefixes), staticSuffixes);
    127     }
    128
    129     private String stripSuffix(String varName, String[] suffix) {
    130         if (suffix != null) {
    131             for (int i = 0; i < suffix.length; i++) {
    132                 if (varName.endsWith(suffix[i])) {
    133                     varName = varName.substring(0, varName.length() - suffix[i].length());
    134                     break;
    135                 }
    136             }
    137         }
    138         return varName;
    139     }
    140
    141     private String stripPrefix(String varName, String[] prefix) {
    142         if (prefix == null) {
    143             return varName;
    144         }
    145         for (int i = 0; i < prefix.length; i++) {
    146             if (varName.startsWith(prefix[i])) {
    147                 return varName.substring(prefix[i].length());
    148             }
    149         }
    150         return varName;
    151     }
    152 }