15d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinpackage dagger.internal.codegen;
25d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
35d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.auto.common.MoreTypes;
45d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.auto.value.AutoValue;
55d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.base.Function;
65d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.base.Optional;
75d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.collect.ImmutableSet;
85d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport dagger.Module;
95d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport dagger.Provides;
105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport dagger.producers.ProducerModule;
115d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport dagger.producers.Produces;
125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.LinkedHashSet;
135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.Set;
145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.element.AnnotationMirror;
155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.element.ExecutableElement;
165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.element.TypeElement;
175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.type.TypeMirror;
185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.util.Elements;
195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
205d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static com.google.auto.common.MoreElements.getAnnotationMirror;
215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static com.google.auto.common.MoreElements.isAnnotationPresent;
225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static com.google.common.base.Verify.verify;
235d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static dagger.internal.codegen.ConfigurationAnnotations.getModuleIncludes;
245d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static dagger.internal.codegen.Util.componentCanMakeNewInstances;
255d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static javax.lang.model.type.TypeKind.DECLARED;
265d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static javax.lang.model.type.TypeKind.NONE;
275d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static javax.lang.model.util.ElementFilter.methodsIn;
285d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
295d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin@AutoValue
305d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinabstract class ModuleDescriptor {
315d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  static final Function<ModuleDescriptor, TypeElement> getModuleElement() {
325d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    return new Function<ModuleDescriptor, TypeElement>() {
335d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      @Override public TypeElement apply(ModuleDescriptor input) {
345d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        return input.moduleElement();
355d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
365d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    };
375d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
385d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
395d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  abstract AnnotationMirror moduleAnnotation();
405d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
415d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  abstract TypeElement moduleElement();
425d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
435d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  abstract ImmutableSet<ModuleDescriptor> includedModules();
445d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
4587182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin  abstract ImmutableSet<ContributionBinding> bindings();
465d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
475d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  enum DefaultCreationStrategy {
485d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    PASSED,
495d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    CONSTRUCTED,
505d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
515d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
525d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  abstract DefaultCreationStrategy defaultCreationStrategy();
535d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
545d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  static final class Factory {
555d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    private final Elements elements;
565d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    private final ProvisionBinding.Factory provisionBindingFactory;
575d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    private final ProductionBinding.Factory productionBindingFactory;
585d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
595d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    Factory(
605d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        Elements elements,
615d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        ProvisionBinding.Factory provisionBindingFactory,
625d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        ProductionBinding.Factory productionBindingFactory) {
635d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      this.elements = elements;
645d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      this.provisionBindingFactory = provisionBindingFactory;
655d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      this.productionBindingFactory = productionBindingFactory;
665d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
675d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
685d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    ModuleDescriptor create(TypeElement moduleElement) {
695d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      AnnotationMirror moduleAnnotation = getModuleAnnotation(moduleElement).get();
705d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
715d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      ImmutableSet.Builder<ContributionBinding> bindings = ImmutableSet.builder();
725d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      for (ExecutableElement moduleMethod : methodsIn(elements.getAllMembers(moduleElement))) {
735d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        if (isAnnotationPresent(moduleMethod, Provides.class)) {
745d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          bindings.add(
755d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin              provisionBindingFactory.forProvidesMethod(moduleMethod, moduleElement.asType()));
765d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        }
775d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        if (isAnnotationPresent(moduleMethod, Produces.class)) {
785d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          bindings.add(
795d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin              productionBindingFactory.forProducesMethod(moduleMethod, moduleElement.asType()));
805d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        }
815d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
825d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
835d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      DefaultCreationStrategy defaultCreationStrategy =
845d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          (componentCanMakeNewInstances(moduleElement)
855d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin              && moduleElement.getTypeParameters().isEmpty())
865d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin                  ? ModuleDescriptor.DefaultCreationStrategy.CONSTRUCTED
875d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin                  : ModuleDescriptor.DefaultCreationStrategy.PASSED;
885d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
895d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      return new AutoValue_ModuleDescriptor(
905d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          moduleAnnotation,
915d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          moduleElement,
925d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          ImmutableSet.copyOf(
935d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin              collectIncludedModules(new LinkedHashSet<ModuleDescriptor>(), moduleElement)),
945d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          bindings.build(),
955d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          defaultCreationStrategy);
965d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
975d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
985d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    private static Optional<AnnotationMirror> getModuleAnnotation(TypeElement moduleElement) {
995d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      return getAnnotationMirror(moduleElement, Module.class)
1005d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          .or(getAnnotationMirror(moduleElement, ProducerModule.class));
1015d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1025d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1035d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    private Set<ModuleDescriptor> collectIncludedModules(
1045d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        Set<ModuleDescriptor> includedModules, TypeElement moduleElement) {
1055d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      TypeMirror superclass = moduleElement.getSuperclass();
1065d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      if (!superclass.getKind().equals(NONE)) {
1075d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        verify(superclass.getKind().equals(DECLARED));
1085d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        TypeElement superclassElement = MoreTypes.asTypeElement(superclass);
1095d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        if (!superclassElement.getQualifiedName().contentEquals(Object.class.getCanonicalName())) {
1105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          collectIncludedModules(includedModules, superclassElement);
1115d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        }
1125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
1135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      Optional<AnnotationMirror> moduleAnnotation = getModuleAnnotation(moduleElement);
1145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      if (moduleAnnotation.isPresent()) {
1155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        for (TypeMirror moduleIncludesType : getModuleIncludes(moduleAnnotation.get())) {
1165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          includedModules.add(create(MoreTypes.asTypeElement(moduleIncludesType)));
1175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        }
1185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
1195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      return includedModules;
1205d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
1225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin}
123