9
9
import java .lang .reflect .Type ;
10
10
import java .lang .reflect .TypeVariable ;
11
11
import java .lang .reflect .WildcardType ;
12
- import java .util .HashMap ;
13
- import java .util .Map ;
12
+ import java .util .ArrayList ;
14
13
import java .util .Objects ;
15
14
16
15
/**
@@ -57,12 +56,13 @@ static TypeResolutionContext narrowMethodTypeParameters(
57
56
return emptyTypeResCtxt ;
58
57
}
59
58
60
- // Construct a mapping from the method type variable names to the types requested by requestedType
59
+ // Construct TypeBindings based on the requested type, and type variables that occur in the generic return type.
61
60
// For example given requestedType: Foo<String, Int>
62
- // and method static <T, U> Foo<T, U> func(Object in)
63
- // This produces {T=String, U=Int}.
61
+ // and method static <T, U> Foo<T, U> func(Bar<T, U> in)
62
+ // Produces TypeBindings {T=String, U=Int}.
64
63
Type [] methodReturnTypeArguments = parameterizedGenericReturnType .getActualTypeArguments ();
65
- Map <String , JavaType > bindTargetsByName = new HashMap <>(methodReturnTypeArguments .length );
64
+ ArrayList <String > names = new ArrayList <>(methodTypeParameters .length );
65
+ ArrayList <JavaType > types = new ArrayList <>(methodTypeParameters .length );
66
66
for (int j = 0 ; j < methodReturnTypeArguments .length ; j ++) {
67
67
Type methodReturnTypeArgument = methodReturnTypeArguments [j ];
68
68
// Note: This strictly supports only TypeVariables, not wildcards with nested type variables
@@ -72,43 +72,33 @@ static TypeResolutionContext narrowMethodTypeParameters(
72
72
if (typeParameterName == null ) {
73
73
return emptyTypeResCtxt ;
74
74
}
75
- // If the type parameter name is not present in the method type parameters we
76
- // fall back to default type handling.
77
- if (! containsName ( methodTypeParameters , typeParameterName )) {
78
- return emptyTypeResCtxt ;
75
+
76
+ // Avoid duplicates
77
+ if (names . contains ( typeParameterName )) {
78
+ continue ;
79
79
}
80
+
80
81
JavaType bindTarget = requestedType .getBindings ().getBoundType (j );
81
82
if (bindTarget == null ) {
82
83
return emptyTypeResCtxt ;
83
84
}
84
- bindTargetsByName .put (typeParameterName , bindTarget );
85
- }
86
- }
87
- boolean appliedAtLeastOneBinding = false ;
88
- JavaType [] bindings = new JavaType [methodTypeParameters .length ];
89
- for (int j = 0 ; j < methodTypeParameters .length ; j ++) {
90
- TypeVariable <Method > methodTypeVariable = methodTypeParameters [j ];
91
- JavaType typeBindingBasedOnRequest = bindTargetsByName .get (methodTypeVariable .getName ());
92
- Type [] bounds = methodTypeVariable .getBounds ();
93
- // Use the propagated type information if it exists, otherwise fall back to bounds provided by the method.
94
- if (typeBindingBasedOnRequest == null
95
- // The method level bindings are used if they're narrower than the requested type
96
- || !pessimisticallyValidateBounds (emptyTypeResCtxt , typeBindingBasedOnRequest , bounds )) {
97
- if (bounds .length == 1 ) {
98
- typeBindingBasedOnRequest = emptyTypeResCtxt .resolveType (bounds [0 ]);
99
- } else {
85
+ // If the type parameter name is not present in the method type parameters we
86
+ // fall back to default type handling.
87
+ TypeVariable <?> methodTypeVariable = findByName (methodTypeParameters , typeParameterName );
88
+ if (methodTypeVariable == null ) {
100
89
return emptyTypeResCtxt ;
101
90
}
102
- } else {
103
- appliedAtLeastOneBinding = true ;
91
+ if (pessimisticallyValidateBounds (emptyTypeResCtxt , bindTarget , methodTypeVariable .getBounds ())) {
92
+ names .add (methodTypeVariable .getName ());
93
+ types .add (bindTarget );
94
+ }
104
95
}
105
- bindings [j ] = typeBindingBasedOnRequest ;
106
96
}
107
97
// Fall back to default handling if no specific types from the requestedType are used
108
- if (! appliedAtLeastOneBinding ) {
98
+ if (names . isEmpty () ) {
109
99
return emptyTypeResCtxt ;
110
100
}
111
- TypeBindings newTypeBindings = TypeBindings .create (candidate , bindings );
101
+ TypeBindings newTypeBindings = TypeBindings .create (names , types );
112
102
return new TypeResolutionContext .Basic (typeFactory , newTypeBindings );
113
103
}
114
104
@@ -185,16 +175,16 @@ private static boolean pessimisticallyValidateBound(
185
175
return true ;
186
176
}
187
177
188
- private static boolean containsName (TypeVariable <?>[] typeVariables , String name ) {
178
+ private static TypeVariable <?> findByName (TypeVariable <?>[] typeVariables , String name ) {
189
179
if (typeVariables == null || name == null ) {
190
- return false ;
180
+ return null ;
191
181
}
192
182
for (TypeVariable <?> typeVariable : typeVariables ) {
193
183
if (name .equals (typeVariable .getName ())) {
194
- return true ;
184
+ return typeVariable ;
195
185
}
196
186
}
197
- return false ;
187
+ return null ;
198
188
}
199
189
200
190
private MethodGenericTypeResolver () {
0 commit comments