View Javadoc

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