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 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 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 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 */ 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 */ 115 abstract boolean validateComponent(TypeElement componentTypeElement, Messager messager); 116 } 117 } 118