• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.rootComponentAnnotations;
22 import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.rootComponentCreatorAnnotations;
23 import static java.util.Collections.disjoint;
24 
25 import com.google.auto.common.MoreElements;
26 import com.google.common.collect.ImmutableSet;
27 import dagger.internal.codegen.base.SourceFileGenerator;
28 import dagger.internal.codegen.binding.BindingGraph;
29 import dagger.internal.codegen.binding.ComponentDescriptor;
30 import dagger.internal.codegen.binding.ComponentDescriptorFactory;
31 import dagger.internal.codegen.validation.ComponentCreatorValidator;
32 import dagger.internal.codegen.validation.ComponentValidator;
33 import dagger.internal.codegen.validation.TypeCheckingProcessingStep;
34 import dagger.internal.codegen.validation.ValidationReport;
35 import java.lang.annotation.Annotation;
36 import java.util.Set;
37 import javax.annotation.processing.Messager;
38 import javax.inject.Inject;
39 import javax.lang.model.element.TypeElement;
40 
41 /**
42  * A processing step that emits the API of a generated component, without any actual implementation.
43  *
44  * <p>When compiling a header jar (hjar), Bazel needs to run annotation processors that generate
45  * API, like Dagger, to see what code they might output. Full {@link BindingGraph} analysis is
46  * costly and unnecessary from the perspective of the header compiler; it's sole goal is to pass
47  * along a slimmed down version of what will be the jar for a particular compilation, whether or not
48  * that compilation succeeds. If it does not, the compilation pipeline will fail, even if header
49  * compilation succeeded.
50  *
51  * <p>The components emitted by this processing step include all of the API elements exposed by the
52  * normal step. Method bodies are omitted as Turbine ignores them entirely.
53  */
54 final class ComponentHjarProcessingStep extends TypeCheckingProcessingStep<TypeElement> {
55   private final Messager messager;
56   private final ComponentValidator componentValidator;
57   private final ComponentCreatorValidator creatorValidator;
58   private final ComponentDescriptorFactory componentDescriptorFactory;
59   private final SourceFileGenerator<ComponentDescriptor> componentGenerator;
60 
61   @Inject
ComponentHjarProcessingStep( Messager messager, ComponentValidator componentValidator, ComponentCreatorValidator creatorValidator, ComponentDescriptorFactory componentDescriptorFactory, SourceFileGenerator<ComponentDescriptor> componentGenerator)62   ComponentHjarProcessingStep(
63       Messager messager,
64       ComponentValidator componentValidator,
65       ComponentCreatorValidator creatorValidator,
66       ComponentDescriptorFactory componentDescriptorFactory,
67       SourceFileGenerator<ComponentDescriptor> componentGenerator) {
68     super(MoreElements::asType);
69     this.messager = messager;
70     this.componentValidator = componentValidator;
71     this.creatorValidator = creatorValidator;
72     this.componentDescriptorFactory = componentDescriptorFactory;
73     this.componentGenerator = componentGenerator;
74   }
75 
76   @Override
annotations()77   public Set<Class<? extends Annotation>> annotations() {
78     return union(rootComponentAnnotations(), rootComponentCreatorAnnotations());
79   }
80 
81   // TODO(ronshapiro): Validation might not even be necessary. We should measure it and figure out
82   // if it's worth seeing if removing it will still work. We could potentially add a new catch
83   // clause for any exception that's not TypeNotPresentException and ignore the component entirely
84   // in that case.
85   @Override
process( TypeElement element, ImmutableSet<Class<? extends Annotation>> annotations)86   protected void process(
87       TypeElement element, ImmutableSet<Class<? extends Annotation>> annotations) {
88     if (!disjoint(annotations, rootComponentAnnotations())) {
89       processRootComponent(element);
90     }
91     if (!disjoint(annotations, rootComponentCreatorAnnotations())) {
92       processRootCreator(element);
93     }
94   }
95 
processRootComponent(TypeElement element)96   private void processRootComponent(TypeElement element) {
97     ValidationReport<TypeElement> validationReport = componentValidator.validate(element);
98     validationReport.printMessagesTo(messager);
99     if (validationReport.isClean()) {
100       componentGenerator.generate(
101           componentDescriptorFactory.rootComponentDescriptor(element), messager);
102     }
103   }
104 
processRootCreator(TypeElement creator)105   private void processRootCreator(TypeElement creator) {
106     creatorValidator.validate(asType(creator)).printMessagesTo(messager);
107   }
108 }
109