Clover coverage report - PMD - 3.9
Coverage timestamp: Tue Dec 19 2006 09:38:44 EST
file stats: LOC: 120   Methods: 3
NCLOC: 52   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AbstractPoorMethodCall.java 75% 88% 100% 83.3%
coverage coverage
 1    package net.sourceforge.pmd.rules;
 2   
 3    import net.sourceforge.pmd.AbstractRule;
 4    import net.sourceforge.pmd.ast.ASTAdditiveExpression;
 5    import net.sourceforge.pmd.ast.ASTLiteral;
 6    import net.sourceforge.pmd.ast.ASTPrimaryExpression;
 7    import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
 8    import net.sourceforge.pmd.ast.SimpleNode;
 9    import net.sourceforge.pmd.symboltable.NameOccurrence;
 10   
 11    import java.util.Iterator;
 12    import java.util.List;
 13   
 14    /**
 15    * Detects and flags the occurrences of specific method calls against an instance of
 16    * a designated class. I.e. String.indexOf. The goal is to be able to suggest more
 17    * efficient/modern ways of implementing the same function.
 18    *
 19    * Concrete subclasses are expected to provide the name of the target class and an
 20    * array of method names that we are looking for. We then pass judgement on any literal
 21    * arguments we find in the subclass as well.
 22    *
 23    * @author Brian Remedios
 24    * @version $Revision: 1.1 $
 25    */
 26    public abstract class AbstractPoorMethodCall extends AbstractRule {
 27   
 28   
 29    /**
 30    * The name of the type the method will be invoked against.
 31    * @return String
 32    */
 33    protected abstract String targetTypename();
 34   
 35    /**
 36    * Return the names of all the methods we are scanning for, no brackets or
 37    * argument types.
 38    *
 39    * @return String[]
 40    */
 41    protected abstract String[] methodNames();
 42   
 43    /**
 44    * Returns whether the string argument at the stated position being sent to
 45    * the method is ok or not. Return true if you want to record the method call
 46    * as a violation, false otherwise.
 47    *
 48    * @param argIndex int
 49    * @param arg String
 50    * @return boolean
 51    */
 52    protected abstract boolean isViolationArgument(int argIndex, String arg);
 53   
 54    /**
 55    * Returns whether the name occurrence is one of the method calls
 56    * we are interested in.
 57    *
 58    * @param occurrence NameOccurrence
 59    * @return boolean
 60    */
 61  6 private boolean isNotedMethod(NameOccurrence occurrence) {
 62   
 63  0 if (occurrence == null) return false;
 64   
 65  6 String methodCall = occurrence.getImage();
 66  6 String[] methodNames = methodNames();
 67   
 68  7 for (int i=0; i<methodNames.length; i++) {
 69  6 if (methodCall.indexOf(methodNames[i]) != -1) return true;
 70    }
 71  0 return false;
 72    }
 73   
 74    /**
 75    * Returns whether the value argument is a single character string.
 76    *
 77    * @param value String
 78    * @return boolean
 79    */
 80  7 public static boolean isSingleCharAsString(String value) {
 81  7 return value.length() == 3 && value.charAt(0) == '\"';
 82    }
 83   
 84    /**
 85    * Method visit.
 86    * @param node ASTVariableDeclaratorId
 87    * @param data Object
 88    * @return Object
 89    * @see net.sourceforge.pmd.ast.JavaParserVisitor#visit(ASTVariableDeclaratorId, Object)
 90    */
 91  6 public Object visit(ASTVariableDeclaratorId node, Object data) {
 92   
 93  6 if (!node.getNameDeclaration().getTypeImage().equals(targetTypename())) {
 94  0 return data;
 95    }
 96   
 97  6 for (Iterator i = node.getUsages().iterator(); i.hasNext();) {
 98  6 NameOccurrence occ = (NameOccurrence) i.next();
 99  6 if (isNotedMethod(occ.getNameForWhichThisIsAQualifier())) {
 100  6 SimpleNode parent = (SimpleNode)occ.getLocation().jjtGetParent().jjtGetParent();
 101  6 if (parent instanceof ASTPrimaryExpression) {
 102    // bail out if it's something like indexOf("a" + "b")
 103  6 List additives = parent.findChildrenOfType(ASTAdditiveExpression.class);
 104  6 if (!additives.isEmpty()) {
 105  1 return data;
 106    }
 107  5 List literals = parent.findChildrenOfType(ASTLiteral.class);
 108  5 for (int l=0; l<literals.size(); l++) {
 109  7 ASTLiteral literal = (ASTLiteral)literals.get(l);
 110  7 if (isViolationArgument(l, literal.getImage())) {
 111  3 addViolation(data, occ.getLocation());
 112    }
 113    }
 114    }
 115    }
 116    }
 117  5 return data;
 118    }
 119    }
 120