diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml
index a6ab7f8913..5504b69ffb 100644
--- a/.ci/files/all-java.xml
+++ b/.ci/files/all-java.xml
@@ -291,7 +291,7 @@
-
+
diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml
index ddc0cd1590..d233ea14e1 100644
--- a/pmd-java/src/main/resources/category/java/performance.xml
+++ b/pmd-java/src/main/resources/category/java/performance.xml
@@ -116,12 +116,13 @@ public class Test {
-Problem: A Calendar is a heavyweight object and expensive to create.
+Problem: `java.util.Calendar` is a heavyweight object and expensive to create. It should only be used, if
+calendar calculations are needed.
Solution: Use `new Date()`, Java 8+ `java.time.LocalDateTime.now()` or `ZonedDateTime.now()`.
@@ -129,26 +130,32 @@ Solution: Use `new Date()`, Java 8+ `java.time.LocalDateTime.now()` or `ZonedDat
2 and ../PrimarySuffix[last()-1][@Image = 'getTime' or @Image='getTimeInMillis']]
+//MethodCall[pmd-java:matchesSig("java.util.Calendar#getTime()") or pmd-java:matchesSig("java.util.Calendar#getTimeInMillis()")]
+ [*[1][local-name() = ('MethodCall', 'ConstructorCall')]
+ [pmd-java:matchesSig("java.util.Calendar#getInstance()")
+ or pmd-java:matchesSig("java.util.GregorianCalendar#getInstance()")
+ or pmd-java:matchesSig("java.util.GregorianCalendar#new()")]
+ ]
|
-//MethodDeclaration[not(MethodDeclarator/FormalParameters//ClassOrInterfaceType[pmd-java:typeIs('java.util.Calendar')])]
- /Block/BlockStatement//PrimaryExpression
- /PrimaryPrefix/Name
- [pmd-java:typeIs('java.util.Calendar')]
- [every $var in @Image satisfies (
- (ends-with($var, '.getTime') or ends-with($var, '.getTimeInMillis'))
- and
- (: ignore if .set* or .add* or .clear is called on the variable :)
- not(ancestor::Block/BlockStatement//Name[
- starts-with(@Image, concat((tokenize($var, '\.'), $var)[1], '.set'))
- or
- starts-with(@Image, concat((tokenize($var, '\.'), $var)[1], '.add'))
- or
- starts-with(@Image, concat((tokenize($var, '\.'), $var)[1], '.clear'))
- ])
- )]
+//MethodCall[pmd-java:matchesSig("java.util.Calendar#getTime()") or pmd-java:matchesSig("java.util.Calendar#getTimeInMillis()")]
+ [*[1][local-name() = 'VariableAccess']]
+ (: ignore if .set* or .add or .clear or .roll is called on the variable :)
+ [not(VariableAccess/@Name = ancestor::Block//MethodCall[starts-with(@MethodName, "set") or @MethodName = ("add", "clear", "roll")]/VariableAccess/@Name)]
+ (: variable must be initialized with getInstance :)
+ [VariableAccess/@Name = ancestor::Block//LocalVariableDeclaration/VariableDeclarator[
+ (MethodCall | ConstructorCall)
+ [pmd-java:matchesSig("java.util.Calendar#getInstance()")
+ or pmd-java:matchesSig("java.util.GregorianCalendar#getInstance()")
+ or pmd-java:matchesSig("java.util.GregorianCalendar#new()")]
+ ]/VariableDeclaratorId/@Name]
|
-//ClassOrInterfaceType[pmd-java:typeIs('org.joda.time.DateTime') or pmd-java:typeIs('org.joda.time.LocalDateTime')][../Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name[ends-with(@Image, 'Calendar.getInstance')]]
+//ConstructorCall[pmd-java:typeIs("org.joda.time.DateTime") or pmd-java:typeIs("org.joda.time.LocalDateTime")]
+ [ArgumentList[(MethodCall | ConstructorCall)
+ [pmd-java:matchesSig("java.util.Calendar#getInstance()")
+ or pmd-java:matchesSig("java.util.GregorianCalendar#getInstance()")
+ or pmd-java:matchesSig("java.util.GregorianCalendar#new()")]]
+ ]
+
]]>
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/AvoidCalendarDateCreationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/AvoidCalendarDateCreationTest.java
index fb5991354b..a3c8909f50 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/AvoidCalendarDateCreationTest.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/AvoidCalendarDateCreationTest.java
@@ -6,6 +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 AvoidCalendarDateCreationTest extends PmdRuleTst {
+ // no additional unit tests
}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidCalendarDateCreation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidCalendarDateCreation.xml
index ce34feba1f..374b93b004 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidCalendarDateCreation.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidCalendarDateCreation.xml
@@ -135,6 +135,7 @@ public class Foo {
+
+
+
+ False positive with Calendar not created here
+ 0
+
+
+
+
+ False positive when this is a Calendar
+ 0
+
+
+
+
+ False positive with calendar builder
+ 0
+
+
+
+
+ False positive with specific date
+ 0
+
+
+
+
+ False positive with calendar not created by getInstance
+ 0
+
+
+
+
+ New GregorianCalendar default constructor
+ 2
+ 7,8
+