AbstractInefficientZeroCheck.java
01 package net.sourceforge.pmd.lang.java.rule;
02 
03 import java.util.List;
04 
05 import net.sourceforge.pmd.lang.ast.Node;
06 import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
07 import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
08 import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType;
09 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 }