fix false positives in UselessOperationOnImmutable

false positives included string were used in expressions and BigInteger
as method arguments. The immutable object is ignored only if expression's
parent is a statement expression.


git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@6227 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Xavier Le Vourch committed 2008-06-18 00:43:51 +00:00
1 parent 116ea27f09
commit 0b5403dd51
3 files changed
+42 -31

No files matched your search

+1 -1
View File
@@ -299,7 +299,7 @@ bin and java14/bin scripts:
retroweaver version was not correct in java14/bin scripts
support for extra languages in cpd.sh
standard unix scripts can be used with cygwin
Upgrading UselessOperationOnImmutable to detect more use cases, especially on String
Upgrading UselessOperationOnImmutable to detect more use cases, especially on String and fix false positives
AvoidDuplicateLiteralRule now has 'skipAnnotations' boolean property
Fixed false positive in UnusedImports: javadoc comments are parsed to check @see and other tags
Fixed parsing bug: constant fields in annotation classes
@@ -129,4 +129,37 @@ public class RuleViolator {
}
]]></code>
</test-code>
<test-code>
<description><![CDATA[
String calls in expressions
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public void foo() {
String s;
String s2 = "foo" + s.substring( 0, delimiterIndex ) + "/";
s2 = "foo" + s.substring( 0, delimiterIndex );
if (s.trim().length() > 0) {
}
}
}
]]></code>
</test-code>
<test-code>
<description><![CDATA[
BigInteger calls in expression
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public void foo() {
BigInteger temp = BigInteger.valueOf((long) startMonth).add(dMonths);
setMonth(temp.subtract(BigInteger.ONE).mod(TWELVE).intValue() + 1);
}
}
]]></code>
</test-code>
</test-data>
@@ -1,17 +1,12 @@
package net.sourceforge.pmd.lang.java.rule.basic;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
@@ -24,12 +19,12 @@ import net.sourceforge.pmd.util.CollectionUtil;
* ignoring the operation result is an error.
*/
public class UselessOperationOnImmutableRule extends AbstractJavaRule {
/**
* These are the BigDecimal methods which are immutable
*/
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
*/
@@ -53,6 +48,7 @@ public class UselessOperationOnImmutableRule extends AbstractJavaRule {
mapClasses.put("String", strMethods);
}
@Override
public Object visit(ASTLocalVariableDeclaration node, Object data) {
ASTVariableDeclaratorId var = getDeclaration(node);
@@ -61,13 +57,12 @@ public class UselessOperationOnImmutableRule extends AbstractJavaRule {
}
String variableName = var.getImage();
for (NameOccurrence no: var.getUsages()) {
// FIXME - getUsages will return everything with the same name as the variable,
// FIXME - getUsages will return everything with the same name as the variable,
// see JUnit test, case 6. Changing to Node below, revisit when getUsages is fixed
Node sn = no.getLocation();
Node primaryExpression = sn.jjtGetParent().jjtGetParent();
Class<? extends Node> parentClass = primaryExpression.jjtGetParent().getClass();
if (!(parentClass.equals(ASTExpression.class) || parentClass.equals(ASTConditionalExpression.class) ||
hasComparisons(primaryExpression))) {
Class<? extends Node> parentClass = primaryExpression.jjtGetParent().getClass();
if (parentClass.equals(ASTStatementExpression.class)) {
String methodCall = sn.getImage().substring(variableName.length());
ASTType nodeType = node.getTypeNode();
if ( nodeType != null ) {
@@ -80,27 +75,10 @@ public class UselessOperationOnImmutableRule extends AbstractJavaRule {
return super.visit(node, data);
}
/**
* Check whether the Immutable is compareTo'd something
*/
private boolean hasComparisons(Node primaryExpression) {
if (primaryExpression.getClass().equals(ASTPrimaryExpression.class)) {
List<ASTPrimarySuffix> suffixes = ((ASTPrimaryExpression)primaryExpression).findChildrenOfType(ASTPrimarySuffix.class);
for (Iterator<ASTPrimarySuffix> iterator = suffixes.iterator(); iterator.hasNext();) {
ASTPrimarySuffix suffix = iterator.next();
if ("compareTo".equals(suffix.getImage()))
return true;
}
} else {
//Some weird usage of the Immutable
}
return false; //No comparison
}
/**
* This method checks the variable declaration if it is on a class we care
* about. If it is, it returns the DeclaratorId
*
*
* @param node
* The ASTLocalVariableDeclaration which is a problem
* @return ASTVariableDeclaratorId