Handle [string literal].equals() correctly in EqualsAvoidNullRule

This fixes https://github.com/alibaba/p3c/issues/471

Previously, the following code can't pass EqualsAvoidNullRule:

public class Test {
  private static final String VERSION = System.getProperty("v");
  public boolean isJava6(){
    return "1.6".equals(VERSION);
  }
}

This PR fixes this issue by checking if the caller is a literal.
This commit is contained in:
Bo Zhang
2019-03-15 05:56:12 +08:00
committed by Feng Wei
parent 3cf2594292
commit 1dc88f5b49
2 changed files with 51 additions and 0 deletions

View File

@@ -26,6 +26,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTLiteral; import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
import net.sourceforge.pmd.lang.java.ast.ASTName; 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.ASTPrimaryPrefix;
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
import net.sourceforge.pmd.lang.java.ast.AbstractJavaNode; import net.sourceforge.pmd.lang.java.ast.AbstractJavaNode;
@@ -61,6 +62,11 @@ public class EqualsAvoidNullRule extends AbstractAliRule {
return super.visit(node, data); return super.visit(node, data);
} }
for (Node invocation : equalsInvocations) { for (Node invocation : equalsInvocations) {
// https://github.com/alibaba/p3c/issues/471
if (callerIsLiteral(invocation)) {
return super.visit(node, data);
}
// if arguments of equals is complicate expression, skip the check // if arguments of equals is complicate expression, skip the check
List<? extends Node> simpleExpressions = invocation.findChildNodesWithXPath(INVOCATION_PREFIX_XPATH); List<? extends Node> simpleExpressions = invocation.findChildNodesWithXPath(INVOCATION_PREFIX_XPATH);
if (simpleExpressions == null || simpleExpressions.isEmpty()) { if (simpleExpressions == null || simpleExpressions.isEmpty()) {
@@ -98,6 +104,14 @@ public class EqualsAvoidNullRule extends AbstractAliRule {
return super.visit(node, data); return super.visit(node, data);
} }
private boolean callerIsLiteral(Node equalsInvocation) {
if (equalsInvocation instanceof ASTPrimaryExpression) {
ASTPrimaryPrefix caller = equalsInvocation.getFirstChildOfType(ASTPrimaryPrefix.class);
return caller != null && caller.getFirstChildOfType(ASTLiteral.class) != null;
}
return false;
}
private String getInvocationName(AbstractJavaNode javaNode) { private String getInvocationName(AbstractJavaNode javaNode) {
Token token = (Token)javaNode.jjtGetFirstToken(); Token token = (Token)javaNode.jjtGetFirstToken();
StringBuilder sb = new StringBuilder(token.image).append(token.image); StringBuilder sb = new StringBuilder(token.image).append(token.image);

View File

@@ -129,4 +129,41 @@
<expected-problems>0</expected-problems> <expected-problems>0</expected-problems>
<code-ref id="caller-is-constant" /> <code-ref id="caller-is-constant" />
</test-code> </test-code>
<!-- ====================================================================== -->
<code-fragment id="string-literal-equals-constant">
<![CDATA[
public class Test {
private static final String VERSION = System.getProperty("v");
public boolean isJava6(){
return "1.6".equals(VERSION);
}
}
]]>
</code-fragment>
<test-code>
<description>string literal equals constant</description>
<expected-problems>0</expected-problems>
<code-ref id="string-literal-equals-constant" />
</test-code>
<!-- ====================================================================== -->
<code-fragment id="string-literal-equals-literal">
<![CDATA[
public class Test {
public boolean isJava6(){
return "1.6".equals("1.6");
}
}
]]>
</code-fragment>
<test-code>
<description>string literal equals string literal</description>
<expected-problems>0</expected-problems>
<code-ref id="string-literal-equals-literal" />
</test-code>
<!-- ====================================================================== -->
</test-data> </test-data>