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 com.google.auto.common.MoreElements.isAnnotationPresent; 20 import static javax.lang.model.util.ElementFilter.methodsIn; 21 import static javax.lang.model.util.ElementFilter.typesIn; 22 23 import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep; 24 import com.google.auto.common.MoreElements; 25 import com.google.common.collect.ImmutableSet; 26 import com.google.common.collect.SetMultimap; 27 import com.google.common.collect.Sets; 28 import dagger.Binds; 29 import dagger.Module; 30 import dagger.Provides; 31 import dagger.internal.codegen.DelegateDeclaration.Factory; 32 import dagger.producers.ProducerModule; 33 import dagger.producers.Produces; 34 import java.lang.annotation.Annotation; 35 import java.util.List; 36 import java.util.Set; 37 import javax.annotation.processing.Messager; 38 import javax.inject.Inject; 39 import javax.lang.model.element.Element; 40 import javax.lang.model.element.ExecutableElement; 41 import javax.lang.model.element.TypeElement; 42 43 /** 44 * A {@link ProcessingStep} that validates module classes and generates factories for binding 45 * methods. 46 */ 47 final class ModuleProcessingStep extends TypeCheckingProcessingStep<TypeElement> { 48 private final Messager messager; 49 private final ModuleValidator moduleValidator; 50 private final BindingFactory bindingFactory; 51 private final SourceFileGenerator<ProvisionBinding> factoryGenerator; 52 private final SourceFileGenerator<ProductionBinding> producerFactoryGenerator; 53 private final SourceFileGenerator<TypeElement> moduleConstructorProxyGenerator; 54 private final InaccessibleMapKeyProxyGenerator inaccessibleMapKeyProxyGenerator; 55 private final DelegateDeclaration.Factory delegateDeclarationFactory; 56 private final Set<TypeElement> processedModuleElements = Sets.newLinkedHashSet(); 57 58 @Inject ModuleProcessingStep( Messager messager, ModuleValidator moduleValidator, BindingFactory bindingFactory, SourceFileGenerator<ProvisionBinding> factoryGenerator, SourceFileGenerator<ProductionBinding> producerFactoryGenerator, @ModuleGenerator SourceFileGenerator<TypeElement> moduleConstructorProxyGenerator, InaccessibleMapKeyProxyGenerator inaccessibleMapKeyProxyGenerator, Factory delegateDeclarationFactory)59 ModuleProcessingStep( 60 Messager messager, 61 ModuleValidator moduleValidator, 62 BindingFactory bindingFactory, 63 SourceFileGenerator<ProvisionBinding> factoryGenerator, 64 SourceFileGenerator<ProductionBinding> producerFactoryGenerator, 65 @ModuleGenerator SourceFileGenerator<TypeElement> moduleConstructorProxyGenerator, 66 InaccessibleMapKeyProxyGenerator inaccessibleMapKeyProxyGenerator, 67 Factory delegateDeclarationFactory) { 68 super(MoreElements::asType); 69 this.messager = messager; 70 this.moduleValidator = moduleValidator; 71 this.bindingFactory = bindingFactory; 72 this.factoryGenerator = factoryGenerator; 73 this.producerFactoryGenerator = producerFactoryGenerator; 74 this.moduleConstructorProxyGenerator = moduleConstructorProxyGenerator; 75 this.inaccessibleMapKeyProxyGenerator = inaccessibleMapKeyProxyGenerator; 76 this.delegateDeclarationFactory = delegateDeclarationFactory; 77 } 78 79 @Override annotations()80 public Set<? extends Class<? extends Annotation>> annotations() { 81 return ImmutableSet.of(Module.class, ProducerModule.class); 82 } 83 84 @Override process( SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation)85 public ImmutableSet<Element> process( 86 SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) { 87 List<TypeElement> modules = typesIn(elementsByAnnotation.values()); 88 moduleValidator.addKnownModules(modules); 89 return super.process(elementsByAnnotation); 90 } 91 92 @Override process( TypeElement module, ImmutableSet<Class<? extends Annotation>> annotations)93 protected void process( 94 TypeElement module, ImmutableSet<Class<? extends Annotation>> annotations) { 95 if (processedModuleElements.contains(module)) { 96 return; 97 } 98 ValidationReport<TypeElement> report = moduleValidator.validate(module); 99 report.printMessagesTo(messager); 100 if (report.isClean()) { 101 for (ExecutableElement method : methodsIn(module.getEnclosedElements())) { 102 if (isAnnotationPresent(method, Provides.class)) { 103 generate(factoryGenerator, bindingFactory.providesMethodBinding(method, module)); 104 } else if (isAnnotationPresent(method, Produces.class)) { 105 generate(producerFactoryGenerator, bindingFactory.producesMethodBinding(method, module)); 106 } else if (isAnnotationPresent(method, Binds.class)) { 107 inaccessibleMapKeyProxyGenerator.generate(bindsMethodBinding(module, method), messager); 108 } 109 } 110 moduleConstructorProxyGenerator.generate(module, messager); 111 } 112 processedModuleElements.add(module); 113 } 114 generate( SourceFileGenerator<B> generator, B binding)115 private <B extends ContributionBinding> void generate( 116 SourceFileGenerator<B> generator, B binding) { 117 generator.generate(binding, messager); 118 inaccessibleMapKeyProxyGenerator.generate(binding, messager); 119 } 120 bindsMethodBinding(TypeElement module, ExecutableElement method)121 private ContributionBinding bindsMethodBinding(TypeElement module, ExecutableElement method) { 122 return bindingFactory.unresolvedDelegateBinding( 123 delegateDeclarationFactory.create(method, module)); 124 } 125 } 126