• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.MoreElements.isAnnotationPresent;
20 import static javax.lang.model.util.ElementFilter.methodsIn;
21 import static javax.lang.model.util.ElementFilter.typesIn;
22 
23 import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
24 import com.google.auto.common.MoreElements;
25 import com.google.common.collect.ImmutableSet;
26 import com.google.common.collect.SetMultimap;
27 import com.google.common.collect.Sets;
28 import dagger.Binds;
29 import dagger.Module;
30 import dagger.Provides;
31 import dagger.internal.codegen.DelegateDeclaration.Factory;
32 import dagger.producers.ProducerModule;
33 import dagger.producers.Produces;
34 import java.lang.annotation.Annotation;
35 import java.util.List;
36 import java.util.Set;
37 import javax.annotation.processing.Messager;
38 import javax.inject.Inject;
39 import javax.lang.model.element.Element;
40 import javax.lang.model.element.ExecutableElement;
41 import javax.lang.model.element.TypeElement;
42 
43 /**
44  * A {@link ProcessingStep} that validates module classes and generates factories for binding
45  * methods.
46  */
47 final class ModuleProcessingStep extends TypeCheckingProcessingStep<TypeElement> {
48   private final Messager messager;
49   private final ModuleValidator moduleValidator;
50   private final BindingFactory bindingFactory;
51   private final SourceFileGenerator<ProvisionBinding> factoryGenerator;
52   private final SourceFileGenerator<ProductionBinding> producerFactoryGenerator;
53   private final SourceFileGenerator<TypeElement> moduleConstructorProxyGenerator;
54   private final InaccessibleMapKeyProxyGenerator inaccessibleMapKeyProxyGenerator;
55   private final DelegateDeclaration.Factory delegateDeclarationFactory;
56   private final Set<TypeElement> processedModuleElements = Sets.newLinkedHashSet();
57 
58   @Inject
ModuleProcessingStep( Messager messager, ModuleValidator moduleValidator, BindingFactory bindingFactory, SourceFileGenerator<ProvisionBinding> factoryGenerator, SourceFileGenerator<ProductionBinding> producerFactoryGenerator, @ModuleGenerator SourceFileGenerator<TypeElement> moduleConstructorProxyGenerator, InaccessibleMapKeyProxyGenerator inaccessibleMapKeyProxyGenerator, Factory delegateDeclarationFactory)59   ModuleProcessingStep(
60       Messager messager,
61       ModuleValidator moduleValidator,
62       BindingFactory bindingFactory,
63       SourceFileGenerator<ProvisionBinding> factoryGenerator,
64       SourceFileGenerator<ProductionBinding> producerFactoryGenerator,
65       @ModuleGenerator SourceFileGenerator<TypeElement> moduleConstructorProxyGenerator,
66       InaccessibleMapKeyProxyGenerator inaccessibleMapKeyProxyGenerator,
67       Factory delegateDeclarationFactory) {
68     super(MoreElements::asType);
69     this.messager = messager;
70     this.moduleValidator = moduleValidator;
71     this.bindingFactory = bindingFactory;
72     this.factoryGenerator = factoryGenerator;
73     this.producerFactoryGenerator = producerFactoryGenerator;
74     this.moduleConstructorProxyGenerator = moduleConstructorProxyGenerator;
75     this.inaccessibleMapKeyProxyGenerator = inaccessibleMapKeyProxyGenerator;
76     this.delegateDeclarationFactory = delegateDeclarationFactory;
77   }
78 
79   @Override
annotations()80   public Set<? extends Class<? extends Annotation>> annotations() {
81     return ImmutableSet.of(Module.class, ProducerModule.class);
82   }
83 
84   @Override
process( SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation)85   public ImmutableSet<Element> process(
86       SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
87     List<TypeElement> modules = typesIn(elementsByAnnotation.values());
88     moduleValidator.addKnownModules(modules);
89     return super.process(elementsByAnnotation);
90   }
91 
92   @Override
process( TypeElement module, ImmutableSet<Class<? extends Annotation>> annotations)93   protected void process(
94       TypeElement module, ImmutableSet<Class<? extends Annotation>> annotations) {
95     if (processedModuleElements.contains(module)) {
96       return;
97     }
98     ValidationReport<TypeElement> report = moduleValidator.validate(module);
99     report.printMessagesTo(messager);
100     if (report.isClean()) {
101       for (ExecutableElement method : methodsIn(module.getEnclosedElements())) {
102         if (isAnnotationPresent(method, Provides.class)) {
103           generate(factoryGenerator, bindingFactory.providesMethodBinding(method, module));
104         } else if (isAnnotationPresent(method, Produces.class)) {
105           generate(producerFactoryGenerator, bindingFactory.producesMethodBinding(method, module));
106         } else if (isAnnotationPresent(method, Binds.class)) {
107           inaccessibleMapKeyProxyGenerator.generate(bindsMethodBinding(module, method), messager);
108         }
109       }
110       moduleConstructorProxyGenerator.generate(module, messager);
111     }
112     processedModuleElements.add(module);
113   }
114 
generate( SourceFileGenerator<B> generator, B binding)115   private <B extends ContributionBinding> void generate(
116       SourceFileGenerator<B> generator, B binding) {
117     generator.generate(binding, messager);
118     inaccessibleMapKeyProxyGenerator.generate(binding, messager);
119   }
120 
bindsMethodBinding(TypeElement module, ExecutableElement method)121   private ContributionBinding bindsMethodBinding(TypeElement module, ExecutableElement method) {
122     return bindingFactory.unresolvedDelegateBinding(
123         delegateDeclarationFactory.create(method, module));
124   }
125 }
126