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 }