• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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