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