View Javadoc

1   package net.sourceforge.pmd.lang.java.rule;
2   
3   import java.util.List;
4   
5   import net.sourceforge.pmd.lang.ast.Node;
6   import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
7   import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
8   import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType;
9   import net.sourceforge.pmd.lang.java.ast.ASTRelationalExpression;
10  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
11  import net.sourceforge.pmd.lang.java.symboltable.NameOccurrence;
12  
13  /**
14   * This is an abstract rule for patterns which compare a method invocation to 0.
15   * It could be further abstracted to find code that compares something to
16   * another definable pattern
17   * 
18   * @author acaplan
19   */
20  public abstract class AbstractInefficientZeroCheck extends AbstractJavaRule {
21  
22      public abstract boolean appliesToClassName(String name);
23  
24      public abstract boolean isTargetMethod(NameOccurrence occ);
25  
26      public Object visit(ASTVariableDeclaratorId node, Object data) {
27  	Node nameNode = node.getTypeNameNode();
28          if (nameNode instanceof ASTPrimitiveType) {
29              return data;
30          }
31          if (!appliesToClassName(node.getNameDeclaration().getTypeImage())) {
32              return data;
33          }
34  
35          List<NameOccurrence> declars = node.getUsages();
36          for (NameOccurrence occ: declars) {
37              if (!isTargetMethod(occ)) {
38                  continue;
39              }
40              Node expr = occ.getLocation().jjtGetParent().jjtGetParent().jjtGetParent();
41              if ((expr instanceof ASTEqualityExpression ||
42                      (expr instanceof ASTRelationalExpression && ">".equals(expr.getImage())))
43                  && isCompareZero(expr)) {
44                  addViolation(data, occ.getLocation());
45              }
46          }
47          return data;
48      }
49  
50      /**
51       * We only need to report if this is comparing against 0
52       * 
53       * @param equality
54       * @return true if this is comparing to 0 else false
55       */
56      private boolean isCompareZero(Node equality) {
57          return checkComparison(equality, 0) || checkComparison(equality, 1);
58  
59      }
60  
61      /**
62       * Checks if the equality expression passed in is of comparing against the
63       * value passed in as i
64       * 
65       * @param equality
66       * @param i
67       *            The ordinal in the equality expression to check
68       * @return true if the value in position i is 0, else false
69       */
70      private boolean checkComparison(Node equality, int i) {
71  	Node target = equality.jjtGetChild(i).jjtGetChild(0);
72          if (target.jjtGetNumChildren() == 0) {
73              return false;
74          }
75          target = target.jjtGetChild(0);
76          return target instanceof ASTLiteral && "0".equals(target.getImage());
77      }
78  
79  }