LANG-1348 - StackOverflowError on TypeUtils.toString(...) for a generic return type of Enum.valueOf (closes #292)
This commit is contained in:
parent
36217ee164
commit
cc6beb2d05
|
@ -1788,7 +1788,7 @@ public class TypeUtils {
|
||||||
|
|
||||||
final Type useOwner = p.getOwnerType();
|
final Type useOwner = p.getOwnerType();
|
||||||
final Class<?> raw = (Class<?>) p.getRawType();
|
final Class<?> raw = (Class<?>) p.getRawType();
|
||||||
final Type[] typeArguments = p.getActualTypeArguments();
|
|
||||||
if (useOwner == null) {
|
if (useOwner == null) {
|
||||||
buf.append(raw.getName());
|
buf.append(raw.getName());
|
||||||
} else {
|
} else {
|
||||||
|
@ -1800,10 +1800,46 @@ public class TypeUtils {
|
||||||
buf.append('.').append(raw.getSimpleName());
|
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();
|
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}.
|
* Format a {@link WildcardType} as a {@link String}.
|
||||||
* @param w {@code WildcardType} to format
|
* @param w {@code WildcardType} to format
|
||||||
|
@ -1840,7 +1876,7 @@ public class TypeUtils {
|
||||||
* @return {@code buf}
|
* @return {@code buf}
|
||||||
* @since 3.2
|
* @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));
|
Validate.notEmpty(Validate.noNullElements(types));
|
||||||
if (types.length > 0) {
|
if (types.length > 0) {
|
||||||
buf.append(toString(types[0]));
|
buf.append(toString(types[0]));
|
||||||
|
@ -1851,4 +1887,8 @@ public class TypeUtils {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <T> String toString(T object) {
|
||||||
|
return object instanceof Type ? toString((Type) object) : object.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -781,6 +781,12 @@ public class TypeUtilsTest<B> {
|
||||||
Assert.assertTrue(TypeUtils.isAssignable(fromType, failingToType));
|
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 Iterable<? extends Map<Integer, ? extends Collection<?>>> iterable;
|
||||||
|
|
||||||
public static <G extends Comparable<G>> G stub() {
|
public static <G extends Comparable<G>> G stub() {
|
||||||
|
|
Loading…
Reference in New Issue