1 package dagger.internal.codegen; 2 3 import com.google.auto.common.MoreTypes; 4 import com.google.auto.value.AutoValue; 5 import com.google.common.base.Function; 6 import com.google.common.base.Optional; 7 import com.google.common.collect.ImmutableSet; 8 import dagger.Module; 9 import dagger.Provides; 10 import dagger.producers.ProducerModule; 11 import dagger.producers.Produces; 12 import java.util.LinkedHashSet; 13 import java.util.Set; 14 import javax.lang.model.element.AnnotationMirror; 15 import javax.lang.model.element.ExecutableElement; 16 import javax.lang.model.element.TypeElement; 17 import javax.lang.model.type.TypeMirror; 18 import javax.lang.model.util.Elements; 19 20 import static com.google.auto.common.MoreElements.getAnnotationMirror; 21 import static com.google.auto.common.MoreElements.isAnnotationPresent; 22 import static com.google.common.base.Verify.verify; 23 import static dagger.internal.codegen.ConfigurationAnnotations.getModuleIncludes; 24 import static dagger.internal.codegen.Util.componentCanMakeNewInstances; 25 import static javax.lang.model.type.TypeKind.DECLARED; 26 import static javax.lang.model.type.TypeKind.NONE; 27 import static javax.lang.model.util.ElementFilter.methodsIn; 28 29 @AutoValue 30 abstract class ModuleDescriptor { getModuleElement()31 static final Function<ModuleDescriptor, TypeElement> getModuleElement() { 32 return new Function<ModuleDescriptor, TypeElement>() { 33 @Override public TypeElement apply(ModuleDescriptor input) { 34 return input.moduleElement(); 35 } 36 }; 37 } 38 39 abstract AnnotationMirror moduleAnnotation(); 40 41 abstract TypeElement moduleElement(); 42 43 abstract ImmutableSet<ModuleDescriptor> includedModules(); 44 45 abstract ImmutableSet<ContributionBinding> bindings(); 46 47 enum DefaultCreationStrategy { 48 PASSED, 49 CONSTRUCTED, 50 } 51 52 abstract DefaultCreationStrategy defaultCreationStrategy(); 53 54 static final class Factory { 55 private final Elements elements; 56 private final ProvisionBinding.Factory provisionBindingFactory; 57 private final ProductionBinding.Factory productionBindingFactory; 58 59 Factory( 60 Elements elements, 61 ProvisionBinding.Factory provisionBindingFactory, 62 ProductionBinding.Factory productionBindingFactory) { 63 this.elements = elements; 64 this.provisionBindingFactory = provisionBindingFactory; 65 this.productionBindingFactory = productionBindingFactory; 66 } 67 68 ModuleDescriptor create(TypeElement moduleElement) { 69 AnnotationMirror moduleAnnotation = getModuleAnnotation(moduleElement).get(); 70 71 ImmutableSet.Builder<ContributionBinding> bindings = ImmutableSet.builder(); 72 for (ExecutableElement moduleMethod : methodsIn(elements.getAllMembers(moduleElement))) { 73 if (isAnnotationPresent(moduleMethod, Provides.class)) { 74 bindings.add( 75 provisionBindingFactory.forProvidesMethod(moduleMethod, moduleElement.asType())); 76 } 77 if (isAnnotationPresent(moduleMethod, Produces.class)) { 78 bindings.add( 79 productionBindingFactory.forProducesMethod(moduleMethod, moduleElement.asType())); 80 } 81 } 82 83 DefaultCreationStrategy defaultCreationStrategy = 84 (componentCanMakeNewInstances(moduleElement) 85 && moduleElement.getTypeParameters().isEmpty()) 86 ? ModuleDescriptor.DefaultCreationStrategy.CONSTRUCTED 87 : ModuleDescriptor.DefaultCreationStrategy.PASSED; 88 89 return new AutoValue_ModuleDescriptor( 90 moduleAnnotation, 91 moduleElement, 92 ImmutableSet.copyOf( 93 collectIncludedModules(new LinkedHashSet<ModuleDescriptor>(), moduleElement)), 94 bindings.build(), 95 defaultCreationStrategy); 96 } 97 98 private static Optional<AnnotationMirror> getModuleAnnotation(TypeElement moduleElement) { 99 return getAnnotationMirror(moduleElement, Module.class) 100 .or(getAnnotationMirror(moduleElement, ProducerModule.class)); 101 } 102 103 private Set<ModuleDescriptor> collectIncludedModules( 104 Set<ModuleDescriptor> includedModules, TypeElement moduleElement) { 105 TypeMirror superclass = moduleElement.getSuperclass(); 106 if (!superclass.getKind().equals(NONE)) { 107 verify(superclass.getKind().equals(DECLARED)); 108 TypeElement superclassElement = MoreTypes.asTypeElement(superclass); 109 if (!superclassElement.getQualifiedName().contentEquals(Object.class.getCanonicalName())) { 110 collectIncludedModules(includedModules, superclassElement); 111 } 112 } 113 Optional<AnnotationMirror> moduleAnnotation = getModuleAnnotation(moduleElement); 114 if (moduleAnnotation.isPresent()) { 115 for (TypeMirror moduleIncludesType : getModuleIncludes(moduleAnnotation.get())) { 116 includedModules.add(create(MoreTypes.asTypeElement(moduleIncludesType))); 117 } 118 } 119 return includedModules; 120 } 121 } 122 } 123