Clover coverage report - PMD - 3.7
Coverage timestamp: Wed May 31 2006 09:25:59 EDT
file stats: LOC: 103   Methods: 4
NCLOC: 55   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
InefficientEmptyStringCheck.java 92.9% 95.2% 100% 94.9%
coverage coverage
 1    package net.sourceforge.pmd.rules.strings;
 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.ASTVariableDeclaratorId;
 8    import net.sourceforge.pmd.ast.Node;
 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 rule finds code which inefficiently determines empty strings. This code
 17    * <p/>
 18    * <pre>
 19    * if(str.trim().length()==0){....
 20    * </pre>
 21    * <p/>
 22    * is quite inefficient as trim() causes a new String to be created. Smarter
 23    * code to check for an empty string would be:
 24    * <p/>
 25    * <pre>
 26    * Character.isWhitespace(str.charAt(i));
 27    * </pre>
 28    *
 29    * @author acaplan
 30    */
 31    public class InefficientEmptyStringCheck extends AbstractRule {
 32   
 33  14 public Object visit(ASTVariableDeclaratorId node, Object data) {
 34  14 SimpleNode nameNode = node.getTypeNameNode();
 35  14 if (nameNode instanceof ASTPrimitiveType) {
 36  5 return data;
 37    }
 38   
 39  9 if (!"String".equals(node.getNameDeclaration().getTypeImage())) {
 40  0 return data;
 41    }
 42   
 43  9 List declars = node.getUsages();
 44  9 for (Iterator i = declars.iterator(); i.hasNext();) {
 45  9 NameOccurrence occ = (NameOccurrence) i.next();
 46  9 if (!isStringLength(occ)) {
 47  2 continue;
 48    }
 49  7 ASTEqualityExpression equality = (ASTEqualityExpression) occ
 50    .getLocation().getFirstParentOfType(ASTEqualityExpression.class);
 51  7 if (equality != null && isCompareZero(equality)) {
 52  3 addViolation(data, occ.getLocation());
 53    }
 54    }
 55  9 return data;
 56    }
 57   
 58    /**
 59    * We only need to report if this is comparing against 0
 60    *
 61    * @param equality
 62    * @return true if this is comparing to 0 else false
 63    */
 64  5 private boolean isCompareZero(ASTEqualityExpression equality) {
 65  5 return (checkComparison(equality, 0) || checkComparison(equality, 1));
 66   
 67    }
 68   
 69    /**
 70    * Determine if we're dealing with String.length method
 71    *
 72    * @param occ The name occurance
 73    * @return true if it's String.length, else false
 74    */
 75  9 private boolean isStringLength(NameOccurrence occ) {
 76  9 if (occ.getNameForWhichThisIsAQualifier() != null
 77    && occ.getNameForWhichThisIsAQualifier().getImage().indexOf("trim") != -1) {
 78  8 Node pExpression = occ.getLocation().jjtGetParent().jjtGetParent();
 79  8 if (pExpression.jjtGetNumChildren() >= 3
 80    && "length"
 81    .equals(((SimpleNode) pExpression.jjtGetChild(2))
 82    .getImage())) {
 83  7 return true;
 84    }
 85    }
 86  2 return false;
 87    }
 88   
 89    /**
 90    * Checks if the equality expression passed in is of comparing against the
 91    * value passed in as i
 92    *
 93    * @param equality
 94    * @param i The ordinal in the equality expression to check
 95    * @return true if the value in position i is 0, else false
 96    */
 97  10 private boolean checkComparison(ASTEqualityExpression equality, int i) {
 98  10 return (equality.jjtGetChild(i).jjtGetChild(0).jjtGetChild(0) instanceof ASTLiteral && "0"
 99    .equals(((SimpleNode) equality.jjtGetChild(i).jjtGetChild(0)
 100    .jjtGetChild(0)).getImage()));
 101    }
 102   
 103    }