Merge pull request #3386 from adangel:pmd7-update-BigIntegerInstantiation
[java] Update BigIntegerInstantiation #3386
This commit is contained in:
5 files changed
+98
-53
No files matched your search
@@ -291,7 +291,7 @@
|
||||
<rule ref="category/java/performance.xml/AvoidFileStream"/>
|
||||
<!-- <rule ref="category/java/performance.xml/AvoidInstantiatingObjectsInLoops"/> -->
|
||||
<rule ref="category/java/performance.xml/AvoidUsingShortType"/>
|
||||
<!-- <rule ref="category/java/performance.xml/BigIntegerInstantiation"/> -->
|
||||
<rule ref="category/java/performance.xml/BigIntegerInstantiation"/>
|
||||
<!-- <rule ref="category/java/performance.xml/BooleanInstantiation"/> -->
|
||||
<rule ref="category/java/performance.xml/ByteInstantiation"/>
|
||||
<rule ref="category/java/performance.xml/ConsecutiveAppendsShouldReuse"/>
|
||||
|
||||
+37
-38
@@ -6,57 +6,56 @@ package net.sourceforge.pmd.lang.java.rule.performance;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.JavaLanguageModule;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
|
||||
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.ASTLiteral;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Rule that marks instantiations of new {@link BigInteger} or
|
||||
* {@link BigDecimal} objects, when there is a well-known constant available,
|
||||
* such as {@link BigInteger#ZERO}.
|
||||
* Rule that marks instantiations of new {@link BigInteger} or {@link BigDecimal} objects, when there is a well-known
|
||||
* constant available, such as {@link BigInteger#ZERO}.
|
||||
*/
|
||||
public class BigIntegerInstantiationRule extends AbstractJavaRule {
|
||||
public class BigIntegerInstantiationRule extends AbstractJavaRulechainRule {
|
||||
|
||||
|
||||
private static final Set<String> CONSTANTS = CollectionUtil.setOf("0", "0.", "1");
|
||||
|
||||
public BigIntegerInstantiationRule() {
|
||||
super(ASTConstructorCall.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object visit(ASTAllocationExpression node, Object data) {
|
||||
Node type = node.getChild(0);
|
||||
public Object visit(ASTConstructorCall node, Object data) {
|
||||
LanguageVersion languageVersion = node.getAstInfo().getLanguageVersion();
|
||||
boolean jdk15 = languageVersion.compareToVersion("1.5") >= 0;
|
||||
boolean jdk9 = languageVersion.compareToVersion("9") >= 0;
|
||||
|
||||
if (!(type instanceof ASTClassOrInterfaceType)) {
|
||||
return super.visit(node, data);
|
||||
}
|
||||
if (TypeTestUtil.isA(BigInteger.class, node) || jdk15 && TypeTestUtil.isA(BigDecimal.class, node)) {
|
||||
|
||||
boolean jdk15 = node.getAstInfo().getLanguageVersion().compareTo(LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("1.5")) >= 0;
|
||||
if ((TypeTestUtil.isA(BigInteger.class, (ASTClassOrInterfaceType) type)
|
||||
|| jdk15 && TypeTestUtil.isA(BigDecimal.class, (ASTClassOrInterfaceType) type))
|
||||
&& !node.hasDescendantOfType(ASTArrayDimsAndInits.class)) {
|
||||
ASTArguments args = node.getFirstChildOfType(ASTArguments.class);
|
||||
if (args.size() == 1) {
|
||||
ASTLiteral literal = node.getFirstDescendantOfType(ASTLiteral.class);
|
||||
if (literal == null
|
||||
|| literal.getParent().getParent().getParent().getParent().getParent() != args) {
|
||||
return super.visit(node, data);
|
||||
}
|
||||
@NonNull
|
||||
ASTArgumentList arguments = node.getArguments();
|
||||
if (arguments.size() == 1) {
|
||||
ASTExpression firstArg = arguments.get(0);
|
||||
|
||||
String img = literal.getImage();
|
||||
if (literal.isStringLiteral()) {
|
||||
img = img.substring(1, img.length() - 1);
|
||||
}
|
||||
|
||||
if ("0".equals(img) || "1".equals(img) || jdk15 && "10".equals(img)) {
|
||||
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)) {
|
||||
addViolation(data, node);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.visit(node, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -313,21 +313,25 @@ public class UsingShort {
|
||||
<rule name="BigIntegerInstantiation"
|
||||
language="java"
|
||||
since="3.9"
|
||||
message="Don't create instances of already existing BigInteger and BigDecimal (ZERO, ONE, TEN)"
|
||||
message="Don''t create instances of already existing BigInteger and BigDecimal (ZERO, ONE, TEN)"
|
||||
class="net.sourceforge.pmd.lang.java.rule.performance.BigIntegerInstantiationRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#bigintegerinstantiation">
|
||||
<description>
|
||||
Don't create instances of already existing BigInteger (BigInteger.ZERO, BigInteger.ONE) and
|
||||
for Java 1.5 onwards, BigInteger.TEN and BigDecimal (BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN)
|
||||
Don't create instances of already existing BigInteger (`BigInteger.ZERO`, `BigInteger.ONE`),
|
||||
for Java 1.5 onwards, BigInteger.TEN and BigDecimal (`BigDecimal.ZERO`, `BigDecimal.ONE`, `BigDecimal.TEN`) and
|
||||
for Java 9 onwards `BigInteger.TWO`.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
BigInteger bi = new BigInteger(1); // reference BigInteger.ONE instead
|
||||
BigInteger bi1 = new BigInteger("1"); // reference BigInteger.ONE instead
|
||||
BigInteger bi2 = new BigInteger("0"); // reference BigInteger.ZERO instead
|
||||
BigInteger bi3 = new BigInteger(0.0); // reference BigInteger.ZERO instead
|
||||
BigInteger bi4;
|
||||
bi4 = new BigInteger(0); // reference BigInteger.ZERO instead
|
||||
BigInteger bi3;
|
||||
bi3 = new BigInteger("0"); // reference BigInteger.ZERO instead
|
||||
|
||||
BigDecimal bd1 = new BigDecimal(0); // reference BigDecimal.ZERO instead
|
||||
BigDecimal bd2 = new BigDecimal("0.") ; // reference BigDecimal.ZERO instead
|
||||
BigDecimal bd3 = new BigDecimal(10); // reference BigDecimal.TEN instead
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
-1
@@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.performance;
|
||||
|
||||
import net.sourceforge.pmd.testframework.PmdRuleTst;
|
||||
|
||||
@org.junit.Ignore("Rule has not been updated yet")
|
||||
public class BigIntegerInstantiationTest extends PmdRuleTst {
|
||||
// no additional unit tests
|
||||
}
|
||||
+49
-6
@@ -7,6 +7,7 @@
|
||||
<test-code>
|
||||
<description>Fail, BigInteger(1)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>4</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
import java.math.BigInteger;
|
||||
|
||||
@@ -33,6 +34,7 @@ public class Foo {
|
||||
<test-code>
|
||||
<description>Fail, BigInteger(0)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>4</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
import java.math.BigInteger;
|
||||
|
||||
@@ -83,6 +85,7 @@ public class Foo {
|
||||
<test-code>
|
||||
<description>Fail, BigInteger(10) 1.5 mode</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>4</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
import java.math.BigInteger;
|
||||
|
||||
@@ -95,12 +98,14 @@ public class Foo {
|
||||
|
||||
<test-code>
|
||||
<description>Fail, BigDecimal(1)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-problems>2</expected-problems>
|
||||
<expected-linenumbers>4,5</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class Foo {
|
||||
BigDecimal b = new BigDecimal(1);
|
||||
BigDecimal b1 = new BigDecimal(1);
|
||||
BigDecimal b2 = new BigDecimal("1");
|
||||
}
|
||||
]]></code>
|
||||
<source-type>java 1.5</source-type>
|
||||
@@ -108,12 +113,14 @@ public class Foo {
|
||||
|
||||
<test-code>
|
||||
<description>Fail, BigDecimal(10)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-problems>2</expected-problems>
|
||||
<expected-linenumbers>4,5</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class Foo {
|
||||
BigDecimal b = new BigDecimal(10);
|
||||
BigDecimal b1 = new BigDecimal(10);
|
||||
BigDecimal b2 = new BigDecimal("10");
|
||||
}
|
||||
]]></code>
|
||||
<source-type>java 1.5</source-type>
|
||||
@@ -121,14 +128,50 @@ public class Foo {
|
||||
|
||||
<test-code>
|
||||
<description>Fail, BigDecimal(0)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-problems>3</expected-problems>
|
||||
<expected-linenumbers>4,5,6</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class Foo {
|
||||
BigDecimal b = new BigDecimal(0);
|
||||
BigDecimal b1 = new BigDecimal(0);
|
||||
BigDecimal b2 = new BigDecimal("0");
|
||||
BigDecimal b3 = new BigDecimal("0.");
|
||||
BigDecimal b4 = new BigDecimal("0.0"); // that's not ZERO - ZERO has no decimals, this has 1 decimal (scale)
|
||||
}
|
||||
]]></code>
|
||||
<source-type>java 1.5</source-type>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Fail, BigInteger(2) with Java9</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>4</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class Foo {
|
||||
BigInteger b = new BigInteger("2"); // Use BigInteger.TWO instead
|
||||
}
|
||||
]]></code>
|
||||
<source-type>java 9</source-type>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>False negative with indirect const string</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>5</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
import java.math.BigInteger;
|
||||
|
||||
class Foo {
|
||||
static final String Z = "0";
|
||||
static { new BigInteger(Z); }
|
||||
|
||||
public void test(String a) {
|
||||
new BigInteger(a); // not a const value
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
</test-data>
|
||||
Reference in new issue
Block a user