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 public Object visit(ASTLocalVariableDeclaration node, Object data) { 33 34 ASTVariableDeclaratorId var = getDeclaration(node); 35 if (var == null) { 36 return super.visit(node, data); 37 } 38 String variableName = var.getImage(); 39 for (Iterator it = var.getUsages().iterator(); it.hasNext();) { 40 NameOccurrence no = (NameOccurrence) it.next(); 41 ASTName sn = (ASTName) no.getLocation(); 42 if (!sn.jjtGetParent().jjtGetParent().jjtGetParent().getClass().equals(ASTExpression.class)) { 43 String methodCall = sn.getImage().substring(variableName.length()); 44 if (targetMethods.contains(methodCall)) { 45 addViolation(data, sn); 46 } 47 } 48 } 49 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 private ASTVariableDeclaratorId getDeclaration(ASTLocalVariableDeclaration node) { 61 ASTType type = node.getTypeNode(); 62 if (targetClasses.contains(type.getTypeImage())) { 63 return (ASTVariableDeclaratorId) node.jjtGetChild(1).jjtGetChild(0); 64 } 65 return null; 66 } 67 }