Skip to content

Commit 4674efb

Browse files
committed
feat: resolve type variables recursively
This enables mutator support for classes that use type variables as part of an array, wildcard or other generic class. E.g. `class MyClass<T> { MyClass(Set<T[]> setOfArrays){...} }`.
1 parent c126abe commit 4674efb

File tree

5 files changed

+645
-31
lines changed

5 files changed

+645
-31
lines changed

src/main/java/com/code_intelligence/jazzer/mutation/mutator/aggregate/BeanSupport.java

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.code_intelligence.jazzer.mutation.mutator.aggregate;
1818

19+
import static com.code_intelligence.jazzer.mutation.support.ParameterizedTypeSupport.resolveTypeArguments;
1920
import static com.code_intelligence.jazzer.mutation.support.StreamSupport.getOrEmpty;
2021
import static com.code_intelligence.jazzer.mutation.support.StreamSupport.toArrayOrEmpty;
2122
import static java.util.Arrays.stream;
@@ -26,22 +27,19 @@
2627
import static java.util.stream.Collectors.toMap;
2728

2829
import java.beans.Introspector;
29-
import java.lang.reflect.AnnotatedParameterizedType;
3030
import java.lang.reflect.AnnotatedType;
3131
import java.lang.reflect.Constructor;
3232
import java.lang.reflect.Executable;
3333
import java.lang.reflect.Method;
3434
import java.lang.reflect.Modifier;
3535
import java.lang.reflect.Type;
36-
import java.lang.reflect.TypeVariable;
3736
import java.util.Arrays;
3837
import java.util.Comparator;
3938
import java.util.HashMap;
4039
import java.util.List;
4140
import java.util.Map;
4241
import java.util.Optional;
4342
import java.util.function.Predicate;
44-
import java.util.stream.IntStream;
4543
import java.util.stream.Stream;
4644

4745
class BeanSupport {
@@ -54,26 +52,6 @@ static Optional<Class<?>> optionalClassForName(String targetClassName) {
5452
}
5553
}
5654

57-
// Returns the resolved type argument for a generic class if one exists.
58-
// For example: For the class `class MyClass<T> {}` with annotated type `MyClass<String>`,
59-
// calling `resolveTypeArgument(MyClass.class, annotatedType, T)` returns
60-
// `Optional.of(String.class)`.
61-
private static Optional<AnnotatedType> resolveTypeArgument(
62-
Class<?> clazz, AnnotatedType classType, Type type) {
63-
if (!(classType instanceof AnnotatedParameterizedType)) {
64-
return Optional.empty();
65-
}
66-
67-
TypeVariable<?>[] typeParameters = clazz.getTypeParameters();
68-
AnnotatedType[] typeArguments =
69-
((AnnotatedParameterizedType) classType).getAnnotatedActualTypeArguments();
70-
71-
return IntStream.range(0, typeParameters.length)
72-
.filter(i -> typeParameters[i].equals(type))
73-
.mapToObj(i -> typeArguments[i])
74-
.findFirst();
75-
}
76-
7755
// Returns the annotated parameter types of a method or constructor resolving all generic type
7856
// arguments.
7957
public static AnnotatedType[] resolveAnnotatedParameterTypes(
@@ -82,8 +60,7 @@ public static AnnotatedType[] resolveAnnotatedParameterTypes(
8260
AnnotatedType[] annotated = e.getAnnotatedParameterTypes();
8361
AnnotatedType[] result = new AnnotatedType[generic.length];
8462
for (int i = 0; i < generic.length; i++) {
85-
result[i] =
86-
resolveTypeArgument(e.getDeclaringClass(), classType, generic[i]).orElse(annotated[i]);
63+
result[i] = resolveTypeArguments(e.getDeclaringClass(), classType, annotated[i]);
8764
}
8865
return result;
8966
}
@@ -96,8 +73,8 @@ public static Type[] resolveParameterTypes(Executable e, AnnotatedType classType
9673
}
9774

9875
static Type resolveReturnType(Method method, AnnotatedType classType) {
99-
return resolveTypeArgument(method.getDeclaringClass(), classType, method.getGenericReturnType())
100-
.orElse(method.getAnnotatedReturnType())
76+
return resolveTypeArguments(
77+
method.getDeclaringClass(), classType, method.getAnnotatedReturnType())
10178
.getType();
10279
}
10380

0 commit comments

Comments
 (0)