1 /* 2 * Copyright (C) 2014 Google, Inc. 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 package dagger.internal.codegen; 17 18 import com.google.auto.common.BasicAnnotationProcessor; 19 import com.google.auto.service.AutoService; 20 import com.google.common.base.Ascii; 21 import com.google.common.collect.ImmutableList; 22 import com.google.common.collect.ImmutableSet; 23 import dagger.Module; 24 import dagger.Provides; 25 import dagger.producers.ProducerModule; 26 import dagger.producers.Produces; 27 import java.lang.annotation.Annotation; 28 import java.util.EnumSet; 29 import java.util.Map; 30 import java.util.Set; 31 import javax.annotation.processing.Filer; 32 import javax.annotation.processing.Messager; 33 import javax.annotation.processing.ProcessingEnvironment; 34 import javax.annotation.processing.Processor; 35 import javax.lang.model.SourceVersion; 36 import javax.lang.model.util.Elements; 37 import javax.lang.model.util.Types; 38 import javax.tools.Diagnostic; 39 40 import static javax.tools.Diagnostic.Kind.ERROR; 41 42 /** 43 * The annotation processor responsible for generating the classes that drive the Dagger 2.0 44 * implementation. 45 * 46 * TODO(gak): give this some better documentation 47 * 48 * @author Gregory Kick 49 * @since 2.0 50 */ 51 @AutoService(Processor.class) 52 public final class ComponentProcessor extends BasicAnnotationProcessor { 53 private InjectBindingRegistry injectBindingRegistry; 54 private FactoryGenerator factoryGenerator; 55 private MembersInjectorGenerator membersInjectorGenerator; 56 57 @Override getSupportedSourceVersion()58 public SourceVersion getSupportedSourceVersion() { 59 return SourceVersion.latestSupported(); 60 } 61 62 @Override getSupportedOptions()63 public Set<String> getSupportedOptions() { 64 return ImmutableSet.of( 65 DISABLE_INTER_COMPONENT_SCOPE_VALIDATION_KEY, 66 NULLABLE_VALIDATION_KEY, 67 PRIVATE_MEMBER_VALIDATION_TYPE_KEY, 68 STATIC_MEMBER_VALIDATION_TYPE_KEY 69 ); 70 } 71 72 @Override initSteps()73 protected Iterable<ProcessingStep> initSteps() { 74 Messager messager = processingEnv.getMessager(); 75 Types types = processingEnv.getTypeUtils(); 76 Elements elements = processingEnv.getElementUtils(); 77 Filer filer = processingEnv.getFiler(); 78 79 Diagnostic.Kind nullableDiagnosticType = 80 nullableValidationType(processingEnv).diagnosticKind().get(); 81 82 MethodSignatureFormatter methodSignatureFormatter = new MethodSignatureFormatter(types); 83 ContributionBindingFormatter contributionBindingFormatter = 84 new ContributionBindingFormatter(methodSignatureFormatter); 85 DependencyRequestFormatter dependencyRequestFormatter = new DependencyRequestFormatter(types); 86 KeyFormatter keyFormatter = new KeyFormatter(); 87 88 InjectConstructorValidator injectConstructorValidator = new InjectConstructorValidator(); 89 InjectFieldValidator injectFieldValidator = new InjectFieldValidator( 90 privateMemberValidationType(processingEnv).diagnosticKind().get(), 91 staticMemberValidationType(processingEnv).diagnosticKind().get()); 92 InjectMethodValidator injectMethodValidator = new InjectMethodValidator( 93 privateMemberValidationType(processingEnv).diagnosticKind().get(), 94 staticMemberValidationType(processingEnv).diagnosticKind().get()); 95 ModuleValidator moduleValidator = 96 new ModuleValidator( 97 types, 98 elements, 99 methodSignatureFormatter, 100 Module.class, 101 ImmutableList.<Class<? extends Annotation>>of(Module.class), 102 Provides.class); 103 ProvidesMethodValidator providesMethodValidator = new ProvidesMethodValidator(elements); 104 BuilderValidator componentBuilderValidator = 105 new BuilderValidator(elements, types, ComponentDescriptor.Kind.COMPONENT); 106 BuilderValidator subcomponentBuilderValidator = 107 new BuilderValidator(elements, types, ComponentDescriptor.Kind.SUBCOMPONENT); 108 ComponentValidator subcomponentValidator = ComponentValidator.createForSubcomponent(elements, 109 types, moduleValidator, subcomponentBuilderValidator); 110 ComponentValidator componentValidator = ComponentValidator.createForComponent(elements, types, 111 moduleValidator, subcomponentValidator, subcomponentBuilderValidator); 112 MapKeyValidator mapKeyValidator = new MapKeyValidator(); 113 ModuleValidator producerModuleValidator = 114 new ModuleValidator( 115 types, 116 elements, 117 methodSignatureFormatter, 118 ProducerModule.class, 119 ImmutableList.of(Module.class, ProducerModule.class), 120 Produces.class); 121 ProducesMethodValidator producesMethodValidator = new ProducesMethodValidator(elements); 122 ProductionComponentValidator productionComponentValidator = new ProductionComponentValidator(); 123 BuilderValidator productionComponentBuilderValidator = 124 new BuilderValidator(elements, types, ComponentDescriptor.Kind.PRODUCTION_COMPONENT); 125 126 Key.Factory keyFactory = new Key.Factory(types, elements); 127 128 this.factoryGenerator = 129 new FactoryGenerator(filer, DependencyRequestMapper.FOR_PROVIDER, nullableDiagnosticType); 130 this.membersInjectorGenerator = 131 new MembersInjectorGenerator(filer, DependencyRequestMapper.FOR_PROVIDER); 132 ComponentGenerator componentGenerator = 133 new ComponentGenerator(filer, elements, types, keyFactory, nullableDiagnosticType); 134 ProducerFactoryGenerator producerFactoryGenerator = 135 new ProducerFactoryGenerator(filer, DependencyRequestMapper.FOR_PRODUCER); 136 MonitoringModuleGenerator monitoringModuleGenerator = new MonitoringModuleGenerator(filer); 137 138 DependencyRequest.Factory dependencyRequestFactory = 139 new DependencyRequest.Factory(elements, keyFactory); 140 ProvisionBinding.Factory provisionBindingFactory = 141 new ProvisionBinding.Factory(elements, types, keyFactory, dependencyRequestFactory); 142 ProductionBinding.Factory productionBindingFactory = 143 new ProductionBinding.Factory(types, keyFactory, dependencyRequestFactory); 144 145 MembersInjectionBinding.Factory membersInjectionBindingFactory = 146 new MembersInjectionBinding.Factory(elements, types, keyFactory, dependencyRequestFactory); 147 148 this.injectBindingRegistry = new InjectBindingRegistry( 149 elements, types, messager, provisionBindingFactory, membersInjectionBindingFactory); 150 151 ModuleDescriptor.Factory moduleDescriptorFactory = new ModuleDescriptor.Factory( 152 elements, provisionBindingFactory, productionBindingFactory); 153 154 ComponentDescriptor.Factory componentDescriptorFactory = new ComponentDescriptor.Factory( 155 elements, types, dependencyRequestFactory, moduleDescriptorFactory); 156 157 BindingGraph.Factory bindingGraphFactory = 158 new BindingGraph.Factory( 159 elements, 160 injectBindingRegistry, 161 keyFactory, 162 provisionBindingFactory, 163 productionBindingFactory); 164 165 MapKeyGenerator mapKeyGenerator = new MapKeyGenerator(filer); 166 ComponentHierarchyValidator componentHierarchyValidator = new ComponentHierarchyValidator(); 167 BindingGraphValidator bindingGraphValidator = 168 new BindingGraphValidator( 169 types, 170 injectBindingRegistry, 171 scopeValidationType(processingEnv), 172 nullableDiagnosticType, 173 contributionBindingFormatter, 174 methodSignatureFormatter, 175 dependencyRequestFormatter, 176 keyFormatter); 177 178 return ImmutableList.<ProcessingStep>of( 179 new MapKeyProcessingStep(messager, types, mapKeyValidator, mapKeyGenerator), 180 new InjectProcessingStep( 181 messager, 182 injectConstructorValidator, 183 injectFieldValidator, 184 injectMethodValidator, 185 provisionBindingFactory, 186 membersInjectionBindingFactory, 187 injectBindingRegistry), 188 new MonitoringModuleProcessingStep(messager, monitoringModuleGenerator), 189 new ModuleProcessingStep( 190 messager, 191 moduleValidator, 192 providesMethodValidator, 193 provisionBindingFactory, 194 factoryGenerator), 195 new ComponentProcessingStep( 196 messager, 197 componentValidator, 198 subcomponentValidator, 199 componentBuilderValidator, 200 subcomponentBuilderValidator, 201 componentHierarchyValidator, 202 bindingGraphValidator, 203 componentDescriptorFactory, 204 bindingGraphFactory, 205 componentGenerator), 206 new ProducerModuleProcessingStep( 207 messager, 208 producerModuleValidator, 209 producesMethodValidator, 210 productionBindingFactory, 211 producerFactoryGenerator), 212 new ProductionComponentProcessingStep( 213 messager, 214 productionComponentValidator, 215 productionComponentBuilderValidator, 216 componentHierarchyValidator, 217 bindingGraphValidator, 218 componentDescriptorFactory, 219 bindingGraphFactory, 220 componentGenerator)); 221 } 222 223 @Override postProcess()224 protected void postProcess() { 225 try { 226 injectBindingRegistry.generateSourcesForRequiredBindings( 227 factoryGenerator, membersInjectorGenerator); 228 } catch (SourceFileGenerationException e) { 229 e.printMessageTo(processingEnv.getMessager()); 230 } 231 } 232 233 private static final String DISABLE_INTER_COMPONENT_SCOPE_VALIDATION_KEY = 234 "dagger.disableInterComponentScopeValidation"; 235 236 private static final String NULLABLE_VALIDATION_KEY = "dagger.nullableValidation"; 237 238 private static final String PRIVATE_MEMBER_VALIDATION_TYPE_KEY = 239 "dagger.privateMemberValidation"; 240 241 private static final String STATIC_MEMBER_VALIDATION_TYPE_KEY = 242 "dagger.staticMemberValidation"; 243 scopeValidationType(ProcessingEnvironment processingEnv)244 private static ValidationType scopeValidationType(ProcessingEnvironment processingEnv) { 245 return valueOf(processingEnv, 246 DISABLE_INTER_COMPONENT_SCOPE_VALIDATION_KEY, 247 ValidationType.ERROR, 248 EnumSet.allOf(ValidationType.class)); 249 } 250 nullableValidationType(ProcessingEnvironment processingEnv)251 private static ValidationType nullableValidationType(ProcessingEnvironment processingEnv) { 252 return valueOf(processingEnv, 253 NULLABLE_VALIDATION_KEY, 254 ValidationType.ERROR, 255 EnumSet.of(ValidationType.ERROR, ValidationType.WARNING)); 256 } 257 privateMemberValidationType(ProcessingEnvironment processingEnv)258 private static ValidationType privateMemberValidationType(ProcessingEnvironment processingEnv) { 259 return valueOf(processingEnv, 260 PRIVATE_MEMBER_VALIDATION_TYPE_KEY, 261 ValidationType.ERROR, 262 EnumSet.of(ValidationType.ERROR, ValidationType.WARNING)); 263 } 264 staticMemberValidationType(ProcessingEnvironment processingEnv)265 private static ValidationType staticMemberValidationType(ProcessingEnvironment processingEnv) { 266 return valueOf(processingEnv, 267 STATIC_MEMBER_VALIDATION_TYPE_KEY, 268 ValidationType.ERROR, 269 EnumSet.of(ValidationType.ERROR, ValidationType.WARNING)); 270 } 271 valueOf(ProcessingEnvironment processingEnv, String key, T defaultValue, Set<T> validValues)272 private static <T extends Enum<T>> T valueOf(ProcessingEnvironment processingEnv, String key, 273 T defaultValue, Set<T> validValues) { 274 Map<String, String> options = processingEnv.getOptions(); 275 if (options.containsKey(key)) { 276 try { 277 T type = Enum.valueOf( 278 defaultValue.getDeclaringClass(), 279 Ascii.toUpperCase(options.get(key))); 280 if (!validValues.contains(type)) { 281 throw new IllegalArgumentException(); // let handler below print out good msg. 282 } 283 return type; 284 } catch (IllegalArgumentException e) { 285 processingEnv.getMessager().printMessage(ERROR, "Processor option -A" 286 + key + " may only have the values " + validValues 287 + " (case insensitive), found: " + options.get(key)); 288 } 289 } 290 return defaultValue; 291 } 292 } 293