Java, typeres: add erased candidate set and minimal erased candidate set methods

This commit is contained in:
Bendegúz Nagy
2017-08-06 22:41:29 +02:00
parent 0f657b3a52
commit 7a707aa7b6
3 changed files with 63 additions and 1 deletions

View File

@ -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

View File

@ -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<Class<?>> getErasedCandidateSet(List<Set<Class<?>>> erasedSuperTypeSets) {
Set<Class<?>> result = new HashSet<>();
if (!erasedSuperTypeSets.isEmpty()) {
result.addAll(erasedSuperTypeSets.get(0));
}
for (Set<Class<?>> superTypeSet : erasedSuperTypeSets) {
result.retainAll(superTypeSet);
}
return result;
}
public static Set<Class<?>> getMinimalErasedCandidateSet(Set<Class<?>> erasedSet) {
Set<Class<?>> 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.
*/

View File

@ -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<Constraint> 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<Set<Class<?>>> superTypeSets = new ArrayList<>();
superTypeSets.add(JavaTypeDefinition.forClass(List.class).getErasedSuperTypeSet());
superTypeSets.add(JavaTypeDefinition.forClass(Set.class).getErasedSuperTypeSet());
Set<Class<?>> 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<Class<?>> minimalSet = TypeInferenceResolver.getMinimalErasedCandidateSet(
JavaTypeDefinition.forClass(List.class).getErasedSuperTypeSet());
assertEquals(minimalSet.size(), 1);
assertTrue(minimalSet.contains(List.class));
}
private List<Constraint> incorporationResult(Bound firstBound, Bound secondBound) {
List<Bound> current = new ArrayList<>();
List<Bound> newBounds = new ArrayList<>();