Clover coverage report - PMD - 3.9
Coverage timestamp: Tue Dec 19 2006 09:38:44 EST
file stats: LOC: 67   Methods: 2
NCLOC: 40   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
UselessOperationOnImmutable.java 100% 100% 100% 100%
coverage
 1    package net.sourceforge.pmd.rules;
 2   
 3    import java.util.Iterator;
 4    import java.util.Set;
 5   
 6    import net.sourceforge.pmd.AbstractRule;
 7    import net.sourceforge.pmd.ast.ASTExpression;
 8    import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration;
 9    import net.sourceforge.pmd.ast.ASTName;
 10    import net.sourceforge.pmd.ast.ASTType;
 11    import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
 12    import net.sourceforge.pmd.symboltable.NameOccurrence;
 13    import net.sourceforge.pmd.util.CollectionUtil;
 14   
 15    /**
 16    * An operation on an Immutable object (BigDecimal or BigInteger) won't change
 17    * the object itself. The result of the operation is a new object. Therefore,
 18    * ignoring the operation result is an error.
 19    */
 20    public class UselessOperationOnImmutable extends AbstractRule {
 21   
 22    /**
 23    * These are the methods which are immutable
 24    */
 25    private static final Set targetMethods = CollectionUtil.asSet(new String[] { ".add", ".multiply", ".divide", ".subtract", ".setScale", ".negate", ".movePointLeft", ".movePointRight", ".pow", ".shiftLeft", ".shiftRight" });
 26   
 27    /**
 28    * These are the classes that the rule can apply to
 29    */
 30    private static final Set targetClasses = CollectionUtil.asSet(new String[] { "java.math.BigDecimal", "BigDecimal", "java.math.BigInteger", "BigInteger" });
 31   
 32  6 public Object visit(ASTLocalVariableDeclaration node, Object data) {
 33   
 34  6 ASTVariableDeclaratorId var = getDeclaration(node);
 35  6 if (var == null) {
 36  2 return super.visit(node, data);
 37    }
 38  4 String variableName = var.getImage();
 39  4 for (Iterator it = var.getUsages().iterator(); it.hasNext();) {
 40  5 NameOccurrence no = (NameOccurrence) it.next();
 41  5 ASTName sn = (ASTName) no.getLocation();
 42  5 if (!sn.jjtGetParent().jjtGetParent().jjtGetParent().getClass().equals(ASTExpression.class)) {
 43  3 String methodCall = sn.getImage().substring(variableName.length());
 44  3 if (targetMethods.contains(methodCall)) {
 45  2 addViolation(data, sn);
 46    }
 47    }
 48    }
 49  4 return super.visit(node, data);
 50    }
 51   
 52    /**
 53    * This method checks the variable declaration if it is on a class we care
 54    * about. If it is, it returns the DeclaratorId
 55    *
 56    * @param node
 57    * The ASTLocalVariableDeclaration which is a problem
 58    * @return ASTVariableDeclaratorId
 59    */
 60  6 private ASTVariableDeclaratorId getDeclaration(ASTLocalVariableDeclaration node) {
 61  6 ASTType type = node.getTypeNode();
 62  6 if (targetClasses.contains(type.getTypeImage())) {
 63  4 return (ASTVariableDeclaratorId) node.jjtGetChild(1).jjtGetChild(0);
 64    }
 65  2 return null;
 66    }
 67    }