01: package net.sourceforge.pmd.rules;
02:
03: import net.sourceforge.pmd.AbstractRule;
04: import net.sourceforge.pmd.ast.ASTEqualityExpression;
05: import net.sourceforge.pmd.ast.ASTLiteral;
06: import net.sourceforge.pmd.ast.ASTPrimitiveType;
07: import net.sourceforge.pmd.ast.ASTRelationalExpression;
08: import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
09: 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()
33: .getTypeImage())) {
34: return data;
35: }
36:
37: List<NameOccurrence> declars = node.getUsages();
38: for (NameOccurrence occ : declars) {
39: if (!isTargetMethod(occ)) {
40: continue;
41: }
42: SimpleNode expr = (SimpleNode) occ.getLocation()
43: .jjtGetParent().jjtGetParent().jjtGetParent();
44: if ((expr instanceof ASTEqualityExpression || (expr instanceof ASTRelationalExpression && ">"
45: .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(
61: equality, 1));
62:
63: }
64:
65: /**
66: * Checks if the equality expression passed in is of comparing against the
67: * value passed in as i
68: *
69: * @param equality
70: * @param i
71: * The ordinal in the equality expression to check
72: * @return true if the value in position i is 0, else false
73: */
74: private boolean checkComparison(SimpleNode equality, int i) {
75: SimpleNode target = (SimpleNode) equality.jjtGetChild(i)
76: .jjtGetChild(0);
77: if (target.jjtGetNumChildren() == 0) {
78: return false;
79: }
80: target = (SimpleNode) target.jjtGetChild(0);
81: return (target instanceof ASTLiteral && "0".equals(target
82: .getImage()));
83: }
84:
85: }
|