• 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 net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
20 
21 import com.google.auto.common.BasicAnnotationProcessor;
22 import com.google.auto.service.AutoService;
23 import com.google.common.annotations.VisibleForTesting;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.ImmutableSet;
26 import com.google.common.collect.Sets;
27 import com.google.errorprone.annotations.CheckReturnValue;
28 import dagger.BindsInstance;
29 import dagger.Component;
30 import dagger.Module;
31 import dagger.Provides;
32 import dagger.internal.codegen.SpiModule.TestingPlugins;
33 import dagger.internal.codegen.base.ClearableCache;
34 import dagger.internal.codegen.base.SourceFileGenerationException;
35 import dagger.internal.codegen.base.SourceFileGenerator;
36 import dagger.internal.codegen.binding.InjectBindingRegistry;
37 import dagger.internal.codegen.binding.MembersInjectionBinding;
38 import dagger.internal.codegen.binding.ProvisionBinding;
39 import dagger.internal.codegen.bindinggraphvalidation.BindingGraphValidationModule;
40 import dagger.internal.codegen.compileroption.CompilerOptions;
41 import dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions;
42 import dagger.internal.codegen.componentgenerator.ComponentGeneratorModule;
43 import dagger.internal.codegen.validation.BindingGraphPlugins;
44 import dagger.internal.codegen.validation.BindingMethodProcessingStep;
45 import dagger.internal.codegen.validation.BindingMethodValidatorsModule;
46 import dagger.internal.codegen.validation.BindsInstanceProcessingStep;
47 import dagger.internal.codegen.validation.InjectBindingRegistryModule;
48 import dagger.internal.codegen.validation.MonitoringModuleProcessingStep;
49 import dagger.internal.codegen.validation.MultibindingAnnotationsProcessingStep;
50 import dagger.spi.BindingGraphPlugin;
51 import java.util.Arrays;
52 import java.util.Optional;
53 import java.util.Set;
54 import javax.annotation.processing.ProcessingEnvironment;
55 import javax.annotation.processing.Processor;
56 import javax.annotation.processing.RoundEnvironment;
57 import javax.inject.Inject;
58 import javax.inject.Singleton;
59 import javax.lang.model.SourceVersion;
60 import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
61 
62 /**
63  * The annotation processor responsible for generating the classes that drive the Dagger 2.0
64  * implementation.
65  *
66  * <p>TODO(gak): give this some better documentation
67  */
68 @IncrementalAnnotationProcessor(ISOLATING)
69 @AutoService(Processor.class)
70 public class ComponentProcessor extends BasicAnnotationProcessor {
71   private final Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins;
72 
73   @Inject InjectBindingRegistry injectBindingRegistry;
74   @Inject SourceFileGenerator<ProvisionBinding> factoryGenerator;
75   @Inject SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator;
76   @Inject ImmutableList<ProcessingStep> processingSteps;
77   @Inject BindingGraphPlugins bindingGraphPlugins;
78   @Inject Set<ClearableCache> clearableCaches;
79 
ComponentProcessor()80   public ComponentProcessor() {
81     this.testingPlugins = Optional.empty();
82   }
83 
ComponentProcessor(Iterable<BindingGraphPlugin> testingPlugins)84   private ComponentProcessor(Iterable<BindingGraphPlugin> testingPlugins) {
85     this.testingPlugins = Optional.of(ImmutableSet.copyOf(testingPlugins));
86   }
87 
88   /**
89    * Creates a component processor that uses given {@link BindingGraphPlugin}s instead of loading
90    * them from a {@link java.util.ServiceLoader}.
91    */
92   @VisibleForTesting
forTesting(BindingGraphPlugin... testingPlugins)93   public static ComponentProcessor forTesting(BindingGraphPlugin... testingPlugins) {
94     return forTesting(Arrays.asList(testingPlugins));
95   }
96 
97   /**
98    * Creates a component processor that uses given {@link BindingGraphPlugin}s instead of loading
99    * them from a {@link java.util.ServiceLoader}.
100    */
101   @VisibleForTesting
forTesting(Iterable<BindingGraphPlugin> testingPlugins)102   public static ComponentProcessor forTesting(Iterable<BindingGraphPlugin> testingPlugins) {
103     return new ComponentProcessor(testingPlugins);
104   }
105 
106   @Override
getSupportedSourceVersion()107   public SourceVersion getSupportedSourceVersion() {
108     return SourceVersion.latestSupported();
109   }
110 
111   @Override
getSupportedOptions()112   public Set<String> getSupportedOptions() {
113     return Sets.union(
114             ProcessingEnvironmentCompilerOptions.supportedOptions(),
115             bindingGraphPlugins.allSupportedOptions())
116         .immutableCopy();
117   }
118 
119   @Override
initSteps()120   protected Iterable<? extends ProcessingStep> initSteps() {
121     ProcessorComponent.factory().create(processingEnv, testingPlugins).inject(this);
122 
123     bindingGraphPlugins.initializePlugins();
124 
125     return processingSteps;
126   }
127 
128   @Singleton
129   @Component(
130       modules = {
131         BindingGraphValidationModule.class,
132         BindingMethodValidatorsModule.class,
133         ComponentGeneratorModule.class,
134         InjectBindingRegistryModule.class,
135         ProcessingEnvironmentModule.class,
136         ProcessingRoundCacheModule.class,
137         ProcessingStepsModule.class,
138         SourceFileGeneratorsModule.class,
139         SpiModule.class
140       })
141   interface ProcessorComponent {
inject(ComponentProcessor processor)142     void inject(ComponentProcessor processor);
143 
factory()144     static Factory factory() {
145       return DaggerComponentProcessor_ProcessorComponent.factory();
146     }
147 
148     @Component.Factory
149     interface Factory {
150       @CheckReturnValue
create( @indsInstance ProcessingEnvironment processingEnv, @BindsInstance @TestingPlugins Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins)151       ProcessorComponent create(
152           @BindsInstance ProcessingEnvironment processingEnv,
153           @BindsInstance @TestingPlugins Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins);
154     }
155   }
156 
157   @Module
158   interface ProcessingStepsModule {
159     @Provides
processingSteps( MapKeyProcessingStep mapKeyProcessingStep, InjectProcessingStep injectProcessingStep, AssistedInjectProcessingStep assistedInjectProcessingStep, AssistedFactoryProcessingStep assistedFactoryProcessingStep, AssistedProcessingStep assistedProcessingStep, MonitoringModuleProcessingStep monitoringModuleProcessingStep, MultibindingAnnotationsProcessingStep multibindingAnnotationsProcessingStep, BindsInstanceProcessingStep bindsInstanceProcessingStep, ModuleProcessingStep moduleProcessingStep, ComponentProcessingStep componentProcessingStep, ComponentHjarProcessingStep componentHjarProcessingStep, BindingMethodProcessingStep bindingMethodProcessingStep, CompilerOptions compilerOptions)160     static ImmutableList<ProcessingStep> processingSteps(
161         MapKeyProcessingStep mapKeyProcessingStep,
162         InjectProcessingStep injectProcessingStep,
163         AssistedInjectProcessingStep assistedInjectProcessingStep,
164         AssistedFactoryProcessingStep assistedFactoryProcessingStep,
165         AssistedProcessingStep assistedProcessingStep,
166         MonitoringModuleProcessingStep monitoringModuleProcessingStep,
167         MultibindingAnnotationsProcessingStep multibindingAnnotationsProcessingStep,
168         BindsInstanceProcessingStep bindsInstanceProcessingStep,
169         ModuleProcessingStep moduleProcessingStep,
170         ComponentProcessingStep componentProcessingStep,
171         ComponentHjarProcessingStep componentHjarProcessingStep,
172         BindingMethodProcessingStep bindingMethodProcessingStep,
173         CompilerOptions compilerOptions) {
174       return ImmutableList.of(
175           mapKeyProcessingStep,
176           injectProcessingStep,
177           assistedInjectProcessingStep,
178           assistedFactoryProcessingStep,
179           assistedProcessingStep,
180           monitoringModuleProcessingStep,
181           multibindingAnnotationsProcessingStep,
182           bindsInstanceProcessingStep,
183           moduleProcessingStep,
184           compilerOptions.headerCompilation()
185               ? componentHjarProcessingStep
186               : componentProcessingStep,
187           bindingMethodProcessingStep);
188     }
189   }
190 
191   @Override
postRound(RoundEnvironment roundEnv)192   protected void postRound(RoundEnvironment roundEnv) {
193     if (!roundEnv.processingOver()) {
194       try {
195         injectBindingRegistry.generateSourcesForRequiredBindings(
196             factoryGenerator, membersInjectorGenerator);
197       } catch (SourceFileGenerationException e) {
198         e.printMessageTo(processingEnv.getMessager());
199       }
200     }
201     clearableCaches.forEach(ClearableCache::clearCache);
202   }
203 }
204