Skip to content

Commit 993a680

Browse files
author
Drozdov Artyom
committed
fix: work around for buggy eclipse JDT-APT implementation of Types.asMemberOf
1 parent dfa270d commit 993a680

1 file changed

Lines changed: 63 additions & 16 deletions

File tree

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/APTCodeModelHelper.java‎

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,21 @@
1818
import java.io.StringWriter;
1919
import java.lang.reflect.Field;
2020
import java.util.ArrayList;
21+
import java.util.Collections;
22+
import java.util.HashMap;
23+
import java.util.LinkedHashMap;
2124
import java.util.List;
25+
import java.util.Map;
2226

2327
import javax.lang.model.element.Element;
2428
import javax.lang.model.element.ExecutableElement;
2529
import javax.lang.model.element.TypeElement;
30+
import javax.lang.model.element.TypeParameterElement;
2631
import javax.lang.model.element.VariableElement;
2732
import javax.lang.model.type.ArrayType;
2833
import javax.lang.model.type.DeclaredType;
29-
import javax.lang.model.type.ExecutableType;
3034
import javax.lang.model.type.TypeKind;
3135
import javax.lang.model.type.TypeMirror;
32-
import javax.lang.model.type.TypeVariable;
3336
import javax.lang.model.type.WildcardType;
3437
import javax.lang.model.util.ElementFilter;
3538
import javax.lang.model.util.Types;
@@ -56,6 +59,10 @@
5659
public 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

Comments
 (0)