diff --git a/engine/src/main/java/net/jqwik/engine/support/GenericsClassContext.java b/engine/src/main/java/net/jqwik/engine/support/GenericsClassContext.java index 8f6b6df47..a8952bbf7 100644 --- a/engine/src/main/java/net/jqwik/engine/support/GenericsClassContext.java +++ b/engine/src/main/java/net/jqwik/engine/support/GenericsClassContext.java @@ -5,8 +5,6 @@ import java.util.*; import java.util.stream.*; -import net.jqwik.api.providers.*; - public class GenericsClassContext { static final GenericsClassContext NULL = new GenericsClassContext(null) { @@ -16,15 +14,15 @@ public String toString() { } }; - private final TypeUsage contextType; + private final Class contextClass; private final Map resolutions = new LinkedHashMap<>(); - GenericsClassContext(TypeUsage contextType) { - this.contextType = contextType; + GenericsClassContext(Class contextClass) { + this.contextClass = contextClass; } - public TypeUsage contextType() { - return contextType; + public Class contextClass() { + return contextClass; } void addResolution(TypeVariable typeVariable, Type resolvedType, AnnotatedType annotatedType) { @@ -34,7 +32,7 @@ void addResolution(TypeVariable typeVariable, Type resolvedType, AnnotatedType a @Override public String toString() { - return String.format("GenericsContext(%s)", contextType.toString()); + return String.format("GenericsContext(%s)", contextClass); } public TypeResolution resolveParameter(Parameter parameter) { @@ -102,7 +100,7 @@ public AnnotatedType[] getAnnotatedActualTypeArguments() { private TypeResolution resolveVariable(TypeResolution typeVariableResolution) { TypeResolution localResolution = resolveVariableLocally(typeVariableResolution); if (localResolution.isVariable()) { - TypeResolution supertypeResolution = resolveVariableInSupertypesOf(localResolution, contextType); + TypeResolution supertypeResolution = resolveVariableInSupertypesOf(localResolution, contextClass); if (supertypeResolution.typeHasChanged()) { return resolveType(supertypeResolution); } @@ -119,19 +117,29 @@ private TypeResolution resolveVariableLocally(TypeResolution typeResolution) { return resolutions.getOrDefault(variable, typeResolution.unchanged()); } - private static TypeResolution resolveVariableInSupertypesOf(TypeResolution variableResolution, TypeUsage type) { - return resolveVariableInTypes(variableResolution, type.getSuperTypes()); + private static TypeResolution resolveVariableInSupertypesOf(TypeResolution variableResolution, Class clazz) { + return resolveVariableInTypes(variableResolution, supertypesOf(clazz)); + } + + private static Collection> supertypesOf(Class clazz) { + if (clazz == null) { + return Collections.emptySet(); + } + Set> supertypes = new LinkedHashSet<>(); + supertypes.add(clazz.getSuperclass()); + supertypes.addAll(Arrays.asList(clazz.getInterfaces())); + return supertypes; } - private static TypeResolution resolveVariableInTypes(TypeResolution variableResolution, Collection superTypes) { - for (TypeUsage superType : superTypes) { + private static TypeResolution resolveVariableInTypes(TypeResolution variableResolution, Collection> superTypes) { + for (Class superType : superTypes) { GenericsClassContext context = GenericsSupport.contextFor(superType); TypeResolution resolved = context.resolveVariableLocally(variableResolution); if (resolved.typeHasChanged()) { return resolved; } } - for (TypeUsage superType : superTypes) { + for (Class superType : superTypes) { TypeResolution typeResolution = resolveVariableInSupertypesOf(variableResolution, superType); if (typeResolution.typeHasChanged()) { return typeResolution; diff --git a/engine/src/main/java/net/jqwik/engine/support/GenericsSupport.java b/engine/src/main/java/net/jqwik/engine/support/GenericsSupport.java index d6697eec1..882fc8b0a 100644 --- a/engine/src/main/java/net/jqwik/engine/support/GenericsSupport.java +++ b/engine/src/main/java/net/jqwik/engine/support/GenericsSupport.java @@ -29,17 +29,18 @@ public synchronized static GenericsClassContext contextFor(TypeUsage typeUsage) } private static GenericsClassContext createContext(TypeUsage typeUsage) { - GenericsClassContext context = new GenericsClassContext(typeUsage); + Class contextClass = typeUsage.getRawType(); + GenericsClassContext context = new GenericsClassContext(contextClass); addOwnResolutions(typeUsage, context); - addResolutionsForSuperclass(typeUsage, context); - addResolutionsForInterfaces(typeUsage, context); + addResolutionsForSuperclass(context); + addResolutionsForInterfaces(context); return context; } - private static void addResolutionsForInterfaces(TypeUsage contextType, GenericsClassContext context) { - Class[] interfaces = contextType.getRawType().getInterfaces(); - Type[] genericInterfaces = contextType.getRawType().getGenericInterfaces(); - AnnotatedType[] annotatedInterfaces = contextType.getRawType().getAnnotatedInterfaces(); + private static void addResolutionsForInterfaces(GenericsClassContext context) { + Class[] interfaces = context.contextClass().getInterfaces(); + Type[] genericInterfaces = context.contextClass().getGenericInterfaces(); + AnnotatedType[] annotatedInterfaces = context.contextClass().getAnnotatedInterfaces(); for (int i = 0; i < interfaces.length; i++) { Class supertype = interfaces[i]; Type genericSupertype = genericInterfaces[i]; @@ -48,11 +49,11 @@ private static void addResolutionsForInterfaces(TypeUsage contextType, GenericsC } } - private static void addResolutionsForSuperclass(TypeUsage typeUsage, GenericsClassContext context) { + private static void addResolutionsForSuperclass(GenericsClassContext context) { addResolutionsForSupertype( - typeUsage.getRawType().getSuperclass(), - typeUsage.getRawType().getGenericSuperclass(), - typeUsage.getRawType().getAnnotatedSuperclass(), + context.contextClass().getSuperclass(), + context.contextClass().getGenericSuperclass(), + context.contextClass().getAnnotatedSuperclass(), context ); } diff --git a/engine/src/test/java/net/jqwik/engine/support/GenericsSupportTests.java b/engine/src/test/java/net/jqwik/engine/support/GenericsSupportTests.java index d8d6e8d4d..f4f61bb3e 100644 --- a/engine/src/test/java/net/jqwik/engine/support/GenericsSupportTests.java +++ b/engine/src/test/java/net/jqwik/engine/support/GenericsSupportTests.java @@ -25,7 +25,7 @@ public Integer apply(String s) { } GenericsClassContext context = GenericsSupport.contextFor(JustAClass.class); - assertThat(context.contextType().getRawType()).isSameAs(JustAClass.class); + assertThat(context.contextClass()).isSameAs(JustAClass.class); } private interface PartialFunction extends Function {} @@ -36,7 +36,7 @@ void createContextFromTypeUsage() throws NoSuchMethodException { TypeUsage.of(PartialFunction.class, TypeUsage.of(Integer.class)); GenericsClassContext context = GenericsSupport.contextFor(integerToStringFunction); - assertThat(context.contextType()).isSameAs(integerToStringFunction); + assertThat(context.contextClass()).isSameAs(PartialFunction.class); Method functionMethod = Function.class.getMethod("apply", Object.class);