Skip to content

Commit

Permalink
Simplified GenericsClassContext
Browse files Browse the repository at this point in the history
  • Loading branch information
jlink committed Oct 20, 2023
1 parent 0454ccd commit 238c991
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -16,15 +14,15 @@ public String toString() {
}
};

private final TypeUsage contextType;
private final Class<?> contextClass;
private final Map<LookupTypeVariable, TypeResolution> 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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand All @@ -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<Class<?>> supertypesOf(Class<?> clazz) {
if (clazz == null) {
return Collections.emptySet();
}
Set<Class<?>> supertypes = new LinkedHashSet<>();
supertypes.add(clazz.getSuperclass());
supertypes.addAll(Arrays.asList(clazz.getInterfaces()));
return supertypes;
}

private static TypeResolution resolveVariableInTypes(TypeResolution variableResolution, Collection<TypeUsage> superTypes) {
for (TypeUsage superType : superTypes) {
private static TypeResolution resolveVariableInTypes(TypeResolution variableResolution, Collection<Class<?>> 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;
Expand Down
23 changes: 12 additions & 11 deletions engine/src/main/java/net/jqwik/engine/support/GenericsSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> extends Function<T, String> {}
Expand All @@ -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);

Expand Down

0 comments on commit 238c991

Please sign in to comment.