1 /* 2 * Copyright (C) 2019 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.hilt.processor.internal; 18 19 import static com.google.auto.common.MoreElements.asPackage; 20 import static com.google.auto.common.MoreElements.asVariable; 21 import static com.google.common.base.Preconditions.checkNotNull; 22 import static dagger.internal.codegen.extension.DaggerCollectors.toOptional; 23 import static javax.lang.model.element.Modifier.ABSTRACT; 24 import static javax.lang.model.element.Modifier.STATIC; 25 26 import com.google.auto.common.AnnotationMirrors; 27 import com.google.auto.common.GeneratedAnnotations; 28 import com.google.auto.common.MoreElements; 29 import com.google.auto.common.MoreTypes; 30 import com.google.common.base.CaseFormat; 31 import com.google.common.base.Equivalence.Wrapper; 32 import com.google.common.base.Joiner; 33 import com.google.common.base.Preconditions; 34 import com.google.common.collect.FluentIterable; 35 import com.google.common.collect.ImmutableList; 36 import com.google.common.collect.ImmutableMap; 37 import com.google.common.collect.ImmutableSet; 38 import com.google.common.collect.Iterables; 39 import com.google.common.collect.LinkedHashMultimap; 40 import com.google.common.collect.Multimap; 41 import com.google.common.collect.SetMultimap; 42 import com.squareup.javapoet.AnnotationSpec; 43 import com.squareup.javapoet.ClassName; 44 import com.squareup.javapoet.MethodSpec; 45 import com.squareup.javapoet.ParameterSpec; 46 import com.squareup.javapoet.ParameterizedTypeName; 47 import com.squareup.javapoet.TypeName; 48 import com.squareup.javapoet.TypeSpec; 49 import dagger.internal.codegen.extension.DaggerStreams; 50 import dagger.internal.codegen.kotlin.KotlinMetadataUtil; 51 import java.lang.annotation.Annotation; 52 import java.util.LinkedHashSet; 53 import java.util.List; 54 import java.util.Map; 55 import java.util.Optional; 56 import java.util.Set; 57 import java.util.stream.Collectors; 58 import java.util.stream.Stream; 59 import javax.annotation.processing.ProcessingEnvironment; 60 import javax.annotation.processing.RoundEnvironment; 61 import javax.inject.Qualifier; 62 import javax.lang.model.element.AnnotationMirror; 63 import javax.lang.model.element.AnnotationValue; 64 import javax.lang.model.element.Element; 65 import javax.lang.model.element.ElementKind; 66 import javax.lang.model.element.ExecutableElement; 67 import javax.lang.model.element.Modifier; 68 import javax.lang.model.element.PackageElement; 69 import javax.lang.model.element.TypeElement; 70 import javax.lang.model.element.VariableElement; 71 import javax.lang.model.type.ArrayType; 72 import javax.lang.model.type.DeclaredType; 73 import javax.lang.model.type.ErrorType; 74 import javax.lang.model.type.PrimitiveType; 75 import javax.lang.model.type.TypeKind; 76 import javax.lang.model.type.TypeMirror; 77 import javax.lang.model.util.ElementFilter; 78 import javax.lang.model.util.Elements; 79 import javax.lang.model.util.SimpleAnnotationValueVisitor7; 80 import javax.lang.model.util.SimpleTypeVisitor7; 81 82 /** Static helper methods for writing a processor. */ 83 public final class Processors { 84 85 public static final String CONSTRUCTOR_NAME = "<init>"; 86 87 public static final String STATIC_INITIALIZER_NAME = "<clinit>"; 88 89 private static final String JAVA_CLASS = "java.lang.Class"; 90 91 /** Returns a map from {@link AnnotationMirror} attribute name to {@link AnnotationValue}s */ getAnnotationValues(Elements elements, AnnotationMirror annotation)92 public static ImmutableMap<String, AnnotationValue> getAnnotationValues(Elements elements, 93 AnnotationMirror annotation) { 94 ImmutableMap.Builder<String, AnnotationValue> annotationMembers = ImmutableMap.builder(); 95 for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e 96 : elements.getElementValuesWithDefaults(annotation).entrySet()) { 97 annotationMembers.put(e.getKey().getSimpleName().toString(), e.getValue()); 98 } 99 return annotationMembers.build(); 100 } 101 102 /** 103 * Returns a multimap from attribute name to the values that are an array of annotation mirrors. 104 * The returned map will not contain mappings for any attributes that are not Annotation Arrays. 105 * 106 * <p>e.g. if the input was the annotation mirror for 107 * <pre> 108 * {@literal @}Foo({{@literal @}Bar("hello"), {@literal @}Bar("world")}) 109 * </pre> 110 * the map returned would have "value" map to a set containing the two @Bar annotation mirrors. 111 */ getAnnotationAnnotationArrayValues( Elements elements, AnnotationMirror annotation)112 public static Multimap<String, AnnotationMirror> getAnnotationAnnotationArrayValues( 113 Elements elements, AnnotationMirror annotation) { 114 SetMultimap<String, AnnotationMirror> annotationMembers = LinkedHashMultimap.create(); 115 for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e 116 : elements.getElementValuesWithDefaults(annotation).entrySet()) { 117 String attribute = e.getKey().getSimpleName().toString(); 118 Set<AnnotationMirror> annotationMirrors = new LinkedHashSet<>(); 119 e.getValue().accept(new AnnotationMirrorAnnotationValueVisitor(), annotationMirrors); 120 annotationMembers.putAll(attribute, annotationMirrors); 121 } 122 return annotationMembers; 123 } 124 125 private static final class AnnotationMirrorAnnotationValueVisitor 126 extends SimpleAnnotationValueVisitor7<Void, Set<AnnotationMirror>> { 127 128 @Override visitArray(List<? extends AnnotationValue> vals, Set<AnnotationMirror> types)129 public Void visitArray(List<? extends AnnotationValue> vals, Set<AnnotationMirror> types) { 130 for (AnnotationValue val : vals) { 131 val.accept(this, types); 132 } 133 return null; 134 } 135 136 @Override visitAnnotation(AnnotationMirror a, Set<AnnotationMirror> annotationMirrors)137 public Void visitAnnotation(AnnotationMirror a, Set<AnnotationMirror> annotationMirrors) { 138 annotationMirrors.add(a); 139 return null; 140 } 141 } 142 143 /** Returns the {@link TypeElement} for a class attribute on an annotation. */ getAnnotationClassValue( Elements elements, AnnotationMirror annotation, String key)144 public static TypeElement getAnnotationClassValue( 145 Elements elements, AnnotationMirror annotation, String key) { 146 return Iterables.getOnlyElement(getAnnotationClassValues(elements, annotation, key)); 147 } 148 149 /** Returns a list of {@link TypeElement}s for a class attribute on an annotation. */ getAnnotationClassValues( Elements elements, AnnotationMirror annotation, String key)150 public static ImmutableList<TypeElement> getAnnotationClassValues( 151 Elements elements, AnnotationMirror annotation, String key) { 152 ImmutableList<TypeElement> values = getOptionalAnnotationClassValues(elements, annotation, key); 153 154 ProcessorErrors.checkState( 155 values.size() >= 1, 156 // TODO(b/152801981): Point to the annotation value rather than the annotated element. 157 annotation.getAnnotationType().asElement(), 158 "@%s, '%s' class is invalid or missing: %s", 159 annotation.getAnnotationType().asElement().getSimpleName(), 160 key, 161 annotation); 162 163 return values; 164 } 165 166 /** Returns a multimap from attribute name to elements for class valued attributes. */ getAnnotationClassValues( Elements elements, AnnotationMirror annotation)167 private static Multimap<String, DeclaredType> getAnnotationClassValues( 168 Elements elements, AnnotationMirror annotation) { 169 Element javaClass = elements.getTypeElement(JAVA_CLASS); 170 SetMultimap<String, DeclaredType> annotationMembers = LinkedHashMultimap.create(); 171 for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e : 172 elements.getElementValuesWithDefaults(annotation).entrySet()) { 173 Optional<DeclaredType> returnType = getOptionalDeclaredType(e.getKey().getReturnType()); 174 if (returnType.isPresent() && returnType.get().asElement().equals(javaClass)) { 175 String attribute = e.getKey().getSimpleName().toString(); 176 Set<DeclaredType> declaredTypes = new LinkedHashSet<DeclaredType>(); 177 e.getValue().accept(new DeclaredTypeAnnotationValueVisitor(), declaredTypes); 178 annotationMembers.putAll(attribute, declaredTypes); 179 } 180 } 181 return annotationMembers; 182 } 183 184 /** Returns an optional {@link TypeElement} for a class attribute on an annotation. */ getOptionalAnnotationClassValue( Elements elements, AnnotationMirror annotation, String key)185 public static Optional<TypeElement> getOptionalAnnotationClassValue( 186 Elements elements, AnnotationMirror annotation, String key) { 187 return getAnnotationClassValues(elements, annotation).get(key).stream() 188 .map(MoreTypes::asTypeElement) 189 .collect(toOptional()); 190 } 191 192 /** Returns a list of {@link TypeElement}s for a class attribute on an annotation. */ getOptionalAnnotationClassValues( Elements elements, AnnotationMirror annotation, String key)193 public static ImmutableList<TypeElement> getOptionalAnnotationClassValues( 194 Elements elements, AnnotationMirror annotation, String key) { 195 return ImmutableList.copyOf( 196 getAnnotationClassValues(elements, annotation).get(key).stream() 197 .map(MoreTypes::asTypeElement) 198 .collect(Collectors.toList())); 199 } 200 201 private static final class DeclaredTypeAnnotationValueVisitor 202 extends SimpleAnnotationValueVisitor7<Void, Set<DeclaredType>> { 203 visitArray( List<? extends AnnotationValue> vals, Set<DeclaredType> types)204 @Override public Void visitArray( 205 List<? extends AnnotationValue> vals, Set<DeclaredType> types) { 206 for (AnnotationValue val : vals) { 207 val.accept(this, types); 208 } 209 return null; 210 } 211 visitType(TypeMirror t, Set<DeclaredType> types)212 @Override public Void visitType(TypeMirror t, Set<DeclaredType> types) { 213 DeclaredType declared = MoreTypes.asDeclared(t); 214 checkNotNull(declared); 215 types.add(declared); 216 return null; 217 } 218 } 219 220 /** 221 * If the received mirror represents a primitive type or an array of primitive types, this returns 222 * the represented primitive type. Otherwise throws an IllegalStateException. 223 */ getPrimitiveType(TypeMirror type)224 public static PrimitiveType getPrimitiveType(TypeMirror type) { 225 return type.accept( 226 new SimpleTypeVisitor7<PrimitiveType, Void> () { 227 @Override public PrimitiveType visitArray(ArrayType type, Void unused) { 228 return getPrimitiveType(type.getComponentType()); 229 } 230 231 @Override public PrimitiveType visitPrimitive(PrimitiveType type, Void unused) { 232 return type; 233 } 234 235 @Override public PrimitiveType defaultAction(TypeMirror type, Void unused) { 236 throw new IllegalStateException("Unhandled type: " + type); 237 } 238 }, null /* the Void accumulator */); 239 } 240 241 /** 242 * Returns an {@link Optional#of} the declared type if the received mirror represents a declared 243 * type or an array of declared types, otherwise returns {@link Optional#empty}. 244 */ 245 public static Optional<DeclaredType> getOptionalDeclaredType(TypeMirror type) { 246 return Optional.ofNullable( 247 type.accept( 248 new SimpleTypeVisitor7<DeclaredType, Void>(null /* defaultValue */) { 249 @Override 250 public DeclaredType visitArray(ArrayType type, Void unused) { 251 return MoreTypes.asDeclared(type.getComponentType()); 252 } 253 254 @Override 255 public DeclaredType visitDeclared(DeclaredType type, Void unused) { 256 return type; 257 } 258 259 @Override 260 public DeclaredType visitError(ErrorType type, Void unused) { 261 return type; 262 } 263 }, 264 null /* the Void accumulator */)); 265 } 266 267 /** 268 * Returns the declared type if the received mirror represents a declared type or an array of 269 * declared types, otherwise throws an {@link IllegalStateException}. 270 */ 271 public static DeclaredType getDeclaredType(TypeMirror type) { 272 return getOptionalDeclaredType(type) 273 .orElseThrow(() -> new IllegalStateException("Not a declared type: " + type)); 274 } 275 276 /** Gets the values from an annotation value representing a string array. */ 277 public static ImmutableList<String> getStringArrayAnnotationValue(AnnotationValue value) { 278 return value.accept(new SimpleAnnotationValueVisitor7<ImmutableList<String>, Void>() { 279 @Override 280 public ImmutableList<String> defaultAction(Object o, Void unused) { 281 throw new IllegalStateException("Expected an array, got instead: " + o); 282 } 283 284 @Override 285 public ImmutableList<String> visitArray(List<? extends AnnotationValue> values, 286 Void unused) { 287 ImmutableList.Builder<String> builder = ImmutableList.builder(); 288 for (AnnotationValue value : values) { 289 builder.add(getStringAnnotationValue(value)); 290 } 291 return builder.build(); 292 } 293 }, /* unused accumulator */ null); 294 } 295 296 /** Gets the values from an annotation value representing an int. */ 297 public static Boolean getBooleanAnnotationValue(AnnotationValue value) { 298 return value.accept( 299 new SimpleAnnotationValueVisitor7<Boolean, Void>() { 300 @Override 301 public Boolean defaultAction(Object o, Void unused) { 302 throw new IllegalStateException("Expected a boolean, got instead: " + o); 303 } 304 305 @Override 306 public Boolean visitBoolean(boolean value, Void unused) { 307 return value; 308 } 309 }, /* unused accumulator */ 310 null); 311 } 312 313 /** Gets the values from an annotation value representing an int. */ 314 public static Integer getIntAnnotationValue(AnnotationValue value) { 315 return value.accept(new SimpleAnnotationValueVisitor7<Integer, Void>() { 316 @Override 317 public Integer defaultAction(Object o, Void unused) { 318 throw new IllegalStateException("Expected an int, got instead: " + o); 319 } 320 321 @Override 322 public Integer visitInt(int value, Void unused) { 323 return value; 324 } 325 }, /* unused accumulator */ null); 326 } 327 328 /** Gets the values from an annotation value representing a long. */ 329 public static Long getLongAnnotationValue(AnnotationValue value) { 330 return value.accept( 331 new SimpleAnnotationValueVisitor7<Long, Void>() { 332 @Override 333 public Long defaultAction(Object o, Void unused) { 334 throw new IllegalStateException("Expected an int, got instead: " + o); 335 } 336 337 @Override 338 public Long visitLong(long value, Void unused) { 339 return value; 340 } 341 }, 342 null /* unused accumulator */); 343 } 344 345 /** Gets the values from an annotation value representing a string. */ 346 public static String getStringAnnotationValue(AnnotationValue value) { 347 return value.accept(new SimpleAnnotationValueVisitor7<String, Void>() { 348 @Override 349 public String defaultAction(Object o, Void unused) { 350 throw new IllegalStateException("Expected a string, got instead: " + o); 351 } 352 353 @Override 354 public String visitString(String value, Void unused) { 355 return value; 356 } 357 }, /* unused accumulator */ null); 358 } 359 360 /** Gets the values from an annotation value representing a DeclaredType. */ 361 public static DeclaredType getDeclaredTypeAnnotationValue(AnnotationValue value) { 362 return value.accept( 363 new SimpleAnnotationValueVisitor7<DeclaredType, Void>() { 364 @Override 365 public DeclaredType defaultAction(Object o, Void unused) { 366 throw new IllegalStateException("Expected a TypeMirror, got instead: " + o); 367 } 368 369 @Override 370 public DeclaredType visitType(TypeMirror typeMirror, Void unused) { 371 return MoreTypes.asDeclared(typeMirror); 372 } 373 }, /* unused accumulator */ 374 null); 375 } 376 377 private static final SimpleAnnotationValueVisitor7<ImmutableSet<VariableElement>, Void> 378 ENUM_ANNOTATION_VALUE_VISITOR = 379 new SimpleAnnotationValueVisitor7<ImmutableSet<VariableElement>, Void>() { 380 @Override 381 public ImmutableSet<VariableElement> defaultAction(Object o, Void unused) { 382 throw new IllegalStateException( 383 "Expected an Enum or an Enum array, got instead: " + o); 384 } 385 386 @Override 387 public ImmutableSet<VariableElement> visitArray( 388 List<? extends AnnotationValue> values, Void unused) { 389 ImmutableSet.Builder<VariableElement> builder = ImmutableSet.builder(); 390 for (AnnotationValue value : values) { 391 builder.addAll(value.accept(this, null)); 392 } 393 return builder.build(); 394 } 395 396 @Override 397 public ImmutableSet<VariableElement> visitEnumConstant( 398 VariableElement value, Void unused) { 399 return ImmutableSet.of(value); 400 } 401 }; 402 403 /** Gets the values from an annotation value representing a Enum array. */ 404 public static ImmutableSet<VariableElement> getEnumArrayAnnotationValue(AnnotationValue value) { 405 return value.accept(ENUM_ANNOTATION_VALUE_VISITOR, /* unused accumulator */ null); 406 } 407 408 /** Converts an annotation value map to be keyed by the attribute name. */ 409 public static ImmutableMap<String, AnnotationValue> convertToAttributeNameMap( 410 Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValues) { 411 ImmutableMap.Builder<String, AnnotationValue> builder = ImmutableMap.builder(); 412 for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e 413 : annotationValues.entrySet()) { 414 String attribute = e.getKey().getSimpleName().toString(); 415 builder.put(attribute, e.getValue()); 416 } 417 return builder.build(); 418 } 419 420 /** Returns the given elements containing package element. */ 421 public static PackageElement getPackageElement(Element originalElement) { 422 checkNotNull(originalElement); 423 for (Element e = originalElement; e != null; e = e.getEnclosingElement()) { 424 if (e instanceof PackageElement) { 425 return (PackageElement) e; 426 } 427 } 428 throw new IllegalStateException("Cannot find a package for " + originalElement); 429 } 430 431 public static TypeElement getTopLevelType(Element originalElement) { 432 checkNotNull(originalElement); 433 for (Element e = originalElement; e != null; e = e.getEnclosingElement()) { 434 if (isTopLevel(e)) { 435 return MoreElements.asType(e); 436 } 437 } 438 throw new IllegalStateException("Cannot find a top-level type for " + originalElement); 439 } 440 441 /** Returns true if the given element is a top-level element. */ 442 public static boolean isTopLevel(Element element) { 443 return element.getEnclosingElement().getKind() == ElementKind.PACKAGE; 444 } 445 446 /** Returns true if the given element is annotated with the given annotation. */ 447 public static boolean hasAnnotation(Element element, Class<? extends Annotation> annotation) { 448 return element.getAnnotation(annotation) != null; 449 } 450 451 /** Returns true if the given element has an annotation with the given class name. */ 452 public static boolean hasAnnotation(Element element, ClassName className) { 453 return getAnnotationMirrorOptional(element, className).isPresent(); 454 } 455 456 /** Returns true if the given element has an annotation with the given class name. */ 457 public static boolean hasAnnotation(AnnotationMirror mirror, ClassName className) { 458 return hasAnnotation(mirror.getAnnotationType().asElement(), className); 459 } 460 461 /** Returns true if the given element is annotated with the given annotation. */ 462 public static boolean hasAnnotation( 463 AnnotationMirror mirror, Class<? extends Annotation> annotation) { 464 return hasAnnotation(mirror.getAnnotationType().asElement(), annotation); 465 } 466 467 /** Returns true if the given element has an annotation that is an error kind. */ 468 public static boolean hasErrorTypeAnnotation(Element element) { 469 for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) { 470 if (annotationMirror.getAnnotationType().getKind() == TypeKind.ERROR) { 471 return true; 472 } 473 } 474 return false; 475 } 476 477 478 /** 479 * Returns all elements in the round that are annotated with at least 1 of the given 480 * annotations. 481 */ 482 @SafeVarargs 483 public static ImmutableSet<Element> getElementsAnnotatedWith(RoundEnvironment roundEnv, 484 Class<? extends Annotation>... annotations) { 485 ImmutableSet.Builder<Element> builder = ImmutableSet.builder(); 486 for (Class<? extends Annotation> annotation : annotations){ 487 builder.addAll(roundEnv.getElementsAnnotatedWith(annotation)); 488 } 489 490 return builder.build(); 491 } 492 493 /** 494 * Returns the name of a class, including prefixing with enclosing class names. i.e. for inner 495 * class Foo enclosed by Bar, returns Bar_Foo instead of just Foo 496 */ 497 public static String getEnclosedName(ClassName name) { 498 return Joiner.on('_').join(name.simpleNames()); 499 } 500 501 /** Returns the name of a class. See {@link #getEnclosedName(ClassName)}. */ 502 public static String getEnclosedName(TypeElement element) { 503 return getEnclosedName(ClassName.get(element)); 504 } 505 506 /** 507 * Returns an equivalent class name with the {@code .} (dots) used for inner classes replaced with 508 * {@code _}. 509 */ 510 public static ClassName getEnclosedClassName(ClassName className) { 511 return ClassName.get(className.packageName(), getEnclosedName(className)); 512 } 513 514 /** Returns the fully qualified class name, with _ instead of . */ 515 public static String getFullyQualifiedEnclosedClassName(ClassName className) { 516 return className.packageName().replace('.', '_') + getEnclosedName(className); 517 } 518 519 /** 520 * Returns the fully qualified class name, with _ instead of . For elements that are not type 521 * elements, this continues to append the simple name of elements. For example, 522 * foo_bar_Outer_Inner_fooMethod. 523 */ 524 public static String getFullEnclosedName(Element element) { 525 Preconditions.checkNotNull(element); 526 String qualifiedName = ""; 527 while (element != null) { 528 if (element.getKind().equals(ElementKind.PACKAGE)) { 529 qualifiedName = asPackage(element).getQualifiedName() + qualifiedName; 530 } else { 531 // This check is needed to keep the name stable when compiled with jdk8 vs jdk11. jdk11 532 // contains newly added "module" enclosing elements of packages, which adds an addtional "_" 533 // prefix to the name due to an empty module element compared with jdk8. 534 if (!element.getSimpleName().toString().isEmpty()) { 535 qualifiedName = "." + element.getSimpleName() + qualifiedName; 536 } 537 } 538 element = element.getEnclosingElement(); 539 } 540 return qualifiedName.replace('.', '_'); 541 } 542 543 /** Appends the given string to the end of the class name. */ 544 public static ClassName append(ClassName name, String suffix) { 545 return name.peerClass(name.simpleName() + suffix); 546 } 547 548 /** Prepends the given string to the beginning of the class name. */ 549 public static ClassName prepend(ClassName name, String prefix) { 550 return name.peerClass(prefix + name.simpleName()); 551 } 552 553 /** 554 * Removes the string {@code suffix} from the simple name of {@code type} and returns it. 555 * 556 * @throws BadInputException if the simple name of {@code type} does not end with {@code suffix} 557 */ 558 public static ClassName removeNameSuffix(TypeElement type, String suffix) { 559 ClassName originalName = ClassName.get(type); 560 String originalSimpleName = originalName.simpleName(); 561 ProcessorErrors.checkState(originalSimpleName.endsWith(suffix), 562 type, "Name of type %s must end with '%s'", originalName, suffix); 563 String withoutSuffix = 564 originalSimpleName.substring(0, originalSimpleName.length() - suffix.length()); 565 return originalName.peerClass(withoutSuffix); 566 } 567 568 /** @see #getAnnotationMirror(Element, ClassName) */ 569 public static AnnotationMirror getAnnotationMirror( 570 Element element, Class<? extends Annotation> annotationClass) { 571 return getAnnotationMirror(element, ClassName.get(annotationClass)); 572 } 573 574 /** @see #getAnnotationMirror(Element, ClassName) */ 575 public static AnnotationMirror getAnnotationMirror(Element element, String annotationClassName) { 576 return getAnnotationMirror(element, ClassName.bestGuess(annotationClassName)); 577 } 578 579 /** 580 * Returns the annotation mirror from the given element that corresponds to the given class. 581 * 582 * @throws IllegalStateException if the given element isn't annotated with that annotation. 583 */ 584 public static AnnotationMirror getAnnotationMirror(Element element, ClassName className) { 585 Optional<AnnotationMirror> annotationMirror = getAnnotationMirrorOptional(element, className); 586 if (annotationMirror.isPresent()) { 587 return annotationMirror.get(); 588 } else { 589 throw new IllegalStateException( 590 String.format( 591 "Couldn't find annotation %s on element %s. Found annotations: %s", 592 className, element.getSimpleName(), element.getAnnotationMirrors())); 593 } 594 } 595 596 /** 597 * Returns the annotation mirror from the given element that corresponds to the given class. 598 * 599 * @throws {@link IllegalArgumentException} if 2 or more annotations are found. 600 * @return {@link Optional#empty()} if no annotation is found on the element. 601 */ 602 static Optional<AnnotationMirror> getAnnotationMirrorOptional( 603 Element element, ClassName className) { 604 return element.getAnnotationMirrors().stream() 605 .filter(mirror -> ClassName.get(mirror.getAnnotationType()).equals(className)) 606 .collect(toOptional()); 607 } 608 609 /** @return true if element inherits directly or indirectly from the className */ 610 public static boolean isAssignableFrom(TypeElement element, ClassName className) { 611 return isAssignableFromAnyOf(element, ImmutableSet.of(className)); 612 } 613 614 /** @return true if element inherits directly or indirectly from any of the classNames */ 615 public static boolean isAssignableFromAnyOf(TypeElement element, 616 ImmutableSet<ClassName> classNames) { 617 for (ClassName className : classNames) { 618 if (ClassName.get(element).equals(className)) { 619 return true; 620 } 621 } 622 623 TypeMirror superClass = element.getSuperclass(); 624 // None type is returned if this is an interface or Object 625 // Error type is returned for classes that are generated by this processor 626 if ((superClass.getKind() != TypeKind.NONE) && (superClass.getKind() != TypeKind.ERROR)) { 627 Preconditions.checkState(superClass.getKind() == TypeKind.DECLARED); 628 if (isAssignableFromAnyOf(MoreTypes.asTypeElement(superClass), classNames)) { 629 return true; 630 } 631 } 632 633 for (TypeMirror iface : element.getInterfaces()) { 634 // Skip errors and keep looking. This is especially needed for classes generated by this 635 // processor. 636 if (iface.getKind() == TypeKind.ERROR) { 637 continue; 638 } 639 Preconditions.checkState(iface.getKind() == TypeKind.DECLARED, 640 "Interface type is %s", iface.getKind()); 641 if (isAssignableFromAnyOf(MoreTypes.asTypeElement(iface), classNames)) { 642 return true; 643 } 644 } 645 646 return false; 647 } 648 649 /** Returns methods from a given TypeElement, not including constructors. */ 650 public static ImmutableList<ExecutableElement> getMethods(TypeElement element) { 651 ImmutableList.Builder<ExecutableElement> builder = ImmutableList.builder(); 652 for (Element e : element.getEnclosedElements()) { 653 // Only look for executable elements, not fields, etc 654 if (e instanceof ExecutableElement) { 655 ExecutableElement method = (ExecutableElement) e; 656 if (!method.getSimpleName().contentEquals(CONSTRUCTOR_NAME) 657 && !method.getSimpleName().contentEquals(STATIC_INITIALIZER_NAME)) { 658 builder.add(method); 659 } 660 } 661 } 662 return builder.build(); 663 } 664 665 public static ImmutableList<ExecutableElement> getConstructors(TypeElement element) { 666 ImmutableList.Builder<ExecutableElement> builder = ImmutableList.builder(); 667 for (Element enclosed : element.getEnclosedElements()) { 668 // Only look for executable elements, not fields, etc 669 if (enclosed instanceof ExecutableElement) { 670 ExecutableElement method = (ExecutableElement) enclosed; 671 if (method.getSimpleName().contentEquals(CONSTRUCTOR_NAME)) { 672 builder.add(method); 673 } 674 } 675 } 676 return builder.build(); 677 } 678 679 /** 680 * Returns all transitive methods from a given TypeElement, not including constructors. Also does 681 * not include methods from Object or that override methods on Object. 682 */ 683 public static ImmutableList<ExecutableElement> getAllMethods(TypeElement element) { 684 ImmutableList.Builder<ExecutableElement> builder = ImmutableList.builder(); 685 builder.addAll( 686 Iterables.filter( 687 getMethods(element), 688 method -> { 689 return !isObjectMethod(method); 690 })); 691 TypeMirror superclass = element.getSuperclass(); 692 if (superclass.getKind() != TypeKind.NONE) { 693 TypeElement superclassElement = MoreTypes.asTypeElement(superclass); 694 builder.addAll(getAllMethods(superclassElement)); 695 } 696 for (TypeMirror iface : element.getInterfaces()) { 697 builder.addAll(getAllMethods(MoreTypes.asTypeElement(iface))); 698 } 699 return builder.build(); 700 } 701 702 /** Checks that the given element is not the error type. */ 703 public static void checkForCompilationError(TypeElement e) { 704 ProcessorErrors.checkState(e.asType().getKind() != TypeKind.ERROR, e, 705 "Unable to resolve the type %s. Look for compilation errors above related to this type.", 706 e); 707 } 708 709 private static void addInterfaceMethods( 710 TypeElement type, ImmutableList.Builder<ExecutableElement> interfaceMethods) { 711 for (TypeMirror interfaceMirror : type.getInterfaces()) { 712 TypeElement interfaceElement = MoreTypes.asTypeElement(interfaceMirror); 713 interfaceMethods.addAll(getMethods(interfaceElement)); 714 addInterfaceMethods(interfaceElement, interfaceMethods); 715 } 716 } 717 718 /** 719 * Finds methods of interfaces implemented by {@code type}. This method also checks the 720 * superinterfaces of those interfaces. This method does not check the interfaces of any 721 * superclass of {@code type}. 722 */ 723 public static ImmutableList<ExecutableElement> methodsOnInterfaces(TypeElement type) { 724 ImmutableList.Builder<ExecutableElement> interfaceMethods = new ImmutableList.Builder<>(); 725 addInterfaceMethods(type, interfaceMethods); 726 return interfaceMethods.build(); 727 } 728 729 /** Returns MapKey annotated annotations found on an element. */ 730 public static ImmutableList<AnnotationMirror> getMapKeyAnnotations(Element element) { 731 return getAnnotationsAnnotatedWith(element, ClassName.get("dagger", "MapKey")); 732 } 733 734 /** Returns Qualifier annotated annotations found on an element. */ 735 public static ImmutableList<AnnotationMirror> getQualifierAnnotations(Element element) { 736 // TODO(bcorso): Consolidate this logic with InjectionAnnotations in Dagger 737 ImmutableSet<? extends AnnotationMirror> qualifiers = 738 AnnotationMirrors.getAnnotatedAnnotations(element, Qualifier.class); 739 KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil(); 740 if (element.getKind() == ElementKind.FIELD 741 // static fields are generally not supported, no need to get qualifier from kotlin metadata 742 && !element.getModifiers().contains(STATIC) 743 && metadataUtil.hasMetadata(element)) { 744 VariableElement fieldElement = asVariable(element); 745 return Stream.concat( 746 qualifiers.stream(), 747 metadataUtil.isMissingSyntheticPropertyForAnnotations(fieldElement) 748 ? Stream.empty() 749 : metadataUtil 750 .getSyntheticPropertyAnnotations(fieldElement, Qualifier.class) 751 .stream()) 752 .map(AnnotationMirrors.equivalence()::wrap) 753 .distinct() 754 .map(Wrapper::get) 755 .collect(DaggerStreams.toImmutableList()); 756 } else { 757 return ImmutableList.copyOf(qualifiers); 758 } 759 } 760 761 /** Returns Scope annotated annotations found on an element. */ 762 public static ImmutableList<AnnotationMirror> getScopeAnnotations(Element element) { 763 return getAnnotationsAnnotatedWith(element, ClassNames.SCOPE); 764 } 765 766 /** Returns annotations of element that are annotated with subAnnotation */ 767 public static ImmutableList<AnnotationMirror> getAnnotationsAnnotatedWith( 768 Element element, ClassName subAnnotation) { 769 ImmutableList.Builder<AnnotationMirror> builder = ImmutableList.builder(); 770 element.getAnnotationMirrors().stream() 771 .filter(annotation -> hasAnnotation(annotation, subAnnotation)) 772 .forEach(builder::add); 773 return builder.build(); 774 } 775 776 /** Returns true if there are any annotations of element that are annotated with subAnnotation */ 777 public static boolean hasAnnotationsAnnotatedWith(Element element, ClassName subAnnotation) { 778 return !getAnnotationsAnnotatedWith(element, subAnnotation).isEmpty(); 779 } 780 781 /** 782 * Returns true iff the given {@code method} is one of the public or protected methods on {@link 783 * Object}, or an overridden version thereof. 784 * 785 * <p>This method ignores the return type of the given method, but this is generally fine since 786 * two methods which only differ by their return type will cause a compiler error. (e.g. a 787 * non-static method with the signature {@code int equals(Object)}) 788 */ 789 public static boolean isObjectMethod(ExecutableElement method) { 790 // First check if this method is directly defined on Object 791 Element enclosingElement = method.getEnclosingElement(); 792 if (enclosingElement.getKind() == ElementKind.CLASS 793 && TypeName.get(enclosingElement.asType()).equals(TypeName.OBJECT)) { 794 return true; 795 } 796 797 if (method.getModifiers().contains(Modifier.STATIC)) { 798 return false; 799 } 800 switch (method.getSimpleName().toString()) { 801 case "equals": 802 return (method.getParameters().size() == 1) 803 && (method.getParameters().get(0).asType().toString().equals("java.lang.Object")); 804 case "hashCode": 805 case "toString": 806 case "clone": 807 case "getClass": 808 case "notify": 809 case "notifyAll": 810 case "finalize": 811 return method.getParameters().isEmpty(); 812 case "wait": 813 if (method.getParameters().isEmpty()) { 814 return true; 815 } else if ((method.getParameters().size() == 1) 816 && (method.getParameters().get(0).asType().toString().equals("long"))) { 817 return true; 818 } else if ((method.getParameters().size() == 2) 819 && (method.getParameters().get(0).asType().toString().equals("long")) 820 && (method.getParameters().get(1).asType().toString().equals("int"))) { 821 return true; 822 } 823 return false; 824 default: 825 return false; 826 } 827 } 828 829 public static ParameterSpec parameterSpecFromVariableElement(VariableElement element) { 830 return ParameterSpec.builder( 831 ClassName.get(element.asType()), 832 upperToLowerCamel(element.getSimpleName().toString())) 833 .build(); 834 } 835 836 /** 837 * Shortcut for converting from upper camel to lower camel case 838 * 839 * <p>Example: "SomeString" => "someString" 840 */ 841 public static String upperToLowerCamel(String upperCamel) { 842 return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, upperCamel); 843 } 844 845 /** @return copy of the given MethodSpec as {@link MethodSpec.Builder} with method body removed */ 846 public static MethodSpec.Builder copyMethodSpecWithoutBody(MethodSpec methodSpec) { 847 MethodSpec.Builder builder; 848 849 if (methodSpec.isConstructor()) { 850 // Constructors cannot have return types 851 builder = MethodSpec.constructorBuilder(); 852 } else { 853 builder = MethodSpec.methodBuilder(methodSpec.name) 854 .returns(methodSpec.returnType); 855 } 856 857 return builder 858 .addAnnotations(methodSpec.annotations) 859 .addModifiers(methodSpec.modifiers) 860 .addParameters(methodSpec.parameters) 861 .addExceptions(methodSpec.exceptions) 862 .addJavadoc(methodSpec.javadoc.toString()) 863 .addTypeVariables(methodSpec.typeVariables); 864 } 865 866 /** @return A method spec for an empty constructor (useful for abstract Dagger modules). */ 867 public static MethodSpec privateEmptyConstructor() { 868 return MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build(); 869 } 870 871 /** 872 * Returns true if the given method is annotated with one of the annotations Dagger recognizes 873 * for abstract methods (e.g. @Binds). 874 */ 875 public static boolean hasDaggerAbstractMethodAnnotation(ExecutableElement method) { 876 return hasAnnotation(method, ClassNames.BINDS) 877 || hasAnnotation(method, ClassNames.BINDS_OPTIONAL_OF) 878 || hasAnnotation(method, ClassNames.MULTIBINDS) 879 || hasAnnotation(method, ClassNames.CONTRIBUTES_ANDROID_INJECTOR); 880 } 881 882 public static ImmutableSet<TypeElement> toTypeElements(Elements elements, String[] classes) { 883 return FluentIterable.from(classes).transform(elements::getTypeElement).toSet(); 884 } 885 886 public static ImmutableSet<ClassName> toClassNames(Iterable<TypeElement> elements) { 887 return FluentIterable.from(elements).transform(ClassName::get).toSet(); 888 } 889 890 public static boolean requiresModuleInstance(Elements elements, TypeElement module) { 891 // Binding methods that lack ABSTRACT or STATIC require module instantiation. 892 // Required by Dagger. See b/31489617. 893 return ElementFilter.methodsIn(elements.getAllMembers(module)).stream() 894 .filter(Processors::isBindingMethod) 895 .map(ExecutableElement::getModifiers) 896 .anyMatch(modifiers -> !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC)); 897 } 898 899 private static boolean isBindingMethod(ExecutableElement method) { 900 return hasAnnotation(method, ClassNames.PROVIDES) 901 || hasAnnotation(method, ClassNames.BINDS) 902 || hasAnnotation(method, ClassNames.BINDS_OPTIONAL_OF) 903 || hasAnnotation(method, ClassNames.MULTIBINDS); 904 } 905 906 public static void addGeneratedAnnotation( 907 TypeSpec.Builder typeSpecBuilder, ProcessingEnvironment env, Class<?> generatorClass) { 908 addGeneratedAnnotation(typeSpecBuilder, env, generatorClass.getName()); 909 } 910 911 public static void addGeneratedAnnotation( 912 TypeSpec.Builder typeSpecBuilder, ProcessingEnvironment env, String generatorClass) { 913 GeneratedAnnotations.generatedAnnotation(env.getElementUtils(), env.getSourceVersion()) 914 .ifPresent( 915 annotation -> 916 typeSpecBuilder.addAnnotation( 917 AnnotationSpec.builder(ClassName.get(annotation)) 918 .addMember("value", "$S", generatorClass) 919 .build())); 920 } 921 922 public static AnnotationSpec getOriginatingElementAnnotation(TypeElement element) { 923 TypeName rawType = rawTypeName(ClassName.get(getTopLevelType(element))); 924 return AnnotationSpec.builder(ClassNames.ORIGINATING_ELEMENT) 925 .addMember("topLevelClass", "$T.class", rawType) 926 .build(); 927 } 928 929 /** 930 * Returns the {@link TypeName} for the raw type of the given type name. If the argument isn't a 931 * parameterized type, it returns the argument unchanged. 932 */ 933 public static TypeName rawTypeName(TypeName typeName) { 934 return (typeName instanceof ParameterizedTypeName) 935 ? ((ParameterizedTypeName) typeName).rawType 936 : typeName; 937 } 938 939 private Processors() {} 940 } 941