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 net.sourceforge.pmd.AbstractRule;
7   import net.sourceforge.pmd.RuleContext;
8   import net.sourceforge.pmd.ast.ASTFieldDeclaration;
9   import net.sourceforge.pmd.ast.ASTInterfaceMemberDeclaration;
10  import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration;
11  import net.sourceforge.pmd.ast.ASTName;
12  import net.sourceforge.pmd.ast.ASTPrimitiveType;
13  import net.sourceforge.pmd.ast.ASTType;
14  import net.sourceforge.pmd.ast.ASTVariableDeclarator;
15  import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
16  import net.sourceforge.pmd.ast.AccessNode;
17  
18  public class VariableNamingConventionsRule extends AbstractRule {
19  
20    public Object visit(ASTLocalVariableDeclaration node, Object data) {
21      return checkNames(node, data);
22    }
23  
24    public Object visit(ASTFieldDeclaration node, Object data) {
25      return checkNames(node, data);
26    }
27  
28      public Object checkNames(AccessNode node, Object data) {
29          ASTType childNodeType = (ASTType)node.jjtGetChild(0);
30          String varType = "";
31          if (childNodeType.jjtGetChild(0)instanceof ASTName ) {
32              varType = ((ASTName)childNodeType.jjtGetChild(0)).getImage();
33          } else if (childNodeType.jjtGetChild(0) instanceof ASTPrimitiveType) {
34              varType = ((ASTPrimitiveType)childNodeType.jjtGetChild(0)).getImage();
35          }
36          if (varType != null && varType.length() > 0) {
37              //Get the variable name
38              ASTVariableDeclarator childNodeName = (ASTVariableDeclarator)node.jjtGetChild(1);
39              ASTVariableDeclaratorId childNodeId = (ASTVariableDeclaratorId)childNodeName.jjtGetChild(0);
40              String varName = childNodeId.getImage();
41  
42              if (varName.equals("serialVersionUID")) {
43                  return data;
44              }
45  
46              // non static final class fields are OK
47              if (node.isFinal() && !node.isStatic() && !(node.jjtGetParent() instanceof ASTInterfaceMemberDeclaration)) {
48                  return data;
49              }
50  
51              // final, non static, class, fields are OK
52              if (node.isFinal() && !node.isStatic() && !(node.jjtGetParent() instanceof ASTInterfaceMemberDeclaration)) {
53                  return data;
54              }
55  
56              // static finals (and interface fields, which are implicitly static and final) are checked for uppercase
57              if ((node.isStatic() && node.isFinal()) || node.jjtGetParent() instanceof ASTInterfaceMemberDeclaration) {
58                  if (!varName.equals(varName.toUpperCase())) {
59                      RuleContext ctx = (RuleContext)data;
60                      ctx.getReport().addRuleViolation(createRuleViolation(ctx, childNodeName.getBeginLine(), "Variables that are final and static should be in all caps."));
61                  }
62                  return data;
63              }
64  
65              // if
66              if (varName.indexOf("_") >= 0) {
67                  RuleContext ctx = (RuleContext)data;
68                  ctx.getReport().addRuleViolation(createRuleViolation(ctx, childNodeName.getBeginLine(), "Variables that are not final should not contain underscores."));
69              }
70              if (Character.isUpperCase(varName.charAt(0))) {
71                  RuleContext ctx = (RuleContext)data;
72                  ctx.getReport().addRuleViolation(createRuleViolation(ctx, childNodeName.getBeginLine(), "Variables should start with a lowercase character"));
73              }
74          }
75          return data;
76      }
77  }