• 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.internal.codegen.base;
18 
19 import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
20 import static com.google.auto.common.MoreElements.asType;
21 import static com.google.auto.common.MoreTypes.asTypeElements;
22 import static com.google.auto.common.MoreTypes.isTypeOf;
23 import static dagger.internal.codegen.base.MoreAnnotationValues.asAnnotationValues;
24 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
25 import static dagger.internal.codegen.javapoet.TypeNames.PRODUCER_MODULE;
26 import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
27 
28 import com.google.auto.value.AutoValue;
29 import com.google.auto.value.extension.memoized.Memoized;
30 import com.google.common.collect.ImmutableList;
31 import com.google.common.collect.ImmutableSet;
32 import com.squareup.javapoet.ClassName;
33 import dagger.Component;
34 import dagger.Subcomponent;
35 import dagger.producers.ProductionComponent;
36 import dagger.producers.ProductionSubcomponent;
37 import java.lang.annotation.Annotation;
38 import java.util.Collection;
39 import java.util.Optional;
40 import javax.lang.model.element.AnnotationMirror;
41 import javax.lang.model.element.AnnotationValue;
42 import javax.lang.model.element.TypeElement;
43 import javax.lang.model.type.TypeMirror;
44 
45 /**
46  * A {@code @Component}, {@code @Subcomponent}, {@code @ProductionComponent}, or
47  * {@code @ProductionSubcomponent} annotation, or a {@code @Module} or {@code @ProducerModule}
48  * annotation that is being treated as a component annotation when validating full binding graphs
49  * for modules.
50  */
51 public abstract class ComponentAnnotation {
52   /** The root component annotation types. */
53   private static final ImmutableSet<Class<? extends Annotation>> ROOT_COMPONENT_ANNOTATIONS =
54      ImmutableSet.of(Component.class, ProductionComponent.class);
55 
56   /** The subcomponent annotation types. */
57   private static final ImmutableSet<Class<? extends Annotation>> SUBCOMPONENT_ANNOTATIONS =
58      ImmutableSet.of(Subcomponent.class, ProductionSubcomponent.class);
59 
60   // TODO(erichang): Move ComponentCreatorAnnotation into /base and use that here?
61   /** The component/subcomponent creator annotation types. */
62   private static final ImmutableSet<Class<? extends Annotation>> CREATOR_ANNOTATIONS =
63       ImmutableSet.of(
64           Component.Builder.class,
65           Component.Factory.class,
66           ProductionComponent.Builder.class,
67           ProductionComponent.Factory.class,
68           Subcomponent.Builder.class,
69           Subcomponent.Factory.class,
70           ProductionSubcomponent.Builder.class,
71           ProductionSubcomponent.Factory.class);
72 
73   /** All component annotation types. */
74   private static final ImmutableSet<Class<? extends Annotation>> ALL_COMPONENT_ANNOTATIONS =
75      ImmutableSet.<Class<? extends Annotation>>builder()
76          .addAll(ROOT_COMPONENT_ANNOTATIONS)
77          .addAll(SUBCOMPONENT_ANNOTATIONS)
78          .build();
79 
80   /** All component and creator annotation types. */
81   private static final ImmutableSet<Class<? extends Annotation>>
82       ALL_COMPONENT_AND_CREATOR_ANNOTATIONS = ImmutableSet.<Class<? extends Annotation>>builder()
83          .addAll(ALL_COMPONENT_ANNOTATIONS)
84          .addAll(CREATOR_ANNOTATIONS)
85          .build();
86 
87   /** The annotation itself. */
annotation()88   public abstract AnnotationMirror annotation();
89 
90   /** The simple name of the annotation type. */
simpleName()91   public String simpleName() {
92     return MoreAnnotationMirrors.simpleName(annotation()).toString();
93   }
94 
95   /**
96    * Returns {@code true} if the annotation is a {@code @Subcomponent} or
97    * {@code @ProductionSubcomponent}.
98    */
isSubcomponent()99   public abstract boolean isSubcomponent();
100 
101   /**
102    * Returns {@code true} if the annotation is a {@code @ProductionComponent},
103    * {@code @ProductionSubcomponent}, or {@code @ProducerModule}.
104    */
isProduction()105   public abstract boolean isProduction();
106 
107   /**
108    * Returns {@code true} if the annotation is a real component annotation and not a module
109    * annotation.
110    */
isRealComponent()111   public abstract boolean isRealComponent();
112 
113   /** The values listed as {@code dependencies}. */
dependencyValues()114   public abstract ImmutableList<AnnotationValue> dependencyValues();
115 
116   /** The types listed as {@code dependencies}. */
dependencyTypes()117   public ImmutableList<TypeMirror> dependencyTypes() {
118     return dependencyValues().stream().map(MoreAnnotationValues::asType).collect(toImmutableList());
119   }
120 
121   /**
122    * The types listed as {@code dependencies}.
123    *
124    * @throws IllegalArgumentException if any of {@link #dependencyTypes()} are error types
125    */
dependencies()126   public ImmutableList<TypeElement> dependencies() {
127     return asTypeElements(dependencyTypes()).asList();
128   }
129 
130   /** The values listed as {@code modules}. */
moduleValues()131   public abstract ImmutableList<AnnotationValue> moduleValues();
132 
133   /** The types listed as {@code modules}. */
moduleTypes()134   public ImmutableList<TypeMirror> moduleTypes() {
135     return moduleValues().stream().map(MoreAnnotationValues::asType).collect(toImmutableList());
136   }
137 
138   /**
139    * The types listed as {@code modules}.
140    *
141    * @throws IllegalArgumentException if any of {@link #moduleTypes()} are error types
142    */
modules()143   public ImmutableSet<TypeElement> modules() {
144     return asTypeElements(moduleTypes());
145   }
146 
getAnnotationValues(String parameterName)147   protected final ImmutableList<AnnotationValue> getAnnotationValues(String parameterName) {
148     return asAnnotationValues(getAnnotationValue(annotation(), parameterName));
149   }
150 
151   /**
152    * Returns an object representing a root component annotation, not a subcomponent annotation, if
153    * one is present on {@code typeElement}.
154    */
rootComponentAnnotation(TypeElement typeElement)155   public static Optional<ComponentAnnotation> rootComponentAnnotation(TypeElement typeElement) {
156     return anyComponentAnnotation(typeElement, ROOT_COMPONENT_ANNOTATIONS);
157   }
158 
159   /**
160    * Returns an object representing a subcomponent annotation, if one is present on {@code
161    * typeElement}.
162    */
subcomponentAnnotation(TypeElement typeElement)163   public static Optional<ComponentAnnotation> subcomponentAnnotation(TypeElement typeElement) {
164     return anyComponentAnnotation(typeElement, SUBCOMPONENT_ANNOTATIONS);
165   }
166 
167   /**
168    * Returns an object representing a root component or subcomponent annotation, if one is present
169    * on {@code typeElement}.
170    */
anyComponentAnnotation(TypeElement typeElement)171   public static Optional<ComponentAnnotation> anyComponentAnnotation(TypeElement typeElement) {
172     return anyComponentAnnotation(typeElement, ALL_COMPONENT_ANNOTATIONS);
173   }
174 
anyComponentAnnotation( TypeElement typeElement, Collection<Class<? extends Annotation>> annotations)175   private static Optional<ComponentAnnotation> anyComponentAnnotation(
176       TypeElement typeElement, Collection<Class<? extends Annotation>> annotations) {
177     return getAnyAnnotation(typeElement, annotations).map(ComponentAnnotation::componentAnnotation);
178   }
179 
180   /** Returns {@code true} if the argument is a component annotation. */
isComponentAnnotation(AnnotationMirror annotation)181   public static boolean isComponentAnnotation(AnnotationMirror annotation) {
182     return ALL_COMPONENT_ANNOTATIONS.stream()
183         .anyMatch(annotationClass -> isTypeOf(annotationClass, annotation.getAnnotationType()));
184   }
185 
186   /** Creates an object representing a component or subcomponent annotation. */
componentAnnotation(AnnotationMirror annotation)187   public static ComponentAnnotation componentAnnotation(AnnotationMirror annotation) {
188     RealComponentAnnotation.Builder annotationBuilder =
189         RealComponentAnnotation.builder().annotation(annotation);
190 
191     if (isTypeOf(Component.class, annotation.getAnnotationType())) {
192       return annotationBuilder.isProduction(false).isSubcomponent(false).build();
193     }
194     if (isTypeOf(Subcomponent.class, annotation.getAnnotationType())) {
195       return annotationBuilder.isProduction(false).isSubcomponent(true).build();
196     }
197     if (isTypeOf(ProductionComponent.class, annotation.getAnnotationType())) {
198       return annotationBuilder.isProduction(true).isSubcomponent(false).build();
199     }
200     if (isTypeOf(ProductionSubcomponent.class, annotation.getAnnotationType())) {
201       return annotationBuilder.isProduction(true).isSubcomponent(true).build();
202     }
203     throw new IllegalArgumentException(
204         annotation
205             + " must be a Component, Subcomponent, ProductionComponent, "
206             + "or ProductionSubcomponent annotation");
207   }
208 
209   /** Creates a fictional component annotation representing a module. */
fromModuleAnnotation(ModuleAnnotation moduleAnnotation)210   public static ComponentAnnotation fromModuleAnnotation(ModuleAnnotation moduleAnnotation) {
211     return new AutoValue_ComponentAnnotation_FictionalComponentAnnotation(moduleAnnotation);
212   }
213 
214   /** The root component annotation types. */
rootComponentAnnotations()215   public static ImmutableSet<Class<? extends Annotation>> rootComponentAnnotations() {
216     return ROOT_COMPONENT_ANNOTATIONS;
217   }
218 
219   /** The subcomponent annotation types. */
subcomponentAnnotations()220   public static ImmutableSet<Class<? extends Annotation>> subcomponentAnnotations() {
221     return SUBCOMPONENT_ANNOTATIONS;
222   }
223 
224   /** All component annotation types. */
allComponentAnnotations()225   public static ImmutableSet<Class<? extends Annotation>> allComponentAnnotations() {
226     return ALL_COMPONENT_ANNOTATIONS;
227   }
228 
229   /** All component and creator annotation types. */
allComponentAndCreatorAnnotations()230   public static ImmutableSet<Class<? extends Annotation>> allComponentAndCreatorAnnotations() {
231     return ALL_COMPONENT_AND_CREATOR_ANNOTATIONS;
232   }
233 
234   /**
235    * An actual component annotation.
236    *
237    * @see FictionalComponentAnnotation
238    */
239   @AutoValue
240   abstract static class RealComponentAnnotation extends ComponentAnnotation {
241 
242     @Override
243     @Memoized
dependencyValues()244     public ImmutableList<AnnotationValue> dependencyValues() {
245       return isSubcomponent() ? ImmutableList.of() : getAnnotationValues("dependencies");
246     }
247 
248     @Override
249     @Memoized
dependencyTypes()250     public ImmutableList<TypeMirror> dependencyTypes() {
251       return super.dependencyTypes();
252     }
253 
254     @Override
255     @Memoized
dependencies()256     public ImmutableList<TypeElement> dependencies() {
257       return super.dependencies();
258     }
259 
260     @Override
isRealComponent()261     public boolean isRealComponent() {
262       return true;
263     }
264 
265     @Override
266     @Memoized
moduleValues()267     public ImmutableList<AnnotationValue> moduleValues() {
268       return getAnnotationValues("modules");
269     }
270 
271     @Override
272     @Memoized
moduleTypes()273     public ImmutableList<TypeMirror> moduleTypes() {
274       return super.moduleTypes();
275     }
276 
277     @Override
278     @Memoized
modules()279     public ImmutableSet<TypeElement> modules() {
280       return super.modules();
281     }
282 
builder()283     static Builder builder() {
284       return new AutoValue_ComponentAnnotation_RealComponentAnnotation.Builder();
285     }
286 
287     @AutoValue.Builder
288     interface Builder {
annotation(AnnotationMirror annotation)289       Builder annotation(AnnotationMirror annotation);
290 
isSubcomponent(boolean isSubcomponent)291       Builder isSubcomponent(boolean isSubcomponent);
292 
isProduction(boolean isProduction)293       Builder isProduction(boolean isProduction);
294 
build()295       RealComponentAnnotation build();
296     }
297   }
298 
299   /**
300    * A fictional component annotation used to represent modules or other collections of bindings as
301    * a component.
302    */
303   @AutoValue
304   abstract static class FictionalComponentAnnotation extends ComponentAnnotation {
305 
306     @Override
annotation()307     public AnnotationMirror annotation() {
308       return moduleAnnotation().annotation();
309     }
310 
311     @Override
isSubcomponent()312     public boolean isSubcomponent() {
313       return false;
314     }
315 
316     @Override
isProduction()317     public boolean isProduction() {
318       return ClassName.get(asType(moduleAnnotation().annotation().getAnnotationType().asElement()))
319           .equals(PRODUCER_MODULE);
320     }
321 
322     @Override
isRealComponent()323     public boolean isRealComponent() {
324       return false;
325     }
326 
327     @Override
dependencyValues()328     public ImmutableList<AnnotationValue> dependencyValues() {
329       return ImmutableList.of();
330     }
331 
332     @Override
moduleValues()333     public ImmutableList<AnnotationValue> moduleValues() {
334       return moduleAnnotation().includesAsAnnotationValues();
335     }
336 
337     @Override
338     @Memoized
moduleTypes()339     public ImmutableList<TypeMirror> moduleTypes() {
340       return super.moduleTypes();
341     }
342 
343     @Override
344     @Memoized
modules()345     public ImmutableSet<TypeElement> modules() {
346       return super.modules();
347     }
348 
moduleAnnotation()349     public abstract ModuleAnnotation moduleAnnotation();
350   }
351 }
352