• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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