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