pmd: Strings.InefficientStringBuffering: fixed bugs #1503099 and #3109408

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@7678 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Andreas Dangel
2012-05-31 18:22:48 +00:00
parent af59a4c38b
commit 2ec09b626a
3 changed files with 83 additions and 5 deletions

View File

@ -27,6 +27,8 @@ TODO - Release blockers - Must implement before this release can be finally fini
and pmd-java:typeof).
Fixed bug 1503099: InefficientStringBuffering bug false +
Fixed bug 3109408: String.InefficientStringBuffering false +
Fixed bug 3424397: Unable to parse
Fixed bug 3530124: pmd: parsing of generic method call with super fails
Fixed bug 3496028: pmd-4.2.6: MissingBreakInSwitch fails to report violation

View File

@ -12,14 +12,18 @@ import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType;
import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
/*
/**
* How this rule works:
* find additive expressions: +
* check that the addition is between anything other than two literals
@ -38,10 +42,14 @@ public class InefficientStringBufferingRule extends AbstractJavaRule {
}
int immediateLiterals = 0;
int immediateStringLiterals = 0;
List<ASTLiteral> nodes = node.findDescendantsOfType(ASTLiteral.class);
for (ASTLiteral literal: nodes) {
if (literal.getNthParent(3) instanceof ASTAdditiveExpression) {
immediateLiterals++;
if (literal.isStringLiteral()) {
immediateStringLiterals++;
}
}
if (literal.isIntLiteral() || literal.isFloatLiteral()) {
return data;
@ -62,6 +70,18 @@ public class InefficientStringBufferingRule extends AbstractJavaRule {
}
}
}
// if literal primitive type and not strings variables, then return
boolean stringFound = false;
for (ASTName name: nameNodes) {
if (!isPrimitiveType(name) && isStringType(name)) {
stringFound = true;
break;
}
}
if (!stringFound && immediateStringLiterals == 0) {
return data;
}
if (bs.isAllocation()) {
for (Iterator<ASTName> iterator = nameNodes.iterator(); iterator.hasNext();) {
@ -82,7 +102,43 @@ public class InefficientStringBufferingRule extends AbstractJavaRule {
return data;
}
protected static boolean isInStringBufferOperation(Node node, int length, String methodName) {
private boolean isStringType(ASTName name) {
ASTType type = getTypeNode(name);
if (type != null) {
List<ASTClassOrInterfaceType> types = type.findDescendantsOfType(ASTClassOrInterfaceType.class);
if (!types.isEmpty()) {
ASTClassOrInterfaceType typeDeclaration = types.get(0);
if (String.class == typeDeclaration.getType() || "String".equals(typeDeclaration.getImage())) {
return true;
}
}
}
return false;
}
private boolean isPrimitiveType(ASTName name) {
ASTType type = getTypeNode(name);
if (type != null && !type.findChildrenOfType(ASTPrimitiveType.class).isEmpty()) {
return true;
}
return false;
}
private ASTType getTypeNode(ASTName name) {
if (name.getNameDeclaration() instanceof VariableNameDeclaration) {
VariableNameDeclaration vnd = (VariableNameDeclaration) name.getNameDeclaration();
if (vnd.getAccessNodeParent() instanceof ASTLocalVariableDeclaration) {
ASTLocalVariableDeclaration l = (ASTLocalVariableDeclaration)vnd.getAccessNodeParent();
return l.getTypeNode();
} else if (vnd.getAccessNodeParent() instanceof ASTFormalParameter) {
ASTFormalParameter p = (ASTFormalParameter) vnd.getAccessNodeParent();
return p.getTypeNode();
}
}
return null;
}
protected static boolean isInStringBufferOperation(Node node, int length, String methodName) {
if (!(node.getNthParent(length) instanceof ASTStatementExpression)) {
return false;
}

View File

@ -332,18 +332,38 @@ public class Foo {
}
]]></code>
</test-code>
<!--test-code>
<test-code>
<description><![CDATA[
3109408, false + with adding two integers in constructor
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Test {
public void method() {
int initialSizeGlobal = (int) (profilingContext.m_profileItems.size() * (150.0 * 0.30));
int initialSizeDetail = s_profiling_details_enabled ? profilingContext.m_overallProfileItems.size() * 150 : 0;
StringBuilder sb = new StringBuilder(initialSizeGlobal + initialSizeDetail);
}
}
]]></code>
</test-code>
<test-code>
<description><![CDATA[
1503099, adding two integers
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public void bar(int a, int b) {
public void bar(int a, int b, long c, long d) {
StringBuffer buf = new StringBuffer();
buf.append(a + b);
buf.append(c - d);
String str1 = "a";
String str2 = "b";
StringBuffer sb = new StringBuffer(str1.length() + str2.length());
}
}
]]></code>
</test-code-->
</test-code>
</test-data>