AnnotationClass.java revision 91d538470c011e19fa4375cc3531b5dd9ae01d55
1199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong/*
2199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong * Copyright (C) 2015 The Android Open Source Project
3199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong *
4199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong * Licensed under the Apache License, Version 2.0 (the "License");
5199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong * you may not use this file except in compliance with the License.
6199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong * You may obtain a copy of the License at
7199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong *
8199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong *      http://www.apache.org/licenses/LICENSE-2.0
9199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong *
10199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong * Unless required by applicable law or agreed to in writing, software
11199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong * distributed under the License is distributed on an "AS IS" BASIS,
12199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong * See the License for the specific language governing permissions and
14199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong * limitations under the License.
15199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dong */
16199d1c131d29b5356f71fbd7826a592c1dd8575fJames Dongpackage android.databinding.tool.reflection.annotation;
170dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn
180dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport org.antlr.v4.codegen.model.decl.Decl;
190dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn
200dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport android.databinding.tool.reflection.ModelAnalyzer;
210dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport android.databinding.tool.reflection.ModelClass;
220dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport android.databinding.tool.reflection.ModelField;
23947f7824118f0e9b642df8760a8725a7eda59318Adam Powellimport android.databinding.tool.reflection.ModelMethod;
240dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport android.databinding.tool.reflection.TypeUtil;
250dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport android.databinding.tool.util.L;
260dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn
270dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport java.util.ArrayList;
280dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport java.util.List;
29be4e6aaa0252dd7da28b7aa85beba982538efa46Dianne Hackborn
300dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.element.Element;
310dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.element.ExecutableElement;
320dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.element.TypeElement;
330dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.element.VariableElement;
340dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.type.ArrayType;
350dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.type.DeclaredType;
360dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.type.PrimitiveType;
370dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.type.TypeKind;
380dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.type.TypeMirror;
390dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornimport javax.lang.model.util.ElementFilter;
40947f7824118f0e9b642df8760a8725a7eda59318Adam Powellimport javax.lang.model.util.Elements;
41947f7824118f0e9b642df8760a8725a7eda59318Adam Powellimport javax.lang.model.util.Types;
42947f7824118f0e9b642df8760a8725a7eda59318Adam Powell
43947f7824118f0e9b642df8760a8725a7eda59318Adam Powell/**
44947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * This is the implementation of ModelClass for the annotation
450dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn * processor. It relies on AnnotationAnalyzer.
460dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn */
470dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackbornclass AnnotationClass extends ModelClass {
480dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn
490dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn    final TypeMirror mTypeMirror;
500dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn
510dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn    public AnnotationClass(TypeMirror typeMirror) {
520dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn        mTypeMirror = typeMirror;
530dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn    }
540dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn
550dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn    @Override
560dad364adb9e9cbc2f7fa115602552f4897387adDianne Hackborn    public String toJavaCode() {
57        return mTypeMirror.toString();
58    }
59
60    @Override
61    public boolean isArray() {
62        return mTypeMirror.getKind() == TypeKind.ARRAY;
63    }
64
65    @Override
66    public AnnotationClass getComponentType() {
67        TypeMirror component = null;
68        if (isArray()) {
69            component = ((ArrayType) mTypeMirror).getComponentType();
70        } else if (isList()) {
71            for (ModelMethod method : getMethods("get", 1)) {
72                ModelClass parameter = method.getParameterTypes()[0];
73                if (parameter.isInt() || parameter.isLong()) {
74                    ArrayList<ModelClass> parameters = new ArrayList<ModelClass>(1);
75                    parameters.add(parameter);
76                    return (AnnotationClass) method.getReturnType(parameters);
77                }
78            }
79            // no "get" call found!
80            return null;
81        } else {
82            AnnotationClass mapClass = (AnnotationClass) ModelAnalyzer.getInstance().getMapType();
83            DeclaredType mapType = findInterface(mapClass.mTypeMirror);
84            if (mapType == null) {
85                return null;
86            }
87            component = mapType.getTypeArguments().get(1);
88        }
89
90        return new AnnotationClass(component);
91    }
92
93    private DeclaredType findInterface(TypeMirror interfaceType) {
94        Types typeUtil = getTypeUtils();
95        TypeMirror foundInterface = null;
96        if (typeUtil.isSameType(interfaceType, typeUtil.erasure(mTypeMirror))) {
97            foundInterface = mTypeMirror;
98        } else {
99            ArrayList<TypeMirror> toCheck = new ArrayList<TypeMirror>();
100            toCheck.add(mTypeMirror);
101            while (!toCheck.isEmpty()) {
102                TypeMirror typeMirror = toCheck.remove(0);
103                if (typeUtil.isSameType(interfaceType, typeUtil.erasure(typeMirror))) {
104                    foundInterface = typeMirror;
105                    break;
106                } else {
107                    toCheck.addAll(typeUtil.directSupertypes(typeMirror));
108                }
109            }
110            if (foundInterface == null) {
111                L.e("Detected " + interfaceType + " type for " + mTypeMirror +
112                        ", but not able to find the implemented interface.");
113                return null;
114            }
115        }
116        if (foundInterface.getKind() != TypeKind.DECLARED) {
117            L.e("Found " + interfaceType + " type for " + mTypeMirror +
118                    ", but it isn't a declared type: " + foundInterface);
119            return null;
120        }
121        return (DeclaredType) foundInterface;
122    }
123
124    @Override
125    public boolean isNullable() {
126        switch (mTypeMirror.getKind()) {
127            case ARRAY:
128            case DECLARED:
129            case NULL:
130                return true;
131            default:
132                return false;
133        }
134    }
135
136    @Override
137    public boolean isPrimitive() {
138        switch (mTypeMirror.getKind()) {
139            case BOOLEAN:
140            case BYTE:
141            case SHORT:
142            case INT:
143            case LONG:
144            case CHAR:
145            case FLOAT:
146            case DOUBLE:
147                return true;
148            default:
149                return false;
150        }
151    }
152
153    @Override
154    public boolean isBoolean() {
155        return mTypeMirror.getKind() == TypeKind.BOOLEAN;
156    }
157
158    @Override
159    public boolean isChar() {
160        return mTypeMirror.getKind() == TypeKind.CHAR;
161    }
162
163    @Override
164    public boolean isByte() {
165        return mTypeMirror.getKind() == TypeKind.BYTE;
166    }
167
168    @Override
169    public boolean isShort() {
170        return mTypeMirror.getKind() == TypeKind.SHORT;
171    }
172
173    @Override
174    public boolean isInt() {
175        return mTypeMirror.getKind() == TypeKind.INT;
176    }
177
178    @Override
179    public boolean isLong() {
180        return mTypeMirror.getKind() == TypeKind.LONG;
181    }
182
183    @Override
184    public boolean isFloat() {
185        return mTypeMirror.getKind() == TypeKind.FLOAT;
186    }
187
188    @Override
189    public boolean isDouble() {
190        return mTypeMirror.getKind() == TypeKind.DOUBLE;
191    }
192
193    @Override
194    public boolean isGeneric() {
195        boolean isGeneric = false;
196        if (mTypeMirror.getKind() == TypeKind.DECLARED) {
197            DeclaredType declaredType = (DeclaredType) mTypeMirror;
198            List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
199            isGeneric = typeArguments != null && !typeArguments.isEmpty();
200        }
201        return isGeneric;
202    }
203
204    @Override
205    public boolean isVoid() {
206        return mTypeMirror.getKind() == TypeKind.VOID;
207    }
208
209    @Override
210    public AnnotationClass unbox() {
211        if (!isNullable()) {
212            return this;
213        }
214        try {
215            return new AnnotationClass(getTypeUtils().unboxedType(mTypeMirror));
216        } catch (IllegalArgumentException e) {
217            // I'm being lazy. This is much easier than checking every type.
218            return this;
219        }
220    }
221
222    @Override
223    public AnnotationClass box() {
224        if (!isPrimitive()) {
225            return this;
226        }
227        return new AnnotationClass(getTypeUtils().boxedClass((PrimitiveType) mTypeMirror).asType());
228    }
229
230    @Override
231    public boolean isAssignableFrom(ModelClass that) {
232        if (that == null) {
233            return false;
234        }
235        AnnotationClass thatAnnotationClass = (AnnotationClass) that;
236        return getTypeUtils().isAssignable(thatAnnotationClass.mTypeMirror, this.mTypeMirror);
237    }
238
239    @Override
240    public ModelMethod[] getDeclaredMethods() {
241        final ModelMethod[] declaredMethods;
242        if (mTypeMirror.getKind() == TypeKind.DECLARED) {
243            DeclaredType declaredType = (DeclaredType) mTypeMirror;
244            Elements elementUtils = getElementUtils();
245            TypeElement typeElement = (TypeElement) declaredType.asElement();
246            List<? extends Element> members = elementUtils.getAllMembers(typeElement);
247            List<ExecutableElement> methods = ElementFilter.methodsIn(members);
248            declaredMethods = new ModelMethod[methods.size()];
249            for (int i = 0; i < declaredMethods.length; i++) {
250                declaredMethods[i] = new AnnotationMethod(declaredType, methods.get(i));
251            }
252        } else {
253            declaredMethods = new ModelMethod[0];
254        }
255        return declaredMethods;
256    }
257
258    @Override
259    public AnnotationClass getSuperclass() {
260        if (mTypeMirror.getKind() == TypeKind.DECLARED) {
261            DeclaredType declaredType = (DeclaredType) mTypeMirror;
262            TypeElement typeElement = (TypeElement) declaredType.asElement();
263            TypeMirror superClass = typeElement.getSuperclass();
264            if (superClass.getKind() == TypeKind.DECLARED) {
265                return new AnnotationClass(superClass);
266            }
267        }
268        return null;
269    }
270
271    @Override
272    public String getCanonicalName() {
273        return getTypeUtils().erasure(mTypeMirror).toString();
274    }
275
276    @Override
277    public ModelClass erasure() {
278        final TypeMirror erasure = getTypeUtils().erasure(mTypeMirror);
279        if (erasure == mTypeMirror) {
280            return this;
281        } else {
282            return new AnnotationClass(erasure);
283        }
284    }
285
286    @Override
287    public String getJniDescription() {
288        return TypeUtil.getInstance().getDescription(this);
289    }
290
291    @Override
292    protected ModelField[] getDeclaredFields() {
293        final ModelField[] declaredFields;
294        if (mTypeMirror.getKind() == TypeKind.DECLARED) {
295            DeclaredType declaredType = (DeclaredType) mTypeMirror;
296            Elements elementUtils = getElementUtils();
297            TypeElement typeElement = (TypeElement) declaredType.asElement();
298            List<? extends Element> members = elementUtils.getAllMembers(typeElement);
299            List<VariableElement> fields = ElementFilter.fieldsIn(members);
300            declaredFields = new ModelField[fields.size()];
301            for (int i = 0; i < declaredFields.length; i++) {
302                declaredFields[i] = new AnnotationField(typeElement, fields.get(i));
303            }
304        } else {
305            declaredFields = new ModelField[0];
306        }
307        return declaredFields;
308    }
309
310    @Override
311    public boolean equals(Object obj) {
312        if (obj instanceof AnnotationClass) {
313            return getTypeUtils().isSameType(mTypeMirror, ((AnnotationClass) obj).mTypeMirror);
314        } else {
315            return false;
316        }
317    }
318
319    @Override
320    public int hashCode() {
321        return mTypeMirror.toString().hashCode();
322    }
323
324    private static Types getTypeUtils() {
325        return AnnotationAnalyzer.get().mProcessingEnv.getTypeUtils();
326    }
327
328    private static Elements getElementUtils() {
329        return AnnotationAnalyzer.get().mProcessingEnv.getElementUtils();
330    }
331
332    @Override
333    public String toString() {
334        return mTypeMirror.toString();
335    }
336}
337