Skip to content

Commit 091888c

Browse files
author
Drozdov Artyom
committed
add: support for generics in beans
add: <? super T> bounds for extending
1 parent 017b589 commit 091888c

8 files changed

Lines changed: 153 additions & 17 deletions

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.sun.codemodel;
2+
3+
import java.util.Iterator;
4+
import java.util.List;
5+
6+
// TODO : At his time (01/2013), it is not possible to handle the
7+
// super bound because code model does not offer a way to model
8+
// statement like " ? super X"
9+
// (see http://java.net/jira/browse/CODEMODEL-11)
10+
//
11+
// This class is a hack against it.
12+
// So, if it will be fixed in code model - just remove this
13+
public class JSuperWildcard extends JClass {
14+
15+
private final JClass bound;
16+
17+
public JSuperWildcard(JClass bound) {
18+
super(bound.owner());
19+
this.bound = bound;
20+
}
21+
22+
public String name() {
23+
return "? super "+ bound.name();
24+
}
25+
26+
public String fullName() {
27+
return "? super "+ bound.fullName();
28+
}
29+
30+
public JPackage _package() {
31+
return null;
32+
}
33+
34+
/**
35+
* Returns the class bound of this variable.
36+
*
37+
* <p>
38+
* If no bound is given, this method returns {@link Object}.
39+
*/
40+
public JClass _extends() {
41+
if(bound !=null)
42+
return bound;
43+
else
44+
return owner().ref(Object.class);
45+
}
46+
47+
/**
48+
* Returns the interface bounds of this variable.
49+
*/
50+
public Iterator<JClass> _implements() {
51+
return bound._implements();
52+
}
53+
54+
public boolean isInterface() {
55+
return false;
56+
}
57+
58+
public boolean isAbstract() {
59+
return false;
60+
}
61+
62+
protected JClass substituteParams(JTypeVar[] variables, List<JClass> bindings) {
63+
JClass nb = bound.substituteParams(variables,bindings);
64+
if(nb== bound)
65+
return this;
66+
else
67+
return nb.wildcard();
68+
}
69+
70+
public void generate(JFormatter f) {
71+
if(bound._extends()==null)
72+
f.p("?"); // instead of "? extends Object"
73+
else
74+
f.p("? super").g(bound);
75+
}
76+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/BeanHandler.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import javax.annotation.processing.ProcessingEnvironment;
2323
import javax.lang.model.element.Element;
2424
import javax.lang.model.type.TypeMirror;
25+
import javax.lang.model.util.Types;
2526

2627
import org.androidannotations.annotations.Bean;
2728
import org.androidannotations.annotations.EBean;
@@ -60,6 +61,7 @@ public void process(Element element, EComponentHolder holder) throws Exception {
6061
TypeMirror elementType = annotationHelper.extractAnnotationClassParameter(element);
6162
if (elementType == null) {
6263
elementType = element.asType();
64+
elementType = holder.processingEnvironment().getTypeUtils().erasure(elementType);
6365
}
6466

6567
String fieldName = element.getSimpleName().toString();

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

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727
import javax.lang.model.element.VariableElement;
2828
import javax.lang.model.type.ArrayType;
2929
import javax.lang.model.type.DeclaredType;
30+
import javax.lang.model.type.ExecutableType;
3031
import javax.lang.model.type.TypeKind;
3132
import javax.lang.model.type.TypeMirror;
3233
import javax.lang.model.type.WildcardType;
3334
import javax.lang.model.util.ElementFilter;
35+
import javax.lang.model.util.Types;
3436

3537
import org.androidannotations.holder.EComponentHolder;
3638
import org.androidannotations.holder.GeneratedClassHolder;
@@ -47,6 +49,7 @@
4749
import com.sun.codemodel.JMethod;
4850
import com.sun.codemodel.JMod;
4951
import com.sun.codemodel.JStatement;
52+
import com.sun.codemodel.JSuperWildcard;
5053
import com.sun.codemodel.JType;
5154
import com.sun.codemodel.JVar;
5255

@@ -73,12 +76,17 @@ public JClass typeMirrorToJClass(TypeMirror type, GeneratedClassHolder holder) {
7376

7477
return declaredClass;
7578
} else if (type instanceof WildcardType) {
76-
// TODO : At his time (01/2013), it is not possible to handle the
77-
// super bound because code model does not offer a way to model
78-
// statement like " ? super X"
79-
// (see http://java.net/jira/browse/CODEMODEL-11)
8079
WildcardType wildcardType = (WildcardType) type;
8180

81+
TypeMirror bound = wildcardType.getExtendsBound();
82+
if (bound == null) {
83+
bound = wildcardType.getSuperBound();
84+
if (bound == null) {
85+
throw new IllegalArgumentException("There are should be 'extends' or 'super' in the wildcard");
86+
}
87+
return superWildcard(typeMirrorToJClass(bound, holder));
88+
}
89+
8290
TypeMirror extendsBound = wildcardType.getExtendsBound();
8391

8492
if (extendsBound == null) {
@@ -97,6 +105,10 @@ public JClass typeMirrorToJClass(TypeMirror type, GeneratedClassHolder holder) {
97105
}
98106
}
99107

108+
private JClass superWildcard(final JClass bound) {
109+
return new JSuperWildcard(bound);
110+
}
111+
100112
public static class Parameter {
101113
public final String name;
102114
public final JClass jClass;
@@ -109,13 +121,20 @@ public Parameter(String name, JClass jClass) {
109121

110122
public JMethod overrideAnnotatedMethod(ExecutableElement executableElement, GeneratedClassHolder holder) {
111123

124+
DeclaredType generatedClass = (DeclaredType) holder.getAnnotatedElement().asType();
125+
Types typeUtils = holder.processingEnvironment().getTypeUtils();
126+
ExecutableType generalisedElement = (ExecutableType) typeUtils.asMemberOf(generatedClass, executableElement);
127+
112128
String methodName = executableElement.getSimpleName().toString();
113-
JClass returnType = typeMirrorToJClass(executableElement.getReturnType(), holder);
129+
JClass returnType = typeMirrorToJClass(generalisedElement.getReturnType(), holder);
114130

115131
List<Parameter> parameters = new ArrayList<Parameter>();
116-
for (VariableElement parameter : executableElement.getParameters()) {
117-
String parameterName = parameter.getSimpleName().toString();
118-
JClass parameterClass = typeMirrorToJClass(parameter.asType(), holder);
132+
for (int i = 0; i < executableElement.getParameters().size(); i++) {
133+
VariableElement parameter = executableElement.getParameters().get(i);
134+
TypeMirror parameterType = generalisedElement.getParameterTypes().get(i);
135+
136+
String parameterName = parameter.getSimpleName().toString();
137+
JClass parameterClass = typeMirrorToJClass(parameterType, holder);
119138
parameters.add(new Parameter(parameterName, parameterClass));
120139
}
121140

@@ -128,11 +147,9 @@ public JMethod overrideAnnotatedMethod(ExecutableElement executableElement, Gene
128147
JMethod method = holder.getGeneratedClass().method(JMod.PUBLIC, returnType, methodName);
129148
method.annotate(Override.class);
130149

131-
for (VariableElement parameter : executableElement.getParameters()) {
132-
String parameterName = parameter.getSimpleName().toString();
133-
JClass parameterClass = typeMirrorToJClass(parameter.asType(), holder);
134-
method.param(JMod.FINAL, parameterClass, parameterName);
135-
}
150+
for (Parameter parameter : parameters) {
151+
method.param(JMod.FINAL, parameter.jClass, parameter.name);
152+
}
136153

137154
for (TypeMirror superThrownType : executableElement.getThrownTypes()) {
138155
JClass thrownType = typeMirrorToJClass(superThrownType, holder);

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/BaseGeneratedClassHolder.java‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
import javax.annotation.processing.ProcessingEnvironment;
2222
import javax.lang.model.element.TypeElement;
23+
import javax.lang.model.element.TypeParameterElement;
24+
import javax.lang.model.util.Elements;
25+
import javax.lang.model.util.Types;
2326

2427
import org.androidannotations.helper.ModelConstants;
2528
import org.androidannotations.process.ProcessHolder;
@@ -43,9 +46,13 @@ public BaseGeneratedClassHolder(ProcessHolder processHolder, TypeElement annotat
4346

4447
protected void setGeneratedClass() throws Exception {
4548
String annotatedComponentQualifiedName = annotatedElement.getQualifiedName().toString();
46-
String subComponentQualifiedName = annotatedComponentQualifiedName + ModelConstants.GENERATION_SUFFIX;
47-
JClass annotatedComponent = codeModel().directClass(annotatedComponentQualifiedName);
49+
String subComponentQualifiedName = annotatedComponentQualifiedName + ModelConstants.GENERATION_SUFFIX;
50+
JClass annotatedComponent = codeModel().directClass(annotatedElement.asType().toString());
51+
4852
generatedClass = codeModel()._class(PUBLIC | FINAL, subComponentQualifiedName, ClassType.CLASS);
53+
for (TypeParameterElement typeParam : annotatedElement.getTypeParameters()) {
54+
generatedClass.generify(typeParam.getSimpleName().toString());
55+
}
4956
generatedClass._extends(annotatedComponent);
5057
}
5158

‎AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/EBeanTest.java‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ public void setup() {
3030

3131
@Test
3232
public void activity_subclass_in_manifest_compiles() {
33-
assertCompilationSuccessful(compileFiles(SomeActivity.class, SomeImplementation.class));
34-
}
33+
assertCompilationSuccessful(compileFiles(
34+
SomeActivity.class,
35+
SomeImplementation.class,
36+
SomeGenericBean.class,
37+
SomeGenericBeanExt.class));
38+
}
3539

3640
}

‎AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/SomeActivity.java‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ public class SomeActivity extends Activity {
2828
@Bean(SomeImplementation.class)
2929
SomeInterface someInterface;
3030

31+
@Bean
32+
SomeGenericBean<Object> objectSomeGenericBean;
33+
3134
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.androidannotations.ebean;
2+
3+
import org.androidannotations.annotations.Background;
4+
import org.androidannotations.annotations.EBean;
5+
6+
import java.util.List;
7+
8+
@EBean
9+
public class SomeGenericBean<T> {
10+
11+
@Background
12+
void someMethod(List<? super T> list){
13+
14+
}
15+
16+
void someOtherMethod(List<? super T> list){
17+
18+
}
19+
20+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.androidannotations.ebean;
2+
3+
import org.androidannotations.annotations.EBean;
4+
5+
@EBean
6+
public class SomeGenericBeanExt extends SomeGenericBean<String> {
7+
}

0 commit comments

Comments
 (0)