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