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