From 7a707aa7b62ec51ae2cbbcbc674e9c683be9a04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sun, 6 Aug 2017 22:41:29 +0200 Subject: [PATCH] Java, typeres: add erased candidate set and minimal erased candidate set methods --- .../typeresolution/MethodTypeResolution.java | 4 +++ .../typeinference/TypeInferenceResolver.java | 33 +++++++++++++++++++ .../pmd/typeresolution/TypeInferenceTest.java | 27 ++++++++++++++- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java index 9fb3c15305..e0750db818 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java @@ -484,6 +484,10 @@ public final class MethodTypeResolution { return isSubtypeable(parameter, argument.getTypeDefinition()); } + public static boolean isSubtypeable(Class parameter, Class argument) { + return isSubtypeable(JavaTypeDefinition.forClass(parameter), JavaTypeDefinition.forClass(argument)); + } + /** * Subtypeability rules. * https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.10 diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typeinference/TypeInferenceResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typeinference/TypeInferenceResolver.java index b4deb26c1b..1f38a90673 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typeinference/TypeInferenceResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typeinference/TypeInferenceResolver.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.java.typeresolution.typeinference; +import net.sourceforge.pmd.lang.java.typeresolution.MethodTypeResolution; import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition; import static net.sourceforge.pmd.lang.java.typeresolution.typeinference.InferenceRuleType.EQUALITY; @@ -26,6 +27,38 @@ public final class TypeInferenceResolver { } + public static Set> getErasedCandidateSet(List>> erasedSuperTypeSets) { + Set> result = new HashSet<>(); + + if (!erasedSuperTypeSets.isEmpty()) { + result.addAll(erasedSuperTypeSets.get(0)); + } + + for (Set> superTypeSet : erasedSuperTypeSets) { + result.retainAll(superTypeSet); + } + + return result; + } + + public static Set> getMinimalErasedCandidateSet(Set> erasedSet) { + Set> result = new HashSet<>(); + + outter: + for (Class candidate : erasedSet) { + for (Class erasedSetMember : erasedSet) { + if (candidate != erasedSetMember + && MethodTypeResolution.isSubtypeable(candidate, erasedSetMember)) { + continue outter; // skip candidate from result set + } + } + + result.add(candidate); + } + + return result; + } + /** * Resolve unresolved variables in a list of bounds. */ diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/TypeInferenceTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/TypeInferenceTest.java index ed31b98676..0bcd6e314a 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/TypeInferenceTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/TypeInferenceTest.java @@ -12,8 +12,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import org.junit.Test; @@ -278,7 +280,7 @@ public class TypeInferenceTest { @Test public void testIncorporationSubtypeAndSubtype() { List result; - + // ### Original rule 4. : S <: α and α <: T imply ‹S <: T› result = incorporationResult(new Bound(s, alpha, EQUALITY), new Bound(alpha, t, SUBTYPE)); assertEquals(result.size(), 1); @@ -291,6 +293,29 @@ public class TypeInferenceTest { } + @Test + public void testErasedCandidateSet() { + List>> superTypeSets = new ArrayList<>(); + superTypeSets.add(JavaTypeDefinition.forClass(List.class).getErasedSuperTypeSet()); + superTypeSets.add(JavaTypeDefinition.forClass(Set.class).getErasedSuperTypeSet()); + + Set> erasedCandidate = TypeInferenceResolver.getErasedCandidateSet(superTypeSets); + + assertEquals(erasedCandidate.size(), 3); + assertTrue(erasedCandidate.contains(Object.class)); + assertTrue(erasedCandidate.contains(Collection.class)); + assertTrue(erasedCandidate.contains(Iterable.class)); + } + + @Test + public void testMinimalErasedCandidateSet() { + Set> minimalSet = TypeInferenceResolver.getMinimalErasedCandidateSet( + JavaTypeDefinition.forClass(List.class).getErasedSuperTypeSet()); + + assertEquals(minimalSet.size(), 1); + assertTrue(minimalSet.contains(List.class)); + } + private List incorporationResult(Bound firstBound, Bound secondBound) { List current = new ArrayList<>(); List newBounds = new ArrayList<>();