• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.ProcessingStep;
19 import com.google.auto.common.MoreElements;
20 import com.google.common.collect.ImmutableSet;
21 import com.google.common.collect.SetMultimap;
22 import java.lang.annotation.Annotation;
23 import javax.annotation.processing.Messager;
24 import javax.lang.model.element.Element;
25 import javax.lang.model.element.TypeElement;
26 
27 /**
28  * A {@link ProcessingStep} that is responsible for dealing with a component or production component
29  * as part of the {@link ComponentProcessor}.
30  */
31 abstract class AbstractComponentProcessingStep implements ProcessingStep {
32 
33   private final Class<? extends Annotation> componentAnnotation;
34   private final Messager messager;
35   private final ComponentHierarchyValidator componentHierarchyValidator;
36   private final BindingGraphValidator bindingGraphValidator;
37   private final ComponentDescriptor.Factory componentDescriptorFactory;
38   private final BindingGraph.Factory bindingGraphFactory;
39   private final ComponentGenerator componentGenerator;
40 
AbstractComponentProcessingStep( Class<? extends Annotation> componentAnnotation, Messager messager, ComponentHierarchyValidator componentHierarchyValidator, BindingGraphValidator bindingGraphValidator, ComponentDescriptor.Factory componentDescriptorFactory, BindingGraph.Factory bindingGraphFactory, ComponentGenerator componentGenerator)41   AbstractComponentProcessingStep(
42       Class<? extends Annotation> componentAnnotation,
43       Messager messager,
44       ComponentHierarchyValidator componentHierarchyValidator,
45       BindingGraphValidator bindingGraphValidator,
46       ComponentDescriptor.Factory componentDescriptorFactory,
47       BindingGraph.Factory bindingGraphFactory,
48       ComponentGenerator componentGenerator) {
49     this.componentAnnotation = componentAnnotation;
50     this.messager = messager;
51     this.componentHierarchyValidator = componentHierarchyValidator;
52     this.bindingGraphValidator = bindingGraphValidator;
53     this.componentDescriptorFactory = componentDescriptorFactory;
54     this.bindingGraphFactory = bindingGraphFactory;
55     this.componentGenerator = componentGenerator;
56   }
57 
58   @Override
process( SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation)59   public final ImmutableSet<Element> process(
60       SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
61     ImmutableSet.Builder<Element> rejectedElements = ImmutableSet.builder();
62     ComponentElementValidator componentElementValidator =
63         componentElementValidator(elementsByAnnotation);
64     for (Element element : elementsByAnnotation.get(componentAnnotation)) {
65       TypeElement componentTypeElement = MoreElements.asType(element);
66       try {
67         if (componentElementValidator.validateComponent(componentTypeElement, messager)) {
68           ComponentDescriptor componentDescriptor =
69               componentDescriptorFactory.forComponent(componentTypeElement);
70           ValidationReport<TypeElement> hierarchyReport =
71               componentHierarchyValidator.validate(componentDescriptor);
72           hierarchyReport.printMessagesTo(messager);
73           if (hierarchyReport.isClean()) {
74             BindingGraph bindingGraph = bindingGraphFactory.create(componentDescriptor);
75             ValidationReport<TypeElement> graphReport =
76                 bindingGraphValidator.validate(bindingGraph);
77             graphReport.printMessagesTo(messager);
78             if (graphReport.isClean()) {
79               generateComponent(bindingGraph);
80             }
81           }
82         }
83       } catch (TypeNotPresentException e) {
84         rejectedElements.add(componentTypeElement);
85       }
86     }
87     return rejectedElements.build();
88   }
89 
generateComponent(BindingGraph bindingGraph)90   private void generateComponent(BindingGraph bindingGraph) {
91     try {
92       componentGenerator.generate(bindingGraph);
93     } catch (SourceFileGenerationException e) {
94       e.printMessageTo(messager);
95     }
96   }
97 
98   /**
99    * Returns an object that can validate a type element annotated with the component type.
100    */
componentElementValidator( SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation)101   protected abstract ComponentElementValidator componentElementValidator(
102       SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation);
103 
104   /**
105    * Validates a component type element.
106    */
107   protected static abstract class ComponentElementValidator {
108     /**
109      * Validates a component type element. Prints any messages about the element to
110      * {@code messager}.
111      *
112      * @throws TypeNotPresentException if any type required to validate the component cannot be
113      *     found
114      */
validateComponent(TypeElement componentTypeElement, Messager messager)115     abstract boolean validateComponent(TypeElement componentTypeElement, Messager messager);
116   }
117 }
118