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