LANG-1348 - StackOverflowError on TypeUtils.toString(...) for a generic return type of Enum.valueOf (closes #292)

This commit is contained in:
mbusso 2017-09-28 21:51:24 -03:00 committed by pascalschumacher
parent 36217ee164
commit cc6beb2d05
2 changed files with 49 additions and 3 deletions

View File

@ -1788,7 +1788,7 @@ public class TypeUtils {
final Type useOwner = p.getOwnerType();
final Class<?> raw = (Class<?>) p.getRawType();
final Type[] typeArguments = p.getActualTypeArguments();
if (useOwner == null) {
buf.append(raw.getName());
} else {
@ -1800,10 +1800,46 @@ public class TypeUtils {
buf.append('.').append(raw.getSimpleName());
}
appendAllTo(buf.append('<'), ", ", typeArguments).append('>');
final int[] recursiveTypeIndexes = findRecursiveTypes(p);
if (recursiveTypeIndexes.length > 0) {
appendRecursiveTypes(buf, recursiveTypeIndexes, p.getActualTypeArguments());
} else {
appendAllTo(buf.append('<'), ", ", p.getActualTypeArguments()).append('>');
}
return buf.toString();
}
private static void appendRecursiveTypes(StringBuilder buf, int[] recursiveTypeIndexes, Type[] argumentTypes) {
for (int i = 0; i < recursiveTypeIndexes.length; i++) {
appendAllTo(buf.append('<'), ", ", argumentTypes[i].toString()).append('>');
}
final Type[] argumentsFiltered = ArrayUtils.removeAll(argumentTypes, recursiveTypeIndexes);
if (argumentsFiltered.length > 0) {
appendAllTo(buf.append('<'), ", ", argumentsFiltered).append('>');
}
}
private static int[] findRecursiveTypes(ParameterizedType p) {
Type[] filteredArgumentTypes = Arrays.copyOf(p.getActualTypeArguments(), p.getActualTypeArguments().length);
int[] indexesToRemove = new int[] {};
for (int i = 0; i < filteredArgumentTypes.length; i++) {
if (filteredArgumentTypes[i] instanceof TypeVariable<?>) {
if (containsVariableTypeSameParametrizedTypeBound(((TypeVariable<?>) filteredArgumentTypes[i]), p)) {
indexesToRemove = ArrayUtils.add(indexesToRemove, i);
}
}
}
return indexesToRemove;
}
private static boolean containsVariableTypeSameParametrizedTypeBound(TypeVariable<?> typeVariable, ParameterizedType p) {
return ArrayUtils.contains(typeVariable.getBounds(), p);
}
/**
* Format a {@link WildcardType} as a {@link String}.
* @param w {@code WildcardType} to format
@ -1840,7 +1876,7 @@ public class TypeUtils {
* @return {@code buf}
* @since 3.2
*/
private static StringBuilder appendAllTo(final StringBuilder buf, final String sep, final Type... types) {
private static <T> StringBuilder appendAllTo(final StringBuilder buf, final String sep, final T... types) {
Validate.notEmpty(Validate.noNullElements(types));
if (types.length > 0) {
buf.append(toString(types[0]));
@ -1851,4 +1887,8 @@ public class TypeUtils {
return buf;
}
private static <T> String toString(T object) {
return object instanceof Type ? toString((Type) object) : object.toString();
}
}

View File

@ -781,6 +781,12 @@ public class TypeUtilsTest<B> {
Assert.assertTrue(TypeUtils.isAssignable(fromType, failingToType));
}
@Test
public void testLANG1348() throws Exception {
final Method method = Enum.class.getMethod("valueOf", Class.class, String.class);
Assert.assertEquals("T extends java.lang.Enum<T>", TypeUtils.toString(method.getGenericReturnType()));
}
public Iterable<? extends Map<Integer, ? extends Collection<?>>> iterable;
public static <G extends Comparable<G>> G stub() {