• 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.binding;
18 
19 import static com.google.auto.common.MoreElements.isAnnotationPresent;
20 import static com.google.common.base.Ascii.toUpperCase;
21 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
22 import static dagger.internal.codegen.extension.DaggerStreams.valuesOf;
23 import static java.util.stream.Collectors.mapping;
24 
25 import com.google.common.collect.ImmutableSet;
26 import dagger.Component;
27 import dagger.Subcomponent;
28 import dagger.internal.codegen.base.ComponentAnnotation;
29 import dagger.producers.ProductionComponent;
30 import dagger.producers.ProductionSubcomponent;
31 import java.lang.annotation.Annotation;
32 import java.util.stream.Collector;
33 import java.util.stream.Stream;
34 import javax.lang.model.element.TypeElement;
35 
36 /** Simple representation of a component creator annotation type. */
37 public enum ComponentCreatorAnnotation {
38   COMPONENT_BUILDER(Component.Builder.class),
39   COMPONENT_FACTORY(Component.Factory.class),
40   SUBCOMPONENT_BUILDER(Subcomponent.Builder.class),
41   SUBCOMPONENT_FACTORY(Subcomponent.Factory.class),
42   PRODUCTION_COMPONENT_BUILDER(ProductionComponent.Builder.class),
43   PRODUCTION_COMPONENT_FACTORY(ProductionComponent.Factory.class),
44   PRODUCTION_SUBCOMPONENT_BUILDER(ProductionSubcomponent.Builder.class),
45   PRODUCTION_SUBCOMPONENT_FACTORY(ProductionSubcomponent.Factory.class),
46   ;
47 
48   private final Class<? extends Annotation> annotation;
49   private final ComponentCreatorKind creatorKind;
50   private final Class<? extends Annotation> componentAnnotation;
51 
52   @SuppressWarnings("unchecked") // Builder/factory annotations live within their parent annotation.
ComponentCreatorAnnotation(Class<? extends Annotation> annotation)53   ComponentCreatorAnnotation(Class<? extends Annotation> annotation) {
54     this.annotation = annotation;
55     this.creatorKind = ComponentCreatorKind.valueOf(toUpperCase(annotation.getSimpleName()));
56     this.componentAnnotation = (Class<? extends Annotation>) annotation.getEnclosingClass();
57   }
58 
59   /** The actual annotation type. */
annotation()60   public Class<? extends Annotation> annotation() {
61     return annotation;
62   }
63 
64   /** The component annotation type that encloses this creator annotation type. */
componentAnnotation()65   public final Class<? extends Annotation> componentAnnotation() {
66     return componentAnnotation;
67   }
68 
69   /** Returns {@code true} if the creator annotation is for a subcomponent. */
isSubcomponentCreatorAnnotation()70   public final boolean isSubcomponentCreatorAnnotation() {
71     return componentAnnotation().getSimpleName().endsWith("Subcomponent");
72   }
73 
74   /**
75    * Returns {@code true} if the creator annotation is for a production component or subcomponent.
76    */
isProductionCreatorAnnotation()77   public final boolean isProductionCreatorAnnotation() {
78     return componentAnnotation().getSimpleName().startsWith("Production");
79   }
80 
81   /** The creator kind the annotation is associated with. */
82   // TODO(dpb): Remove ComponentCreatorKind.
creatorKind()83   public ComponentCreatorKind creatorKind() {
84     return creatorKind;
85   }
86 
87   @Override
toString()88   public final String toString() {
89     return annotation().getName();
90   }
91 
92   /** Returns all component creator annotations. */
allCreatorAnnotations()93   public static ImmutableSet<Class<? extends Annotation>> allCreatorAnnotations() {
94     return stream().collect(toAnnotationClasses());
95   }
96 
97   /** Returns all root component creator annotations. */
rootComponentCreatorAnnotations()98   public static ImmutableSet<Class<? extends Annotation>> rootComponentCreatorAnnotations() {
99     return stream()
100         .filter(
101             componentCreatorAnnotation ->
102                 !componentCreatorAnnotation.isSubcomponentCreatorAnnotation())
103         .collect(toAnnotationClasses());
104   }
105 
106   /** Returns all subcomponent creator annotations. */
subcomponentCreatorAnnotations()107   public static ImmutableSet<Class<? extends Annotation>> subcomponentCreatorAnnotations() {
108     return stream()
109         .filter(
110             componentCreatorAnnotation ->
111                 componentCreatorAnnotation.isSubcomponentCreatorAnnotation())
112         .collect(toAnnotationClasses());
113   }
114 
115   /** Returns all production component creator annotations. */
productionCreatorAnnotations()116   public static ImmutableSet<Class<? extends Annotation>> productionCreatorAnnotations() {
117     return stream()
118         .filter(
119             componentCreatorAnnotation ->
120                 componentCreatorAnnotation.isProductionCreatorAnnotation())
121         .collect(toAnnotationClasses());
122   }
123 
124   /** Returns the legal creator annotations for the given {@code componentAnnotation}. */
creatorAnnotationsFor( ComponentAnnotation componentAnnotation)125   public static ImmutableSet<Class<? extends Annotation>> creatorAnnotationsFor(
126       ComponentAnnotation componentAnnotation) {
127     return stream()
128         .filter(
129             creatorAnnotation ->
130                 creatorAnnotation
131                     .componentAnnotation()
132                     .getSimpleName()
133                     .equals(componentAnnotation.simpleName()))
134         .collect(toAnnotationClasses());
135   }
136 
137   /** Returns all creator annotations present on the given {@code type}. */
getCreatorAnnotations(TypeElement type)138   public static ImmutableSet<ComponentCreatorAnnotation> getCreatorAnnotations(TypeElement type) {
139     return stream()
140         .filter(cca -> isAnnotationPresent(type, cca.annotation()))
141         .collect(toImmutableSet());
142   }
143 
stream()144   private static Stream<ComponentCreatorAnnotation> stream() {
145     return valuesOf(ComponentCreatorAnnotation.class);
146   }
147 
148   private static Collector<ComponentCreatorAnnotation, ?, ImmutableSet<Class<? extends Annotation>>>
toAnnotationClasses()149       toAnnotationClasses() {
150     return mapping(ComponentCreatorAnnotation::annotation, toImmutableSet());
151   }
152 }
153