• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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