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.asType; 20 import static com.google.common.collect.Sets.union; 21 import static dagger.internal.codegen.base.ComponentAnnotation.allComponentAnnotations; 22 import static dagger.internal.codegen.base.ComponentAnnotation.rootComponentAnnotations; 23 import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotations; 24 import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.allCreatorAnnotations; 25 import static java.util.Collections.disjoint; 26 27 import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep; 28 import com.google.auto.common.MoreElements; 29 import com.google.common.collect.ImmutableSet; 30 import com.google.errorprone.annotations.CanIgnoreReturnValue; 31 import dagger.internal.codegen.base.SourceFileGenerator; 32 import dagger.internal.codegen.binding.BindingGraph; 33 import dagger.internal.codegen.binding.BindingGraphFactory; 34 import dagger.internal.codegen.binding.ComponentDescriptor; 35 import dagger.internal.codegen.binding.ComponentDescriptorFactory; 36 import dagger.internal.codegen.validation.BindingGraphValidator; 37 import dagger.internal.codegen.validation.ComponentCreatorValidator; 38 import dagger.internal.codegen.validation.ComponentDescriptorValidator; 39 import dagger.internal.codegen.validation.ComponentValidator; 40 import dagger.internal.codegen.validation.TypeCheckingProcessingStep; 41 import dagger.internal.codegen.validation.ValidationReport; 42 import java.lang.annotation.Annotation; 43 import java.util.Set; 44 import javax.annotation.processing.Messager; 45 import javax.inject.Inject; 46 import javax.lang.model.element.Element; 47 import javax.lang.model.element.TypeElement; 48 49 /** 50 * A {@link ProcessingStep} that is responsible for dealing with a component or production component 51 * as part of the {@link ComponentProcessor}. 52 */ 53 final class ComponentProcessingStep extends TypeCheckingProcessingStep<TypeElement> { 54 private final Messager messager; 55 private final ComponentValidator componentValidator; 56 private final ComponentCreatorValidator creatorValidator; 57 private final ComponentDescriptorValidator componentDescriptorValidator; 58 private final ComponentDescriptorFactory componentDescriptorFactory; 59 private final BindingGraphFactory bindingGraphFactory; 60 private final SourceFileGenerator<BindingGraph> componentGenerator; 61 private final BindingGraphValidator bindingGraphValidator; 62 63 @Inject ComponentProcessingStep( Messager messager, ComponentValidator componentValidator, ComponentCreatorValidator creatorValidator, ComponentDescriptorValidator componentDescriptorValidator, ComponentDescriptorFactory componentDescriptorFactory, BindingGraphFactory bindingGraphFactory, SourceFileGenerator<BindingGraph> componentGenerator, BindingGraphValidator bindingGraphValidator)64 ComponentProcessingStep( 65 Messager messager, 66 ComponentValidator componentValidator, 67 ComponentCreatorValidator creatorValidator, 68 ComponentDescriptorValidator componentDescriptorValidator, 69 ComponentDescriptorFactory componentDescriptorFactory, 70 BindingGraphFactory bindingGraphFactory, 71 SourceFileGenerator<BindingGraph> componentGenerator, 72 BindingGraphValidator bindingGraphValidator) { 73 super(MoreElements::asType); 74 this.messager = messager; 75 this.componentValidator = componentValidator; 76 this.creatorValidator = creatorValidator; 77 this.componentDescriptorValidator = componentDescriptorValidator; 78 this.componentDescriptorFactory = componentDescriptorFactory; 79 this.bindingGraphFactory = bindingGraphFactory; 80 this.componentGenerator = componentGenerator; 81 this.bindingGraphValidator = bindingGraphValidator; 82 } 83 84 @Override annotations()85 public Set<Class<? extends Annotation>> annotations() { 86 return union(allComponentAnnotations(), allCreatorAnnotations()); 87 } 88 89 @Override process( TypeElement element, ImmutableSet<Class<? extends Annotation>> annotations)90 protected void process( 91 TypeElement element, ImmutableSet<Class<? extends Annotation>> annotations) { 92 if (!disjoint(annotations, rootComponentAnnotations())) { 93 processRootComponent(element); 94 } 95 if (!disjoint(annotations, subcomponentAnnotations())) { 96 processSubcomponent(element); 97 } 98 if (!disjoint(annotations, allCreatorAnnotations())) { 99 processCreator(element); 100 } 101 } 102 processRootComponent(TypeElement component)103 private void processRootComponent(TypeElement component) { 104 if (!isComponentValid(component)) { 105 return; 106 } 107 ComponentDescriptor componentDescriptor = 108 componentDescriptorFactory.rootComponentDescriptor(component); 109 if (!isValid(componentDescriptor)) { 110 return; 111 } 112 if (!validateFullBindingGraph(componentDescriptor)) { 113 return; 114 } 115 BindingGraph bindingGraph = bindingGraphFactory.create(componentDescriptor, false); 116 if (bindingGraphValidator.isValid(bindingGraph.topLevelBindingGraph())) { 117 generateComponent(bindingGraph); 118 } 119 } 120 processSubcomponent(TypeElement subcomponent)121 private void processSubcomponent(TypeElement subcomponent) { 122 if (!isComponentValid(subcomponent)) { 123 return; 124 } 125 ComponentDescriptor subcomponentDescriptor = 126 componentDescriptorFactory.subcomponentDescriptor(subcomponent); 127 // TODO(dpb): ComponentDescriptorValidator for subcomponents, as we do for root components. 128 validateFullBindingGraph(subcomponentDescriptor); 129 } 130 generateComponent(BindingGraph bindingGraph)131 private void generateComponent(BindingGraph bindingGraph) { 132 componentGenerator.generate(bindingGraph, messager); 133 } 134 processCreator(Element creator)135 private void processCreator(Element creator) { 136 creatorValidator.validate(MoreElements.asType(creator)).printMessagesTo(messager); 137 } 138 isComponentValid(Element component)139 private boolean isComponentValid(Element component) { 140 ValidationReport<?> report = componentValidator.validate(asType(component)); 141 report.printMessagesTo(messager); 142 return report.isClean(); 143 } 144 145 @CanIgnoreReturnValue validateFullBindingGraph(ComponentDescriptor componentDescriptor)146 private boolean validateFullBindingGraph(ComponentDescriptor componentDescriptor) { 147 TypeElement component = componentDescriptor.typeElement(); 148 if (!bindingGraphValidator.shouldDoFullBindingGraphValidation(component)) { 149 return true; 150 } 151 BindingGraph fullBindingGraph = bindingGraphFactory.create(componentDescriptor, true); 152 return bindingGraphValidator.isValid(fullBindingGraph.topLevelBindingGraph()); 153 } 154 isValid(ComponentDescriptor componentDescriptor)155 private boolean isValid(ComponentDescriptor componentDescriptor) { 156 ValidationReport<TypeElement> componentDescriptorReport = 157 componentDescriptorValidator.validate(componentDescriptor); 158 componentDescriptorReport.printMessagesTo(messager); 159 return componentDescriptorReport.isClean(); 160 } 161 } 162