Browse Source

Support variable resolution of wildcard types

Includes cleanup of "varaible" typos in ResolvableTypeTests.

Closes gh-24150
pull/27217/head
Juergen Hoeller 6 years ago
parent
commit
197dbffe20
  1. 14
      spring-core/src/main/java/org/springframework/core/ResolvableType.java
  2. 29
      spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java

14
spring-core/src/main/java/org/springframework/core/ResolvableType.java

@ -872,6 +872,12 @@ public class ResolvableType implements Serializable { @@ -872,6 +872,12 @@ public class ResolvableType implements Serializable {
return forType(ownerType, this.variableResolver).resolveVariable(variable);
}
}
if (this.type instanceof WildcardType) {
ResolvableType resolved = resolveType().resolveVariable(variable);
if (resolved != null) {
return resolved;
}
}
if (this.variableResolver != null) {
return this.variableResolver.resolveVariable(variable);
}
@ -997,7 +1003,7 @@ public class ResolvableType implements Serializable { @@ -997,7 +1003,7 @@ public class ResolvableType implements Serializable {
* {@link Class#isAssignableFrom}, which this serves as a wrapper for.
* For example: {@code ResolvableType.forRawClass(List.class)}.
* @param clazz the class to introspect ({@code null} is semantically
* equivalent to {@code Object.class} for typical use cases here}
* equivalent to {@code Object.class} for typical use cases here)
* @return a {@link ResolvableType} for the specified class
* @since 4.2
* @see #forClass(Class)
@ -1485,10 +1491,10 @@ public class ResolvableType implements Serializable { @@ -1485,10 +1491,10 @@ public class ResolvableType implements Serializable {
@Override
@Nullable
public ResolvableType resolveVariable(TypeVariable<?> variable) {
TypeVariable<?> variableToCompare = SerializableTypeWrapper.unwrap(variable);
for (int i = 0; i < this.variables.length; i++) {
TypeVariable<?> v1 = SerializableTypeWrapper.unwrap(this.variables[i]);
TypeVariable<?> v2 = SerializableTypeWrapper.unwrap(variable);
if (ObjectUtils.nullSafeEquals(v1, v2)) {
TypeVariable<?> resolvedVariable = SerializableTypeWrapper.unwrap(this.variables[i]);
if (ObjectUtils.nullSafeEquals(resolvedVariable, variableToCompare)) {
return this.generics[i];
}
}

29
spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java

@ -684,38 +684,31 @@ public class ResolvableTypeTests { @@ -684,38 +684,31 @@ public class ResolvableTypeTests {
@Test
public void resolveBoundedTypeVariableResult() throws Exception {
ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("boundedTypeVaraibleResult"));
ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("boundedTypeVariableResult"));
assertThat(type.resolve(), equalTo((Class) CharSequence.class));
}
@Test
public void resolveVariableNotFound() throws Exception {
ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("typedReturn"));
assertThat(type.resolve(), nullValue());
public void resolveBoundedTypeVariableWildcardResult() throws Exception {
ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("boundedTypeVariableWildcardResult"));
assertThat(type.getGeneric(1).asCollection().resolveGeneric(), equalTo((Class) CharSequence.class));
}
@Test
public void resolveTypeVaraibleFromMethodReturn() throws Exception {
public void resolveVariableNotFound() throws Exception {
ResolvableType type = ResolvableType.forMethodReturnType(Methods.class.getMethod("typedReturn"));
assertThat(type.resolve(), nullValue());
}
@Test
public void resolveTypeVaraibleFromMethodReturnWithInstanceClass() throws Exception {
ResolvableType type = ResolvableType.forMethodReturnType(
Methods.class.getMethod("typedReturn"), TypedMethods.class);
assertThat(type.resolve(), equalTo((Class) String.class));
}
@Test
public void resolveTypeVaraibleFromSimpleInterfaceType() {
public void resolveTypeVariableFromSimpleInterfaceType() {
ResolvableType type = ResolvableType.forClass(
MySimpleInterfaceType.class).as(MyInterfaceType.class);
assertThat(type.resolveGeneric(), equalTo((Class) String.class));
}
@Test
public void resolveTypeVaraibleFromSimpleCollectionInterfaceType() {
public void resolveTypeVariableFromSimpleCollectionInterfaceType() {
ResolvableType type = ResolvableType.forClass(
MyCollectionInterfaceType.class).as(MyInterfaceType.class);
assertThat(type.resolveGeneric(), equalTo((Class) Collection.class));
@ -723,14 +716,14 @@ public class ResolvableTypeTests { @@ -723,14 +716,14 @@ public class ResolvableTypeTests {
}
@Test
public void resolveTypeVaraibleFromSimpleSuperclassType() {
public void resolveTypeVariableFromSimpleSuperclassType() {
ResolvableType type = ResolvableType.forClass(
MySimpleSuperclassType.class).as(MySuperclassType.class);
assertThat(type.resolveGeneric(), equalTo((Class) String.class));
}
@Test
public void resolveTypeVaraibleFromSimpleCollectionSuperclassType() {
public void resolveTypeVariableFromSimpleCollectionSuperclassType() {
ResolvableType type = ResolvableType.forClass(
MyCollectionSuperclassType.class).as(MySuperclassType.class);
assertThat(type.resolveGeneric(), equalTo((Class) Collection.class));
@ -1459,7 +1452,9 @@ public class ResolvableTypeTests { @@ -1459,7 +1452,9 @@ public class ResolvableTypeTests {
void charSequenceParameter(List<CharSequence> cs);
<R extends CharSequence & Serializable> R boundedTypeVaraibleResult();
<R extends CharSequence & Serializable> R boundedTypeVariableResult();
Map<String, ? extends List<? extends CharSequence>> boundedTypeVariableWildcardResult();
void nested(Map<Map<String, Integer>, Map<Byte, Long>> p);

Loading…
Cancel
Save