1 /* 2 * Copyright (C) 2019 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.hilt.processor.internal.definecomponent; 18 19 20 import androidx.room.compiler.processing.XElement; 21 import androidx.room.compiler.processing.XProcessingEnv; 22 import androidx.room.compiler.processing.XRoundEnv; 23 import androidx.room.compiler.processing.XTypeElement; 24 import com.google.common.collect.ImmutableSet; 25 import com.squareup.javapoet.AnnotationSpec; 26 import com.squareup.javapoet.ClassName; 27 import dagger.hilt.processor.internal.BaseProcessingStep; 28 import dagger.hilt.processor.internal.ClassNames; 29 import dagger.hilt.processor.internal.Processors; 30 import dagger.hilt.processor.internal.definecomponent.DefineComponentBuilderMetadatas.DefineComponentBuilderMetadata; 31 import dagger.hilt.processor.internal.definecomponent.DefineComponentMetadatas.DefineComponentMetadata; 32 33 /** 34 * A processor for {@link dagger.hilt.DefineComponent} and {@link 35 * dagger.hilt.DefineComponent.Builder}. 36 */ 37 public final class DefineComponentProcessingStep extends BaseProcessingStep { 38 // Note: these caches should be cleared between rounds. 39 private DefineComponentMetadatas componentMetadatas; 40 private DefineComponentBuilderMetadatas componentBuilderMetadatas; 41 DefineComponentProcessingStep(XProcessingEnv env)42 public DefineComponentProcessingStep(XProcessingEnv env) { 43 super(env); 44 } 45 46 @Override preProcess(XProcessingEnv env, XRoundEnv round)47 public void preProcess(XProcessingEnv env, XRoundEnv round) { 48 componentMetadatas = DefineComponentMetadatas.create(); 49 componentBuilderMetadatas = DefineComponentBuilderMetadatas.create(componentMetadatas); 50 } 51 52 @Override postProcess(XProcessingEnv env, XRoundEnv round)53 public void postProcess(XProcessingEnv env, XRoundEnv round) { 54 componentMetadatas = null; 55 componentBuilderMetadatas = null; 56 } 57 58 @Override annotationClassNames()59 protected ImmutableSet<ClassName> annotationClassNames() { 60 return ImmutableSet.of(ClassNames.DEFINE_COMPONENT, ClassNames.DEFINE_COMPONENT_BUILDER); 61 } 62 63 @Override processEach(ClassName annotation, XElement element)64 public void processEach(ClassName annotation, XElement element) { 65 if (annotation.equals(ClassNames.DEFINE_COMPONENT)) { 66 // TODO(bcorso): For cycles we currently process each element in the cycle. We should skip 67 // processing of subsequent elements in a cycle, but this requires ensuring that the first 68 // element processed is always the same so that our failure tests are stable. 69 DefineComponentMetadata metadata = componentMetadatas.get(element); 70 generateFile("component", metadata.component()); 71 } else if (annotation.equals(ClassNames.DEFINE_COMPONENT_BUILDER)) { 72 DefineComponentBuilderMetadata metadata = componentBuilderMetadatas.get(element); 73 generateFile("builder", metadata.builder()); 74 } else { 75 throw new AssertionError("Unhandled annotation type: " + annotation.canonicalName()); 76 } 77 } 78 generateFile(String member, XTypeElement typeElement)79 private void generateFile(String member, XTypeElement typeElement) { 80 Processors.generateAggregatingClass( 81 ClassNames.DEFINE_COMPONENT_CLASSES_PACKAGE, 82 AnnotationSpec.builder(ClassNames.DEFINE_COMPONENT_CLASSES) 83 .addMember(member, "$S", typeElement.getQualifiedName()) 84 .build(), 85 typeElement, 86 getClass()); 87 } 88 } 89