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