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.DYNAMIC; 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.Iterables; 27 import com.google.errorprone.annotations.CanIgnoreReturnValue; 28 import com.google.errorprone.annotations.CheckReturnValue; 29 import dagger.BindsInstance; 30 import dagger.Component; 31 import dagger.Module; 32 import dagger.Provides; 33 import dagger.internal.codegen.SpiModule.TestingPlugins; 34 import dagger.spi.BindingGraphPlugin; 35 import java.util.Arrays; 36 import java.util.Optional; 37 import java.util.Set; 38 import javax.annotation.processing.Processor; 39 import javax.annotation.processing.RoundEnvironment; 40 import javax.inject.Inject; 41 import javax.inject.Singleton; 42 import javax.lang.model.SourceVersion; 43 import net.ltgt.gradle.incap.IncrementalAnnotationProcessor; 44 45 /** 46 * The annotation processor responsible for generating the classes that drive the Dagger 2.0 47 * implementation. 48 * 49 * <p>TODO(gak): give this some better documentation 50 */ 51 @IncrementalAnnotationProcessor(DYNAMIC) 52 @AutoService(Processor.class) 53 public class ComponentProcessor extends BasicAnnotationProcessor { 54 private final Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins; 55 56 @Inject InjectBindingRegistry injectBindingRegistry; 57 @Inject SourceFileGenerator<ProvisionBinding> factoryGenerator; 58 @Inject SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator; 59 @Inject ImmutableList<ProcessingStep> processingSteps; 60 @Inject BindingGraphPlugins bindingGraphPlugins; 61 @Inject CompilerOptions compilerOptions; 62 @Inject DaggerStatisticsCollector statisticsCollector; 63 @Inject Set<ClearableCache> clearableCaches; 64 ComponentProcessor()65 public ComponentProcessor() { 66 this.testingPlugins = Optional.empty(); 67 } 68 ComponentProcessor(Iterable<BindingGraphPlugin> testingPlugins)69 private ComponentProcessor(Iterable<BindingGraphPlugin> testingPlugins) { 70 this.testingPlugins = Optional.of(ImmutableSet.copyOf(testingPlugins)); 71 } 72 73 /** 74 * Creates a component processor that uses given {@link BindingGraphPlugin}s instead of loading 75 * them from a {@link java.util.ServiceLoader}. 76 */ 77 @VisibleForTesting forTesting(BindingGraphPlugin... testingPlugins)78 public static ComponentProcessor forTesting(BindingGraphPlugin... testingPlugins) { 79 return forTesting(Arrays.asList(testingPlugins)); 80 } 81 82 /** 83 * Creates a component processor that uses given {@link BindingGraphPlugin}s instead of loading 84 * them from a {@link java.util.ServiceLoader}. 85 */ 86 @VisibleForTesting forTesting(Iterable<BindingGraphPlugin> testingPlugins)87 public static ComponentProcessor forTesting(Iterable<BindingGraphPlugin> testingPlugins) { 88 return new ComponentProcessor(testingPlugins); 89 } 90 91 @Override getSupportedSourceVersion()92 public SourceVersion getSupportedSourceVersion() { 93 return SourceVersion.latestSupported(); 94 } 95 96 @Override getSupportedOptions()97 public Set<String> getSupportedOptions() { 98 ImmutableSet.Builder<String> options = ImmutableSet.builder(); 99 options.addAll(ProcessingEnvironmentCompilerOptions.supportedOptions()); 100 options.addAll(bindingGraphPlugins.allSupportedOptions()); 101 if (compilerOptions.useGradleIncrementalProcessing()) { 102 options.add("org.gradle.annotation.processing.isolating"); 103 } 104 return options.build(); 105 } 106 107 @Override initSteps()108 protected Iterable<? extends ProcessingStep> initSteps() { 109 ProcessorComponent.builder() 110 .processingEnvironmentModule(new ProcessingEnvironmentModule(processingEnv)) 111 .testingPlugins(testingPlugins) 112 .build() 113 .inject(this); 114 115 statisticsCollector.processingStarted(); 116 bindingGraphPlugins.initializePlugins(); 117 return Iterables.transform( 118 processingSteps, 119 step -> new DaggerStatisticsCollectingProcessingStep(step, statisticsCollector)); 120 } 121 122 @Singleton 123 @Component( 124 modules = { 125 BindingGraphValidationModule.class, 126 BindingMethodValidatorsModule.class, 127 InjectBindingRegistryModule.class, 128 ProcessingEnvironmentModule.class, 129 ProcessingRoundCacheModule.class, 130 ProcessingStepsModule.class, 131 SourceFileGeneratorsModule.class, 132 SpiModule.class, 133 SystemComponentsModule.class, 134 TopLevelImplementationComponent.InstallationModule.class, 135 }) 136 interface ProcessorComponent { inject(ComponentProcessor processor)137 void inject(ComponentProcessor processor); 138 builder()139 static Builder builder() { 140 return DaggerComponentProcessor_ProcessorComponent.builder(); 141 } 142 143 @CanIgnoreReturnValue 144 @Component.Builder 145 interface Builder { processingEnvironmentModule(ProcessingEnvironmentModule module)146 Builder processingEnvironmentModule(ProcessingEnvironmentModule module); 147 148 @BindsInstance testingPlugins( @estingPlugins Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins)149 Builder testingPlugins( 150 @TestingPlugins Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins); 151 build()152 @CheckReturnValue ProcessorComponent build(); 153 } 154 } 155 156 @Module 157 interface ProcessingStepsModule { 158 @Provides processingSteps( MapKeyProcessingStep mapKeyProcessingStep, InjectProcessingStep injectProcessingStep, MonitoringModuleProcessingStep monitoringModuleProcessingStep, MultibindingAnnotationsProcessingStep multibindingAnnotationsProcessingStep, BindsInstanceProcessingStep bindsInstanceProcessingStep, ModuleProcessingStep moduleProcessingStep, ComponentProcessingStep componentProcessingStep, ComponentHjarProcessingStep componentHjarProcessingStep, BindingMethodProcessingStep bindingMethodProcessingStep, CompilerOptions compilerOptions)159 static ImmutableList<ProcessingStep> processingSteps( 160 MapKeyProcessingStep mapKeyProcessingStep, 161 InjectProcessingStep injectProcessingStep, 162 MonitoringModuleProcessingStep monitoringModuleProcessingStep, 163 MultibindingAnnotationsProcessingStep multibindingAnnotationsProcessingStep, 164 BindsInstanceProcessingStep bindsInstanceProcessingStep, 165 ModuleProcessingStep moduleProcessingStep, 166 ComponentProcessingStep componentProcessingStep, 167 ComponentHjarProcessingStep componentHjarProcessingStep, 168 BindingMethodProcessingStep bindingMethodProcessingStep, 169 CompilerOptions compilerOptions) { 170 return ImmutableList.of( 171 mapKeyProcessingStep, 172 injectProcessingStep, 173 monitoringModuleProcessingStep, 174 multibindingAnnotationsProcessingStep, 175 bindsInstanceProcessingStep, 176 moduleProcessingStep, 177 compilerOptions.headerCompilation() 178 // Ahead Of Time subcomponents use the regular hjar filtering in 179 // HjarSourceFileGenerator since they must retain protected implementation methods 180 // between subcomponents 181 && !compilerOptions.aheadOfTimeSubcomponents() 182 ? componentHjarProcessingStep 183 : componentProcessingStep, 184 bindingMethodProcessingStep); 185 } 186 } 187 188 @Override postRound(RoundEnvironment roundEnv)189 protected void postRound(RoundEnvironment roundEnv) { 190 statisticsCollector.roundFinished(); 191 if (roundEnv.processingOver()) { 192 statisticsCollector.processingStopped(); 193 } else { 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