[java] StringInstatiation: False negative with String-array access

Fixes #2141
This commit is contained in:
Andreas Dangel
2019-12-06 11:18:27 +01:00
parent b1fc3110de
commit 3b6fcf4b7a
3 changed files with 61 additions and 2 deletions

View File

@ -6,19 +6,30 @@ package net.sourceforge.pmd.lang.java.rule.performance;
import java.util.List;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAdditiveExpression;
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
import net.sourceforge.pmd.lang.java.ast.ASTArguments;
import net.sourceforge.pmd.lang.java.ast.ASTArrayDimsAndInits;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.java.symboltable.TypedNameDeclaration;
import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
public class StringInstantiationRule extends AbstractJavaRule {
public StringInstantiationRule() {
addRuleChainVisit(ASTAllocationExpression.class);
}
@Override
public Object visit(ASTAllocationExpression node, Object data) {
if (!(node.jjtGetChild(0) instanceof ASTClassOrInterfaceType)) {
@ -29,8 +40,9 @@ public class StringInstantiationRule extends AbstractJavaRule {
return data;
}
boolean arrayAccess = isArrayAccess(node);
List<ASTExpression> exp = node.findDescendantsOfType(ASTExpression.class);
if (exp.size() >= 2) {
if (exp.size() >= 2 && !arrayAccess) {
return data;
}
@ -50,9 +62,37 @@ public class StringInstantiationRule extends AbstractJavaRule {
return data;
}
if (nd instanceof TypedNameDeclaration && TypeHelper.isExactlyAny((TypedNameDeclaration) nd, String.class)) {
if (nd instanceof TypedNameDeclaration && TypeHelper.isExactlyAny((TypedNameDeclaration) nd, String.class) || arrayAccess) {
addViolation(data, node);
}
return data;
}
private boolean isArrayAccess(ASTAllocationExpression node) {
ASTArguments arguments = node.getFirstChildOfType(ASTArguments.class);
if (arguments == null || arguments.getArgumentCount() != 1) {
return false;
}
Node firstArg = arguments.getFirstChildOfType(ASTArgumentList.class).jjtGetChild(0);
ASTPrimaryExpression primary = firstArg.getFirstChildOfType(ASTPrimaryExpression.class);
if (primary == null) {
return false;
}
ASTPrimaryPrefix prefix = primary.getFirstChildOfType(ASTPrimaryPrefix.class);
if (prefix == null || !isStringArrayTypeDefinition(prefix.getTypeDefinition())) {
return false;
}
ASTPrimarySuffix suffix = primary.getFirstChildOfType(ASTPrimarySuffix.class);
return suffix != null && suffix.isArrayDereference();
}
private boolean isStringArrayTypeDefinition(JavaTypeDefinition typeDefinition) {
if (typeDefinition == null || !typeDefinition.isArrayType() || typeDefinition.getElementType() == null) {
return false;
}
return typeDefinition.getElementType().getType() == String.class;
}
}

View File

@ -99,4 +99,20 @@ public class Foo {
}
]]></code>
</test-code>
<test-code>
<description>#2141 [java] StringInstatiation: False negative with String-array access</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<code><![CDATA[
public class Foo {
public void bar() {
String[] arr = getArray();
String s = new String(arr[0]);
// better
String s2 = arr[0];
}
}
]]></code>
</test-code>
</test-data>