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.generatesrootinput; 18 19 import static com.google.common.base.Suppliers.memoize; 20 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet; 21 22 import androidx.room.compiler.processing.XAnnotation; 23 import androidx.room.compiler.processing.XElement; 24 import androidx.room.compiler.processing.XProcessingEnv; 25 import androidx.room.compiler.processing.XRoundEnv; 26 import androidx.room.compiler.processing.XTypeElement; 27 import com.google.common.base.Supplier; 28 import com.google.common.collect.ImmutableList; 29 import com.google.common.collect.ImmutableSet; 30 import com.squareup.javapoet.ClassName; 31 import dagger.hilt.processor.internal.ClassNames; 32 import dagger.hilt.processor.internal.ProcessorErrors; 33 import dagger.internal.codegen.xprocessing.XAnnotations; 34 import java.util.List; 35 36 /** Extracts the list of annotations annotated with {@link dagger.hilt.GeneratesRootInput}. */ 37 public final class GeneratesRootInputs { 38 static final String AGGREGATING_PACKAGE = 39 GeneratesRootInputs.class.getPackage().getName() + ".codegen"; 40 41 private final XProcessingEnv env; 42 private final Supplier<ImmutableList<ClassName>> generatesRootInputAnnotations = 43 memoize(() -> getAnnotationList()); 44 GeneratesRootInputs(XProcessingEnv processingEnvironment)45 public GeneratesRootInputs(XProcessingEnv processingEnvironment) { 46 this.env = processingEnvironment; 47 } 48 getElementsToWaitFor(XRoundEnv roundEnv)49 public ImmutableSet<XElement> getElementsToWaitFor(XRoundEnv roundEnv) { 50 // Processing can only take place after all dependent annotations have been processed 51 // Note: We start with ClassName rather than TypeElement because jdk8 does not treat type 52 // elements as equal across rounds. Thus, in order for RoundEnvironment#getElementsAnnotatedWith 53 // to work properly, we get new elements to ensure it works across rounds (See b/148693284). 54 return generatesRootInputAnnotations.get().stream() 55 .map(className -> env.findTypeElement(className.toString())) 56 .filter(element -> element != null) 57 .flatMap( 58 annotation -> roundEnv.getElementsAnnotatedWith(annotation.getQualifiedName()).stream()) 59 .collect(toImmutableSet()); 60 } 61 getAnnotationList()62 private ImmutableList<ClassName> getAnnotationList() { 63 List<? extends XTypeElement> annotationElements = 64 env.getTypeElementsFromPackage(AGGREGATING_PACKAGE); 65 66 ImmutableList.Builder<ClassName> builder = ImmutableList.builder(); 67 for (XTypeElement element : annotationElements) { 68 ProcessorErrors.checkState( 69 element.isClass(), 70 element, 71 "Only classes may be in package %s. Did you add custom code in the package?", 72 AGGREGATING_PACKAGE); 73 74 XAnnotation annotation = 75 element.getAnnotation(ClassNames.GENERATES_ROOT_INPUT_PROPAGATED_DATA); 76 ProcessorErrors.checkState( 77 annotation != null, 78 element, 79 "Classes in package %s must be annotated with @%s: %s." 80 + " Found: %s. Files in this package are generated, did you add custom code in the" 81 + " package? ", 82 AGGREGATING_PACKAGE, 83 ClassNames.GENERATES_ROOT_INPUT_PROPAGATED_DATA, 84 element.getClassName().simpleName(), 85 element.getAllAnnotations().stream() 86 .map(XAnnotations::toStableString) 87 .collect(toImmutableSet())); 88 89 XTypeElement value = annotation.getAsType("value").getTypeElement(); 90 91 builder.add(value.getClassName()); 92 } 93 // This annotation was on Dagger so it couldn't be annotated with @GeneratesRootInput to be 94 // cultivated later. We have to manually add it to the list. 95 builder.add(ClassNames.PRODUCTION_COMPONENT); 96 return builder.build(); 97 } 98 } 99