diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 58fe6e34a8..3ad9af3175 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -19,6 +19,7 @@ This is a {{ site.pmd.release_type }} release. * [#4881](https://github.com/pmd/pmd/issues/4881): \[java] ClassNamingConventions: interfaces are identified as abstract classes (regression in 7.0.0) * java-performance * [#4874](https://github.com/pmd/pmd/issues/4874): \[java] StringInstantiation: False-positive when using `new String(charArray)` + * [#4886](https://github.com/pmd/pmd/issues/4886): \[java] BigIntegerInstantiation: False Positive with Java 17 and BigDecimal.TWO ### 🚨 API Changes diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/BigIntegerInstantiationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/BigIntegerInstantiationRule.java index eefd379de2..c49cacc44a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/BigIntegerInstantiationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/BigIntegerInstantiationRule.java @@ -13,7 +13,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.java.ast.ASTArgumentList; import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; -import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; import net.sourceforge.pmd.util.CollectionUtil; @@ -24,8 +23,9 @@ import net.sourceforge.pmd.util.CollectionUtil; */ public class BigIntegerInstantiationRule extends AbstractJavaRulechainRule { + // BigDecimal.ZERO, ONE, TEN: since 1.5 + private static final Set BIGDECIMAL_CONSTANTS = CollectionUtil.setOf("0", "0.", "1", "10"); - private static final Set CONSTANTS = CollectionUtil.setOf("0", "0.", "1"); public BigIntegerInstantiationRule() { super(ASTConstructorCall.class); @@ -34,25 +34,42 @@ public class BigIntegerInstantiationRule extends AbstractJavaRulechainRule { @Override public Object visit(ASTConstructorCall node, Object data) { LanguageVersion languageVersion = node.getTextDocument().getLanguageVersion(); - boolean jdk15 = languageVersion.compareToVersion("1.5") >= 0; - boolean jdk9 = languageVersion.compareToVersion("9") >= 0; - if (TypeTestUtil.isA(BigInteger.class, node) || jdk15 && TypeTestUtil.isA(BigDecimal.class, node)) { + @NonNull + ASTArgumentList arguments = node.getArguments(); + if (arguments.size() != 1) { + // only consider the single argument constructors + return data; + } - @NonNull - ASTArgumentList arguments = node.getArguments(); - if (arguments.size() == 1) { - ASTExpression firstArg = arguments.get(0); + // might be a String, an Integer, a Long, a Double, or a BigInteger + Object constValue = arguments.get(0).getConstValue(); - Object constValue = firstArg.getConstValue(); - if (CONSTANTS.contains(constValue) - || jdk15 && "10".equals(constValue) - || jdk9 && "2".equals(constValue) - || Integer.valueOf(0).equals(constValue) - || Integer.valueOf(1).equals(constValue) - || jdk15 && Integer.valueOf(10).equals(constValue)) { - asCtx(data).addViolation(node); - } + boolean java5 = languageVersion.compareToVersion("1.5") >= 0; + boolean java9 = languageVersion.compareToVersion("9") >= 0; + boolean java19 = languageVersion.compareToVersion("19") >= 0; + + if (TypeTestUtil.isA(BigInteger.class, node)) { + // BigInteger.ZERO, ONE: since 1.2 + if ("0".equals(constValue) || "1".equals(constValue)) { + asCtx(data).addViolation(node); + } + // BigInteger.TEN: since 1.5 + if (java5 && "10".equals(constValue)) { + asCtx(data).addViolation(node); + } + // BigInteger.TWO: since 9 + if (java9 && "2".equals(constValue)) { + asCtx(data).addViolation(node); + } + } else if (TypeTestUtil.isA(BigDecimal.class, node)) { + // BigDecimal.ZERO, ONE, TEN: since 1.5 + if (java5 && BIGDECIMAL_CONSTANTS.contains(String.valueOf(constValue))) { + asCtx(data).addViolation(node); + } + // BigDecimal.TWO: since 19 + if (java19 && "2".equals(String.valueOf(constValue))) { + asCtx(data).addViolation(node); } } return data; diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/BigIntegerInstantiation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/BigIntegerInstantiation.xml index 2c62d72b52..2db3bc1f8d 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/BigIntegerInstantiation.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/BigIntegerInstantiation.xml @@ -174,4 +174,34 @@ class Foo { } ]]> + + + [java] BigIntegerInstantiation: False Positive with Java 17 and BigDecimal.TWO #4886 + 0 + + java 17 + + + + [java] BigIntegerInstantiation: BigDecimal.TWO with Java 19 #4886 + 1 + + java 19 +