Merge branch 'master' into perf-AvoidCalendarDateCreation

This commit is contained in:
Andreas Dangel
2020-06-18 11:13:55 +02:00
5 changed files with 220 additions and 19 deletions

View File

@ -553,7 +553,7 @@ while (true) { // preferred approach
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#defaultpackage">
<description>
Use explicit scoping instead of accidental usage of default package private level.
The rule allows methods and fields annotated with Guava's @VisibleForTesting.
The rule allows methods and fields annotated with Guava's @VisibleForTesting and JUnit 5's annotations.
</description>
<priority>3</priority>
<properties>
@ -564,7 +564,17 @@ The rule allows methods and fields annotated with Guava's @VisibleForTesting.
//ClassOrInterfaceDeclaration[@Interface= false()]
/ClassOrInterfaceBody
/ClassOrInterfaceBodyDeclaration
[not(Annotation//Name[ends-with(@Image, 'VisibleForTesting')])]
[not(Annotation//Name[
pmd-java:typeIs('org.junit.jupiter.api.Test')
or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
or pmd-java:typeIs('org.junit.jupiter.api.ParameterizedTest')
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
or pmd-java:typeIs('org.junit.jupiter.api.BeforeAll')
or pmd-java:typeIs('org.junit.jupiter.api.AfterAll')
or pmd-java:typeIs('org.junit.jupiter.api.BeforeEach')
or pmd-java:typeIs('org.junit.jupiter.api.AfterEach')
or ends-with(@Image, 'VisibleForTesting')])]
[
FieldDeclaration[@PackagePrivate= true()]
or MethodDeclaration[@PackagePrivate= true()]
@ -2016,6 +2026,11 @@ Use the diamond operator to let the type be inferred automatically. With the Dia
to avoid duplication of the type parameters.
Instead, the compiler is now able to infer the parameter types for constructor calls,
which makes the code also more readable.
The diamond operator has been introduced with java 7. However, type inference has been improved further
with java8, rendering more type parameters unnecessary. This is only possible with java8 and the resulting
code won't compile with java7. If you use java7, make sure to enable `java7Compatibility` for this rule to avoid
false positives.
</description>
<priority>3</priority>
<properties>
@ -2028,15 +2043,17 @@ which makes the code also more readable.
|
//StatementExpression[AssignmentOperator and PrimaryExpression/PrimaryPrefix[not(Expression)]]
)
/Expression/PrimaryExpression[not(PrimarySuffix) and not(ancestor::ArgumentList)]
/(Expression | Expression[$java7Compatibility = false()]/ConditionalExpression | Expression[$java7Compatibility = false()]/ConditionalExpression/Expression)
/PrimaryExpression[not(PrimarySuffix) and not(ancestor::ArgumentList)]
/PrimaryPrefix
/AllocationExpression
[@AnonymousClass=false()]
[ClassOrInterfaceType/TypeArguments[@Diamond=false() and not(TypeArgument//TypeArguments)]]
[ClassOrInterfaceType/TypeArguments[@Diamond=false() and not($java7Compatibility = true() and .//TypeArgument[@Wildcard=true()])]]
[not(ArrayDimsAndInits)]
]]>
</value>
</property>
<property name="java7Compatibility" type="Boolean" description="If disabled, the rule shows also violations that are applicable for java8+" value="false" />
</properties>
<example>
<![CDATA[

View File

@ -61,6 +61,114 @@ public class Foo {
<code><![CDATA[
public class Foo {
@VisibleForTesting static final int[] ints = {};
}
]]></code>
</test-code>
<test-code>
<description>#2573 DefaultPackage triggers on field annotated with JUnit 5 @Test</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@org.junit.jupiter.api.Test
void bar() {
}
}
]]></code>
</test-code>
<test-code>
<description>#2573 DefaultPackage triggers on field annotated with JUnit 5 @RepeatedTest</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@org.junit.jupiter.api.RepeatedTest
void bar() {
}
}
]]></code>
</test-code>
<test-code>
<description>#2573 DefaultPackage triggers on field annotated with JUnit 5 @ParameterizedTest</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@org.junit.jupiter.api.ParameterizedTest
void bar() {
}
}
]]></code>
</test-code>
<test-code>
<description>#2573 DefaultPackage triggers on field annotated with JUnit 5 @TestFactory</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@org.junit.jupiter.api.TestFactory
void bar() {
}
}
]]></code>
</test-code>
<test-code>
<description>#2573 DefaultPackage triggers on field annotated with JUnit 5 @TestTemplate</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@org.junit.jupiter.api.TestTemplate
void bar() {
}
}
]]></code>
</test-code>
<test-code>
<description>#2573 DefaultPackage triggers on field annotated with JUnit 5 @BeforeAll</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@org.junit.jupiter.api.BeforeAll
void bar() {
}
}
]]></code>
</test-code>
<test-code>
<description>#2573 DefaultPackage triggers on field annotated with JUnit 5 @AfterAll</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@org.junit.jupiter.api.AfterAll
void bar() {
}
}
]]></code>
</test-code>
<test-code>
<description>#2573 DefaultPackage triggers on field annotated with JUnit 5 @BeforeEach</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@org.junit.jupiter.api.BeforeEach
void bar() {
}
}
]]></code>
</test-code>
<test-code>
<description>#2573 DefaultPackage triggers on field annotated with JUnit 5 @AfterEach</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@org.junit.jupiter.api.AfterEach
void bar() {
}
}
]]></code>
</test-code>

View File

@ -6,8 +6,8 @@
<test-code>
<description>Use Diamond</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>6,11</expected-linenumbers>
<expected-problems>3</expected-problems>
<expected-linenumbers>6,9,10</expected-linenumbers>
<code><![CDATA[
import java.util.ArrayList;
import java.util.List;
@ -17,7 +17,6 @@ public class Foo {
List<String> strings = new ArrayList<String>();
List<String> strings2 = new ArrayList<>();
List<List<String>> strings3 = new ArrayList<>();
// this is a known false negative, see at the bottom
List<List<String>> strings4 = new ArrayList<List<List<String>>>();
this.field = new ArrayList<String>();
}
@ -139,35 +138,43 @@ class Foo {
</test-code>
<!-- These tests depend on the Java version used -->
<!-- For now we keep the old behaviour of ignoring type
arguments that have type arguments themselves, ie we have
false negatives. We can improve that with better type resolution
<!-- For now we keep the old behaviour of Java 7 and ignoring type
arguments which have wildcards involved, ie we have
false negatives for Java8+. We can improve that with better type resolution
in PMD 7. -->
<test-code regressionTest="false">
<description>(J7) Version sensitive tests</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>6</expected-linenumbers>
<test-code>
<description>(J7) Version sensitive tests - avoid possible false positives on Java7</description>
<rule-property name="java7Compatibility">true</rule-property>
<expected-problems>0</expected-problems>
<code><![CDATA[
import java.lang.ref.WeakReference;
public class Foo {
private WeakReference<Class<?>> typeReference;
public void foo() {
// this should be positive in Java 8, negative in Java 7
// in java 7: no violation, in java 8 violation
typeReference = new WeakReference<Class<?>>(String.class);
// this is because in java 7, new WeakReference<>(String.class) types as WeakReference<Class<String>>
// which is incompatible with WeakReference<Class<?>>, whereas Java 8's type inference is better.
typeReference = new WeakReference<Class<?>>(String.class);
// the following is the same:
// in java 7: no violation, in java 8 violation
Class<?> type = null;
typeReference = new WeakReference<Class<?>>(type); // this should be positive on all versions
typeReference = new WeakReference<Class<?>>(type);
}
}
]]></code>
</test-code>
<test-code regressionTest="false">
<description>(J8) Version sensitive tests</description>
<test-code>
<description>(J8) Version sensitive tests - known false negatives on Java8+</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>4,6</expected-linenumbers>
<expected-linenumbers>6,8</expected-linenumbers>
<code><![CDATA[
import java.lang.ref.WeakReference;
public class Foo {
private WeakReference<Class<?>> typeReference;
public void foo() {
@ -175,6 +182,51 @@ public class Foo {
Class<?> type = null;
typeReference = new WeakReference<Class<?>>(type); // pos
}
}
]]></code>
</test-code>
<test-code>
<description>False negative for nested type parameters (#2545)</description>
<rule-property name="java7Compatibility">true</rule-property>
<expected-problems>3</expected-problems>
<expected-linenumbers>7,8,17</expected-linenumbers>
<code><![CDATA[
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.lang.ref.WeakReference;
public class UseDiamondOperatorFalseNegative {
List<Map<String,Object>> l = new ArrayList<Map<String,Object>>(); // FN
WeakReference<Class<String>> typeReference = new WeakReference<Class<String>>(String.class); // FN
WeakReference<Class<?>> typeReference2 = new WeakReference<Class<?>>(String.class); // FP
public void test() {
final List<String> l2;
l2 = true ? new ArrayList<String>() : new ArrayList<String>(); // FN twice for java8+, but for java7, this is ok!
}
static {
l = new ArrayList<Map<String,Object>>(); // FN
}
}
]]></code>
</test-code>
<test-code>
<description>(J8+) False negative for Java8+ and ternary operator (#2545)</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>7,7</expected-linenumbers>
<code><![CDATA[
import java.util.List;
import java.util.ArrayList;
public class UseDiamondOperatorFalseNegative {
public void test() {
final List<String> l2;
l2 = true ? new ArrayList<String>() : new ArrayList<String>(); // FN twice for java8+, but for java7, this is ok!
}
}
]]></code>
</test-code>