1818import java .io .StringWriter ;
1919import java .lang .reflect .Field ;
2020import java .util .ArrayList ;
21+ import java .util .Collections ;
22+ import java .util .HashMap ;
23+ import java .util .LinkedHashMap ;
2124import java .util .List ;
25+ import java .util .Map ;
2226
2327import javax .lang .model .element .Element ;
2428import javax .lang .model .element .ExecutableElement ;
2529import javax .lang .model .element .TypeElement ;
30+ import javax .lang .model .element .TypeParameterElement ;
2631import javax .lang .model .element .VariableElement ;
2732import javax .lang .model .type .ArrayType ;
2833import javax .lang .model .type .DeclaredType ;
29- import javax .lang .model .type .ExecutableType ;
3034import javax .lang .model .type .TypeKind ;
3135import javax .lang .model .type .TypeMirror ;
32- import javax .lang .model .type .TypeVariable ;
3336import javax .lang .model .type .WildcardType ;
3437import javax .lang .model .util .ElementFilter ;
3538import javax .lang .model .util .Types ;
5659public class APTCodeModelHelper {
5760
5861 public JClass typeMirrorToJClass (TypeMirror type , GeneratedClassHolder holder ) {
62+ return typeMirrorToJClass (type , holder , Collections .<String , TypeMirror >emptyMap ());
63+ }
64+
65+ public JClass typeMirrorToJClass (TypeMirror type , GeneratedClassHolder holder , Map <String , TypeMirror > substitute ) {
5966
6067 if (type instanceof DeclaredType ) {
6168 DeclaredType declaredType = (DeclaredType ) type ;
@@ -68,7 +75,7 @@ public JClass typeMirrorToJClass(TypeMirror type, GeneratedClassHolder holder) {
6875
6976 List <JClass > typeArgumentJClasses = new ArrayList <JClass >();
7077 for (TypeMirror typeArgument : typeArguments ) {
71- typeArgumentJClasses .add (typeMirrorToJClass (typeArgument , holder ));
78+ typeArgumentJClasses .add (typeMirrorToJClass (typeArgument , holder , substitute ));
7279 }
7380 if (typeArgumentJClasses .size () > 0 ) {
7481 declaredClass = declaredClass .narrow (typeArgumentJClasses );
@@ -84,23 +91,27 @@ public JClass typeMirrorToJClass(TypeMirror type, GeneratedClassHolder holder) {
8491 if (bound == null ) {
8592 return holder .classes ().OBJECT .wildcard ();
8693 }
87- return superWildcard (typeMirrorToJClass (bound , holder ));
94+ return superWildcard (typeMirrorToJClass (bound , holder , substitute ));
8895 }
8996
9097 TypeMirror extendsBound = wildcardType .getExtendsBound ();
9198
9299 if (extendsBound == null ) {
93100 return holder .classes ().OBJECT .wildcard ();
94101 } else {
95- return typeMirrorToJClass (extendsBound , holder ).wildcard ();
102+ return typeMirrorToJClass (extendsBound , holder , substitute ).wildcard ();
96103 }
97104 } else if (type instanceof ArrayType ) {
98105 ArrayType arrayType = (ArrayType ) type ;
99106
100- JClass refClass = typeMirrorToJClass (arrayType .getComponentType (), holder );
107+ JClass refClass = typeMirrorToJClass (arrayType .getComponentType (), holder , substitute );
101108
102109 return refClass .array ();
103110 } else {
111+ TypeMirror substituted = substitute .get (type .toString ());
112+ if (substituted != null ) {
113+ return typeMirrorToJClass (substituted , holder , substitute );
114+ }
104115 return holder .refClass (type .toString ());
105116 }
106117 }
@@ -119,22 +130,60 @@ public Parameter(String name, JClass jClass) {
119130 }
120131 }
121132
133+ private Map <String , TypeMirror > getActualTypes (Types typeUtils , DeclaredType baseClass , TypeMirror actualClass ) {
134+ List <TypeMirror > superTypes = new ArrayList <TypeMirror >();
135+ superTypes .add (actualClass );
136+ while (!superTypes .isEmpty ()) {
137+ TypeMirror x = superTypes .remove (0 );
138+ if (typeUtils .isSameType (typeUtils .erasure (x ), typeUtils .erasure (baseClass ))) {
139+ DeclaredType type = (DeclaredType ) x ;
140+ Map <String , TypeMirror > actualTypes = new HashMap <String , TypeMirror >();
141+ for (int i = 0 ; i < type .getTypeArguments ().size (); i ++) {
142+ TypeMirror actualArg = type .getTypeArguments ().get (i );
143+ TypeMirror formalArg = baseClass .getTypeArguments ().get (i );
144+ if (!typeUtils .isSameType (actualArg , formalArg )) {
145+ actualTypes .put (formalArg .toString (), actualArg );
146+ }
147+ }
148+ return actualTypes ;
149+ }
150+ superTypes .addAll (typeUtils .directSupertypes (x ));
151+ }
152+ return Collections .emptyMap ();
153+ }
154+
122155 public JMethod overrideAnnotatedMethod (ExecutableElement executableElement , GeneratedClassHolder holder ) {
156+ TypeMirror generatedClass = holder .getAnnotatedElement ().asType ();
157+ DeclaredType originalClass = (DeclaredType ) executableElement .getEnclosingElement ().asType ();
123158
124- DeclaredType generatedClass = (DeclaredType ) holder .getAnnotatedElement ().asType ();
125159 Types typeUtils = holder .processingEnvironment ().getTypeUtils ();
126- ExecutableType executableType = (ExecutableType ) typeUtils .asMemberOf (generatedClass , executableElement );
160+
161+ Map <String , TypeMirror > actualTypes = getActualTypes (typeUtils , originalClass , generatedClass );
162+ Map <String , JClass > methodTypes = new LinkedHashMap <String , JClass >();
163+
164+ for (TypeParameterElement typeParameter : executableElement .getTypeParameters ()) {
165+ List <? extends TypeMirror > bounds = typeParameter .getBounds ();
166+ JClass jClassBounds ;
167+ if (bounds .isEmpty ()) {
168+ jClassBounds = holder .classes ().OBJECT ;
169+ } else {
170+ //TODO resolve <T extends A&B> bounds
171+ jClassBounds = typeMirrorToJClass (bounds .get (0 ), holder , actualTypes );
172+ }
173+ methodTypes .put (typeParameter .toString (), jClassBounds );
174+ }
175+
176+ actualTypes .keySet ().removeAll (methodTypes .keySet ());
127177
128178 String methodName = executableElement .getSimpleName ().toString ();
129- JClass returnType = typeMirrorToJClass (executableType .getReturnType (), holder );
179+ JClass returnType = typeMirrorToJClass (executableElement .getReturnType (), holder , actualTypes );
130180
131181 List <Parameter > parameters = new ArrayList <Parameter >();
132182 for (int i = 0 ; i < executableElement .getParameters ().size (); i ++) {
133183 VariableElement parameter = executableElement .getParameters ().get (i );
134- TypeMirror parameterType = executableType .getParameterTypes ().get (i );
135184
136185 String parameterName = parameter .getSimpleName ().toString ();
137- JClass parameterClass = typeMirrorToJClass (parameterType , holder );
186+ JClass parameterClass = typeMirrorToJClass (parameter . asType () , holder , actualTypes );
138187 parameters .add (new Parameter (parameterName , parameterClass ));
139188 }
140189
@@ -147,18 +196,16 @@ public JMethod overrideAnnotatedMethod(ExecutableElement executableElement, Gene
147196 JMethod method = holder .getGeneratedClass ().method (JMod .PUBLIC , returnType , methodName );
148197 method .annotate (Override .class );
149198
150- for (TypeVariable typeParameter : executableType .getTypeVariables ()) {
151- TypeMirror bound = typeParameter .getUpperBound ();
152- JClass jClassBounds = typeMirrorToJClass (bound , holder );
153- method .generify (typeParameter .toString (), jClassBounds );
199+ for (Map .Entry <String , JClass > typeDeclaration : methodTypes .entrySet ()) {
200+ method .generify (typeDeclaration .getKey (), typeDeclaration .getValue ());
154201 }
155202
156203 for (Parameter parameter : parameters ) {
157204 method .param (JMod .FINAL , parameter .jClass , parameter .name );
158205 }
159206
160207 for (TypeMirror superThrownType : executableElement .getThrownTypes ()) {
161- JClass thrownType = typeMirrorToJClass (superThrownType , holder );
208+ JClass thrownType = typeMirrorToJClass (superThrownType , holder , actualTypes );
162209 method ._throws (thrownType );
163210 }
164211
0 commit comments