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