From e2b666210b0120342699613f3ce7c196d698d83f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 29 Apr 2024 14:40:44 +0200 Subject: [PATCH 1/3] [java] Fix #4852 - TypeTestUtil.isA considers intersection type subtype of everything --- .../pmd/lang/java/types/TypeTestUtil.java | 9 ++++++++- .../pmd/lang/java/types/TypeTestUtilTest.java | 18 ++++++++++++++++++ .../xml/ReplaceVectorWithList.xml | 19 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java index f9c5df63eb..d2dc5500e5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java @@ -139,7 +139,7 @@ public final class TypeTestUtil { * @param t1 A supertype * @param t2 A type * - * @return Whether t1 is a subtype of t2 + * @return Whether t2 is a subtype of t1 */ public static boolean isA(@Nullable JTypeMirror t1, @NonNull JTypeMirror t2) { if (t1 == null) { @@ -153,6 +153,13 @@ public final class TypeTestUtil { return false; // conventionally } else if (t2 instanceof JTypeVar) { return t1.isTop() || isA(t1, ((JTypeVar) t2).getUpperBound()); + } else if (t2 instanceof JIntersectionType) { + for (JTypeMirror subt : ((JIntersectionType) t2).getComponents()) { + if (isA(t1, subt)) { + return true; + } + } + return false; } return t2.isSubtypeOf(t1); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypeTestUtilTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypeTestUtilTest.java index 520962b291..c9ef03c5e6 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypeTestUtilTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypeTestUtilTest.java @@ -173,6 +173,24 @@ class TypeTestUtilTest extends BaseParserTest { assertIsNot(field, String.class); } + @Test + void testIsATypeVarWithUnresolvedIntersectionBound() { + // a type var with an unresolved bound should not be considered + // a subtype of everything + // #4852 + + ASTType field = + java.parse("class Foo {\n" + + "\tT field;\n" + + "}") + .descendants(ASTFieldDeclaration.class) + .firstOrThrow().getTypeNode(); + + assertIsA(field, Object.class); + assertIsA(field, Number.class); + assertIsNot(field, String.class); + } + @Test void testIsAStringWithTypeArguments() { diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceVectorWithList.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceVectorWithList.xml index e8f6476c87..d1b3906aab 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceVectorWithList.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceVectorWithList.xml @@ -42,4 +42,23 @@ public class Foo { } ]]> + + Not about vector + 0 + { + + public static & IAntiFraudCriterion> AAntiFraudPolicy of(Class enumClass, + Map> criterionChecks) { + return new AAntiFraudPolicy(); + } + + } + ]]> + From 676767c34a10f20a3fabab15cd0fa059c448ce5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 29 Apr 2024 14:45:08 +0200 Subject: [PATCH 2/3] Use typeIsExactly for ReplaceVectorWithList --- .../main/resources/category/java/bestpractices.xml | 3 ++- .../bestpractices/xml/ReplaceVectorWithList.xml | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 881f6b4995..8db08d0343 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -1312,12 +1312,13 @@ Consider replacing Vector usages with the newer java.util.ArrayList if expensive + + + Generic vector + 1 + v) { + } +} + ]]> + + ok, not java.util.Vector 0 From fa176cf31693f53ef4a4ef79e3f90267e274bf31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Mon, 29 Apr 2024 13:34:06 -0300 Subject: [PATCH 3/3] Update changelog, refs 4852 --- docs/pages/release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 2a0c2c81f0..85fe4d5f8d 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -18,6 +18,7 @@ This is a {{ site.pmd.release_type }} release. * java-bestpractices * [#4278](https://github.com/pmd/pmd/issues/4278): \[java] UnusedPrivateMethod FP with Junit 5 @MethodSource and default factory method name + * [#4852](https://github.com/pmd/pmd/issues/4852): \[java] ReplaceVectorWithList false-positive (neither Vector nor List usage) * [#4975](https://github.com/pmd/pmd/issues/4975): \[java] UnusedPrivateMethod false positive when using @MethodSource on a @Nested test ### 🚨 API Changes