Skip to content

Commit 9713b64

Browse files
committed
Merge pull request androidannotations#1117 from Artyomcool/1077-fragment-generics
fix: generic issues in EFragment
2 parents 65f610a + 60fd32d commit 9713b64

7 files changed

Lines changed: 67 additions & 31 deletions

File tree

AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/ExtraHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import javax.annotation.processing.ProcessingEnvironment;
2525
import javax.lang.model.element.Element;
26+
import javax.lang.model.type.TypeMirror;
2627

2728
import org.androidannotations.annotations.Extra;
2829
import org.androidannotations.helper.APTCodeModelHelper;
@@ -94,7 +95,8 @@ private void injectExtraInComponent(Element element, HasExtras hasExtras, JField
9495
JVar extras = hasExtras.getInjectExtras();
9596
JBlock injectExtrasBlock = hasExtras.getInjectExtrasBlock();
9697

97-
BundleHelper bundleHelper = new BundleHelper(annotationHelper, element);
98+
TypeMirror type = codeModelHelper.getActualType(element, hasExtras);
99+
BundleHelper bundleHelper = new BundleHelper(annotationHelper, type);
98100

99101
JFieldRef extraField = JExpr.ref(fieldName);
100102
JBlock ifContainsKey = injectExtrasBlock._if(JExpr.invoke(extras, "containsKey").arg(extraKeyStaticField))._then();

AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/FragmentArgHandler.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ public void process(Element element, EFragmentHolder holder) {
6060
argKey = fieldName;
6161
}
6262

63-
BundleHelper bundleHelper = new BundleHelper(annotationHelper, element);
63+
TypeMirror actualType = codeModelHelper.getActualType(element, holder);
64+
65+
BundleHelper bundleHelper = new BundleHelper(annotationHelper, actualType);
6466
JFieldVar argKeyStaticField = createStaticArgField(holder, argKey, fieldName);
6567
injectArgInComponent(element, holder, bundleHelper, argKeyStaticField, fieldName);
6668
createBuilderInjectionMethod(element, holder, bundleHelper, argKeyStaticField, fieldName);
@@ -85,7 +87,8 @@ private void injectArgInComponent(Element element, EFragmentHolder holder, Bundl
8587
JExpression restoreMethodCall = JExpr.invoke(bundle, bundleHelper.getMethodNameToRestore()).arg(extraKeyStaticField);
8688
if (bundleHelper.restoreCallNeedCastStatement()) {
8789

88-
JClass jclass = codeModelHelper.typeMirrorToJClass(element.asType(), holder);
90+
TypeMirror type = codeModelHelper.getActualType(element, holder);
91+
JClass jclass = codeModelHelper.typeMirrorToJClass(type, holder);
8992
restoreMethodCall = JExpr.cast(jclass, restoreMethodCall);
9093

9194
if (bundleHelper.restoreCallNeedsSuppressWarning()) {
@@ -102,8 +105,8 @@ private void injectArgInComponent(Element element, EFragmentHolder holder, Bundl
102105
private void createBuilderInjectionMethod(Element element, EFragmentHolder holder, BundleHelper bundleHelper, JFieldVar argKeyStaticField, String fieldName) {
103106
JDefinedClass builderClass = holder.getBuilderClass();
104107
JFieldRef builderArgsField = holder.getBuilderArgsField();
105-
TypeMirror elementType = element.asType();
106-
JClass paramClass = codeModelHelper.typeMirrorToJClass(elementType, holder);
108+
TypeMirror type = codeModelHelper.getActualType(element, holder);
109+
JClass paramClass = codeModelHelper.typeMirrorToJClass(type, holder);
107110

108111
JMethod method = builderClass.method(PUBLIC, builderClass, fieldName);
109112
JVar arg = method.param(paramClass, fieldName);

AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/InstanceStateHandler.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import javax.annotation.processing.ProcessingEnvironment;
2121
import javax.lang.model.element.Element;
22+
import javax.lang.model.type.TypeMirror;
2223

2324
import org.androidannotations.annotations.InstanceState;
2425
import org.androidannotations.helper.APTCodeModelHelper;
@@ -63,9 +64,12 @@ public void process(Element element, HasInstanceState holder) {
6364
JVar restoreStateBundleParam = holder.getRestoreStateBundleParam();
6465

6566
AnnotationHelper annotationHelper = new AnnotationHelper(processingEnv);
66-
BundleHelper bundleHelper = new BundleHelper(annotationHelper, element);
6767
APTCodeModelHelper codeModelHelper = new APTCodeModelHelper();
6868

69+
TypeMirror type = codeModelHelper.getActualType(element, holder);
70+
71+
BundleHelper bundleHelper = new BundleHelper(annotationHelper, type);
72+
6973
JFieldRef ref = ref(fieldName);
7074
saveStateBody.invoke(saveStateBundleParam, bundleHelper.getMethodNameToSave()).arg(fieldName).arg(ref);
7175

AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/ServiceActionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ private void addActionInOnHandleIntent(EIntentServiceHolder holder, ExecutableEl
9898
String extraParamName = paramName + "Extra";
9999
JFieldVar paramVar = getStaticExtraField(holder, paramName);
100100
JClass extraParamClass = codeModelHelper.typeMirrorToJClass(param.asType(), holder);
101-
BundleHelper bundleHelper = new BundleHelper(annotationHelper, param);
101+
BundleHelper bundleHelper = new BundleHelper(annotationHelper, param.asType());
102102

103103
JExpression getExtraExpression = JExpr.invoke(extras, bundleHelper.getMethodNameToRestore()).arg(paramVar);
104104
if (bundleHelper.restoreCallNeedCastStatement()) {

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,4 +510,16 @@ public JExpression litObject(Object o) {
510510
return lit((String) o);
511511
}
512512
}
513+
514+
//TODO it would be nice to cache the result map for better performance
515+
public TypeMirror getActualType(Element element, GeneratedClassHolder holder) {
516+
Types types = holder.processingEnvironment().getTypeUtils();
517+
DeclaredType typeMirror = (DeclaredType) element.getEnclosingElement().asType();
518+
TypeMirror annotatedClass = holder.getAnnotatedElement().asType();
519+
520+
Map<String, TypeMirror> actualTypes = getActualTypes(types, typeMirror, annotatedClass);
521+
522+
TypeMirror type = actualTypes.get(element.asType().toString());
523+
return type == null ? element.asType() : type;
524+
}
513525
}

AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/BundleHelper.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,20 +77,20 @@ public class BundleHelper {
7777
private String methodNameToSave;
7878
private String methodNameToRestore;
7979

80-
public BundleHelper(AnnotationHelper helper, Element element) {
80+
public BundleHelper(AnnotationHelper helper, TypeMirror element) {
8181
annotationHelper = helper;
8282

83-
String typeString = element.asType().toString();
83+
String typeString = element.toString();
8484
TypeElement elementType = annotationHelper.typeElementFromQualifiedName(typeString);
8585

8686
if (methodSuffixNameByTypeName.containsKey(typeString)) {
8787

8888
methodNameToSave = "put" + methodSuffixNameByTypeName.get(typeString);
8989
methodNameToRestore = "get" + methodSuffixNameByTypeName.get(typeString);
9090

91-
} else if (element.asType().getKind() == TypeKind.ARRAY) {
91+
} else if (element.getKind() == TypeKind.ARRAY) {
9292

93-
ArrayType arrayType = (ArrayType) element.asType();
93+
ArrayType arrayType = (ArrayType) element;
9494

9595
boolean hasTypeArguments = false;
9696
if (arrayType.getComponentType() instanceof DeclaredType) {
@@ -119,9 +119,8 @@ public BundleHelper(AnnotationHelper helper, Element element) {
119119
} else if (typeString.startsWith(CanonicalNameConstants.ARRAYLIST)) {
120120

121121
boolean hasTypeArguments = false;
122-
TypeMirror elementAsType = element.asType();
123-
if (elementAsType instanceof DeclaredType) {
124-
DeclaredType declaredType = (DeclaredType) elementAsType;
122+
if (element instanceof DeclaredType) {
123+
DeclaredType declaredType = (DeclaredType) element;
125124
List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
126125
if (typeArguments.size() == 1) {
127126
TypeMirror typeArgument = typeArguments.get(0);
@@ -154,10 +153,9 @@ public BundleHelper(AnnotationHelper helper, Element element) {
154153

155154
} else {
156155

157-
TypeMirror elementAsType = element.asType();
158156
boolean hasTypeArguments = false;
159-
if (elementAsType instanceof DeclaredType) {
160-
DeclaredType declaredType = (DeclaredType) elementAsType;
157+
if (element instanceof DeclaredType) {
158+
DeclaredType declaredType = (DeclaredType) element;
161159
typeString = declaredType.asElement().toString();
162160
elementType = annotationHelper.typeElementFromQualifiedName(typeString);
163161
hasTypeArguments = declaredType.getTypeArguments().size() > 0;

AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EFragmentHolder.java

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,13 @@
2828

2929
import javax.lang.model.element.TypeElement;
3030

31+
import com.sun.codemodel.*;
3132
import org.androidannotations.helper.ActionBarSherlockHelper;
3233
import org.androidannotations.helper.AnnotationHelper;
3334
import org.androidannotations.process.ProcessHolder;
3435

35-
import com.sun.codemodel.JBlock;
36-
import com.sun.codemodel.JClass;
37-
import com.sun.codemodel.JClassAlreadyExistsException;
38-
import com.sun.codemodel.JDefinedClass;
39-
import com.sun.codemodel.JExpr;
40-
import com.sun.codemodel.JFieldRef;
41-
import com.sun.codemodel.JFieldVar;
42-
import com.sun.codemodel.JMethod;
43-
import com.sun.codemodel.JMod;
44-
import com.sun.codemodel.JVar;
36+
import java.util.ArrayList;
37+
import java.util.List;
4538

4639
public class EFragmentHolder extends EComponentWithViewSupportHolder implements HasInstanceState, HasOptionsMenu, HasOnActivityResult, HasReceiverRegistration {
4740

@@ -50,6 +43,7 @@ public class EFragmentHolder extends EComponentWithViewSupportHolder implements
5043
private JVar inflater;
5144
private JVar container;
5245
private JDefinedClass fragmentBuilderClass;
46+
private JClass narrowBuilderClass;
5347
private JFieldRef fragmentArgumentsBuilderField;
5448
private JMethod injectArgsMethod;
5549
private JBlock injectArgsBlock;
@@ -124,27 +118,50 @@ private void setFindViewById() {
124118

125119
private void setFragmentBuilder() throws JClassAlreadyExistsException {
126120
fragmentBuilderClass = generatedClass._class(PUBLIC | STATIC, "FragmentBuilder_");
121+
122+
narrowBuilderClass = narrow(fragmentBuilderClass);
123+
124+
generify(fragmentBuilderClass);
127125
JClass superClass = refClass(org.androidannotations.api.builder.FragmentBuilder.class);
128-
superClass = superClass.narrow(fragmentBuilderClass, getAnnotatedClass());
126+
superClass = superClass.narrow(narrowBuilderClass, getAnnotatedClass());
129127
fragmentBuilderClass._extends(superClass);
130128
fragmentArgumentsBuilderField = ref("args");
131129
setFragmentBuilderBuild();
132130
setFragmentBuilderCreate();
133131
}
134132

133+
private JClass narrow(JClass toNarrow) {
134+
List<JClass> classes = new ArrayList<JClass>();
135+
for (JTypeVar type : generatedClass.typeParams()) {
136+
classes.add(codeModel().directClass(type.name()));
137+
}
138+
if (classes.isEmpty()) {
139+
return toNarrow;
140+
}
141+
return toNarrow.narrow(classes);
142+
}
143+
135144
private void setFragmentBuilderBuild() {
136145
JMethod method = fragmentBuilderClass.method(PUBLIC, generatedClass._extends(), "build");
137146
method.annotate(Override.class);
138147
JBlock body = method.body();
139148

140-
JVar fragment = body.decl(generatedClass, "fragment_", _new(generatedClass));
149+
JClass result = narrow(generatedClass);
150+
JVar fragment = body.decl(result, "fragment_", _new(result));
141151
body.invoke(fragment, "setArguments").arg(fragmentArgumentsBuilderField);
142152
body._return(fragment);
143153
}
144154

145155
private void setFragmentBuilderCreate() {
146-
JMethod method = generatedClass.method(STATIC | PUBLIC, fragmentBuilderClass, "builder");
147-
method.body()._return(_new(fragmentBuilderClass));
156+
JMethod method = generatedClass.method(STATIC | PUBLIC, narrowBuilderClass, "builder");
157+
generify(method);
158+
method.body()._return(_new(narrowBuilderClass));
159+
}
160+
161+
private void generify(JGenerifiable generifiable) {
162+
for (JTypeVar type : generatedClass.typeParams()) {
163+
generifiable.generify(type.name(), type._extends());
164+
}
148165
}
149166

150167
private void setOnCreateOptionsMenu() {

0 commit comments

Comments
 (0)