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 }
|