View Javadoc

1   /***
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.rules.design;
5   
6   import net.sourceforge.pmd.AbstractRule;
7   import net.sourceforge.pmd.ast.ASTAssignmentOperator;
8   import net.sourceforge.pmd.ast.ASTConditionalExpression;
9   import net.sourceforge.pmd.ast.ASTEqualityExpression;
10  import net.sourceforge.pmd.ast.ASTName;
11  import net.sourceforge.pmd.ast.ASTNullLiteral;
12  import net.sourceforge.pmd.ast.ASTStatementExpression;
13  import net.sourceforge.pmd.ast.Node;
14  import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
15  
16  import java.util.Iterator;
17  import java.util.Map;
18  
19  // Would this be simplified by using DFA somehow?
20  public class NullAssignmentRule extends AbstractRule {
21  
22      public Object visit(ASTNullLiteral node, Object data) {
23          if (get5thParent(node) instanceof ASTStatementExpression) {
24              ASTStatementExpression n = (ASTStatementExpression)get5thParent(node);
25  
26              if (isAssignmentToFinalField(n)) {
27                  return data;
28              }
29  
30              if (n.jjtGetNumChildren() > 2 && n.jjtGetChild(1) instanceof ASTAssignmentOperator) {
31                  addViolation(data, node);
32              }
33          } else if (get4thParent(node) instanceof ASTConditionalExpression) {
34              checkTernary((ASTConditionalExpression)get4thParent(node), data, node);
35          } else if (get5thParent(node) instanceof ASTConditionalExpression) {
36              checkTernary((ASTConditionalExpression)get5thParent(node), data, node);
37          }
38  
39          return data;
40      }
41  
42      private boolean isAssignmentToFinalField(ASTStatementExpression n) {
43          ASTName name = (ASTName)n.getFirstChildOfType(ASTName.class);
44          if (name != null) {
45              Map vars = name.getScope().getEnclosingClassScope().getVariableDeclarations();
46              for (Iterator i = vars.keySet().iterator(); i.hasNext();) {
47                  VariableNameDeclaration vnd = (VariableNameDeclaration)i.next();
48                  if (vnd.getImage().equals(name.getImage()) && vnd.getAccessNodeParent().isFinal()) {
49                      return true;
50                  }
51              }
52          }
53          return false;
54      }
55  
56      private Node get4thParent(ASTNullLiteral node) {
57          return node.jjtGetParent().jjtGetParent().jjtGetParent().jjtGetParent();
58      }
59  
60      private Node get5thParent(ASTNullLiteral node) {
61          return get4thParent(node).jjtGetParent();
62      }
63  
64      private void checkTernary(ASTConditionalExpression n, Object data, ASTNullLiteral node) {
65          if (n.isTernary() && !(n.jjtGetChild(0) instanceof ASTEqualityExpression)) {
66              addViolation(data, node);
67          }
68      }
69  }