Applying patch [ 1966013 ] Missing cases in UselessOperationOnImmutable

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/branches/pmd/4.2.x@6197 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Romain Pelisse
2008-06-13 20:36:32 +00:00
parent b287a5a73c
commit 79a84939c5
4 changed files with 54 additions and 14 deletions

View File

@ -2,9 +2,11 @@
Fixes for exclude-pattern Fixes for exclude-pattern
Updates to RuleChain to honor RuleSet exclude-pattern Updates to RuleChain to honor RuleSet exclude-pattern
Upgrading UselessOperationOnImmutable to detect more use cases, especially on String
Fixed bug 1988829 - Violation reported without source file name (actually a fix to ConsecutiveLiteralAppends) Fixed bug 1988829 - Violation reported without source file name (actually a fix to ConsecutiveLiteralAppends)
Fixed bug 1989814 - false +: ConsecutiveLiteralAppends Fixed bug 1989814 - false +: ConsecutiveLiteralAppends
May 20, 2008 - 4.2.2: May 20, 2008 - 4.2.2:
Fixed false positive in UnusedImports: javadoc comments are parsed to check @see and other tags Fixed false positive in UnusedImports: javadoc comments are parsed to check @see and other tags

View File

@ -10,7 +10,7 @@ useless operation on BigDecimal
public class Foo { public class Foo {
public void foo() { public void foo() {
BigDecimal bd = new BigDecimal(5); BigDecimal bd = new BigDecimal(5);
bd.add(new BigDecimal(5)); bd.divideToIntegralValue(new BigDecimal(5));
} }
} }
]]></code> ]]></code>
@ -24,7 +24,7 @@ useless operation on BigInteger
public class Foo { public class Foo {
public void foo() { public void foo() {
BigInteger bi = new BigInteger(5); BigInteger bi = new BigInteger(5);
bi.add(new BigInteger(5)); bi.modPow(new BigInteger(1), new BigInteger(5));
} }
} }
]]></code> ]]></code>

View File

@ -789,11 +789,11 @@ public class Test {
<rule name="UselessOperationOnImmutable" <rule name="UselessOperationOnImmutable"
since="3.5" since="3.5"
message="An operation on an Immutable object (BigDecimal or BigInteger) won't change the object itself" message="An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself"
class="net.sourceforge.pmd.rules.UselessOperationOnImmutable" class="net.sourceforge.pmd.rules.UselessOperationOnImmutable"
externalInfoUrl="http://pmd.sourceforge.net/rules/basic.html#UselessOperationOnImmutable"> externalInfoUrl="http://pmd.sourceforge.net/rules/basic.html#UselessOperationOnImmutable">
<description> <description>
An operation on an Immutable object (BigDecimal or BigInteger) won't change the object itself. The An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself. The
result of the operation is a new object. Therefore, ignoring the operation result is an error. result of the operation is a new object. Therefore, ignoring the operation result is an error.
</description> </description>
<priority>3</priority> <priority>3</priority>

View File

@ -1,9 +1,12 @@
package net.sourceforge.pmd.rules; package net.sourceforge.pmd.rules;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import net.sourceforge.pmd.AbstractJavaRule;
import net.sourceforge.pmd.AbstractRule; import net.sourceforge.pmd.AbstractRule;
import net.sourceforge.pmd.ast.ASTConditionalExpression; import net.sourceforge.pmd.ast.ASTConditionalExpression;
import net.sourceforge.pmd.ast.ASTExpression; import net.sourceforge.pmd.ast.ASTExpression;
@ -18,21 +21,40 @@ import net.sourceforge.pmd.symboltable.NameOccurrence;
import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.CollectionUtil;
/** /**
* An operation on an Immutable object (BigDecimal or BigInteger) won't change * An operation on an Immutable object (String, BigDecimal or BigInteger) won't change
* the object itself. The result of the operation is a new object. Therefore, * the object itself. The result of the operation is a new object. Therefore,
* ignoring the operation result is an error. * ignoring the operation result is an error.
*/ */
public class UselessOperationOnImmutable extends AbstractRule { public class UselessOperationOnImmutable extends AbstractJavaRule {
/** /**
* These are the methods which are immutable * These are the BigDecimal methods which are immutable
*/ */
private static final Set<String> targetMethods = CollectionUtil.asSet(new String[] { ".add", ".multiply", ".divide", ".subtract", ".setScale", ".negate", ".movePointLeft", ".movePointRight", ".pow", ".shiftLeft", ".shiftRight" }); private static final Set<String> decMethods = CollectionUtil.asSet(new String[] { ".abs", ".add", ".divide", ".divideToIntegralValue", ".max", ".min", ".movePointLeft", ".movePointRight", ".multiply", ".negate", ".plus", ".pow", ".remainder", ".round", ".scaleByPowerOfTen", ".setScale", ".stripTrailingZeros", ".subtract", ".ulp" });
/**
* These are the BigInteger methods which are immutable
*/
private static final Set<String> intMethods = CollectionUtil.asSet(new String[] { ".abs", ".add", ".and", ".andNot", ".clearBit", ".divide", ".flipBit", ".gcd", ".max", ".min", ".mod", ".modInverse", ".modPow", ".multiply", ".negate", ".nextProbablePrine", ".not", ".or", ".pow", ".remainder", ".setBit", ".shiftLeft", ".shiftRight", ".subtract", ".xor" });
/**
* These are the String methods which are immutable
*/
private static final Set<String> strMethods = CollectionUtil.asSet(new String[] { ".concat", ".intern", ".replace", ".replaceAll", ".replaceFirst", ".substring", ".toLowerCase", ".toString", ".toUpperCase", ".trim" });
/** /**
* These are the classes that the rule can apply to * These are the classes that the rule can apply to
*/ */
private static final Set<String> targetClasses = CollectionUtil.asSet(new String[] { "java.math.BigDecimal", "BigDecimal", "java.math.BigInteger", "BigInteger" }); private static final Map<String, Set<String>> mapClasses = new HashMap<String, Set<String>>();
static {
mapClasses.put("java.math.BigDecimal", decMethods);
mapClasses.put("BigDecimal", decMethods);
mapClasses.put("java.math.BigInteger", intMethods);
mapClasses.put("BigInteger", intMethods);
mapClasses.put("java.lang.String", strMethods);
mapClasses.put("String", strMethods);
}
public Object visit(ASTLocalVariableDeclaration node, Object data) { public Object visit(ASTLocalVariableDeclaration node, Object data) {
ASTVariableDeclaratorId var = getDeclaration(node); ASTVariableDeclaratorId var = getDeclaration(node);
@ -49,7 +71,7 @@ public class UselessOperationOnImmutable extends AbstractRule {
if (!(parentClass.equals(ASTExpression.class) || parentClass.equals(ASTConditionalExpression.class) || if (!(parentClass.equals(ASTExpression.class) || parentClass.equals(ASTConditionalExpression.class) ||
hasComparisons(primaryExpression))) { hasComparisons(primaryExpression))) {
String methodCall = sn.getImage().substring(variableName.length()); String methodCall = sn.getImage().substring(variableName.length());
if (targetMethods.contains(methodCall)) { if (mapClasses.get(getType(node)).contains(methodCall)) {
addViolation(data, sn); addViolation(data, sn);
} }
} }
@ -83,10 +105,26 @@ public class UselessOperationOnImmutable extends AbstractRule {
* @return ASTVariableDeclaratorId * @return ASTVariableDeclaratorId
*/ */
private ASTVariableDeclaratorId getDeclaration(ASTLocalVariableDeclaration node) { private ASTVariableDeclaratorId getDeclaration(ASTLocalVariableDeclaration node) {
ASTType type = node.getTypeNode(); String type = getType(node);
if (targetClasses.contains(type.getTypeImage())) { if (mapClasses.keySet().contains(type)) {
return (ASTVariableDeclaratorId) node.jjtGetChild(1).jjtGetChild(0); return (ASTVariableDeclaratorId) node.jjtGetChild(1).jjtGetChild(0);
} }
return null; return null;
} }
/**
* This method returns the name of the node's class.
*
* @param node
* The ASTLocalVariableDeclaration which is a problem
* @return the class name
*/
private static String getType(ASTLocalVariableDeclaration node) {
ASTType type = node.getTypeNode();
if (type != null) {
return type.getTypeImage();
}
return null;
}
} }