Fix behavior for #3160

This commit is contained in:
Clément Fournier committed 2021-03-05 15:32:34 +01:00
1 parent 56b054d0c5
commit ec1e6bfb77
4 files changed
+49 -6

No files matched your search

@@ -34,6 +34,13 @@ public final class ASTArrayInitializer extends AbstractJavaExpr implements ASTEx
return visitor.visit(this, data);
}
/**
* Return the number of elements.
*/
public int length() {
return getNumChildren();
}
@Override
public Iterator<ASTExpression> iterator() {
@@ -4,10 +4,16 @@
package net.sourceforge.pmd.lang.java.rule.bestpractices;
import net.sourceforge.pmd.lang.ast.NodeStream;
import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation;
import net.sourceforge.pmd.lang.java.ast.ASTArrayDimExpr;
import net.sourceforge.pmd.lang.java.ast.ASTArrayInitializer;
import net.sourceforge.pmd.lang.java.ast.ASTArrayTypeDim;
import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr;
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil;
@@ -43,7 +49,7 @@ public class MethodReturnsInternalArrayRule extends AbstractJavaRulechainRule {
JVariableSymbol symbol = reference.getReferencedSym();
if (symbol instanceof JFieldSymbol) {
JFieldSymbol field = (JFieldSymbol) symbol;
if (field.isStatic() && !field.isFinal()) {
if (field.isStatic() && (!field.isFinal() || !hasZeroLengthArrayInitializer(field))) {
addViolation(data, returnStmt, reference.getName());
}
}
@@ -52,4 +58,31 @@ public class MethodReturnsInternalArrayRule extends AbstractJavaRulechainRule {
}
return data;
}
private static boolean hasZeroLengthArrayInitializer(JFieldSymbol sym) {
return NodeStream.of(sym.tryGetNode())
.map(ASTVariableDeclaratorId::getInitializer)
.filter(MethodReturnsInternalArrayRule::isZeroLengthArrayExpr)
.nonEmpty();
}
private static boolean isZeroLengthArrayExpr(ASTExpression expr) {
if (expr instanceof ASTArrayInitializer) {
// {}
return ((ASTArrayInitializer) expr).length() == 0;
} else if (expr instanceof ASTArrayAllocation) {
ASTArrayInitializer init = ((ASTArrayAllocation) expr).getArrayInitializer();
if (init != null) {
// new int[] {}
return init.length() == 0;
} else {
// new int[0]
ASTArrayTypeDim lastChild = ((ASTArrayAllocation) expr).getTypeNode().getDimensions().getLastChild();
if (lastChild instanceof ASTArrayDimExpr) {
return JavaRuleUtil.isIntLit(((ASTArrayDimExpr) lastChild).getLengthExpression(), 0);
}
}
}
return false;
}
}
@@ -123,9 +123,12 @@ public final class JavaRuleUtil {
return false;
}
private static boolean isIntLit(JavaNode e, int value) {
/**
* Return true if the number is an int or long literal with the given int value.
*/
public static boolean isIntLit(JavaNode e, int value) {
if (e instanceof ASTNumericLiteral) {
return ((ASTNumericLiteral) e).getValueAsInt() == value;
return ((ASTNumericLiteral) e).isIntegral() && ((ASTNumericLiteral) e).getValueAsInt() == value;
}
return false;
}
@@ -402,8 +402,8 @@ public class OuterClass {
<test-code>
<description>Detect returned static arrays</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>16</expected-linenumbers>
<expected-problems>2</expected-problems>
<expected-linenumbers>8,16</expected-linenumbers>
<code><![CDATA[
import java.util.concurrent.Callable;
@@ -412,7 +412,7 @@ public class MyClass {
private final Callable<String[]> returnsFooBar = new Callable<String[]>() {
@Override
public String[] call() {
return FOO_BAR; // no violation, because FOO_BAR is final. See https://sourceforge.net/p/pmd/bugs/1475/
return FOO_BAR;
}
};