• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 import static androidx.room.compiler.processing.compat.XConverters.getProcessingEnv;
20 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
21 
22 import androidx.room.compiler.processing.XAnnotation;
23 import androidx.room.compiler.processing.XProcessingEnv;
24 import androidx.room.compiler.processing.XTypeElement;
25 import com.google.auto.value.AutoValue;
26 import com.google.common.collect.ImmutableSet;
27 import dagger.hilt.processor.internal.AggregatedElements;
28 import dagger.hilt.processor.internal.ClassNames;
29 import dagger.hilt.processor.internal.ProcessorErrors;
30 import dagger.hilt.processor.internal.root.ir.DefineComponentClassesIr;
31 
32 /**
33  * A class that represents the values stored in an {@link
34  * dagger.hilt.internal.definecomponent.DefineComponentClasses} annotation.
35  */
36 @AutoValue
37 public abstract class DefineComponentClassesMetadata {
38 
39   /** Returns the aggregating element */
aggregatingElement()40   public abstract XTypeElement aggregatingElement();
41 
42   /**
43    * Returns the element annotated with {@code dagger.hilt.internal.definecomponent.DefineComponent}
44    * or {@code dagger.hilt.internal.definecomponent.DefineComponent.Builder}.
45    */
element()46   public abstract XTypeElement element();
47 
48   /** Returns {@code true} if this element represents a component. */
isComponent()49   abstract boolean isComponent();
50 
51   /** Returns {@code true} if this element represents a component builder. */
isComponentBuilder()52   boolean isComponentBuilder() {
53     return !isComponent();
54   }
55 
56   /** Returns metadata for all aggregated elements in the aggregating package. */
from(XProcessingEnv env)57   public static ImmutableSet<DefineComponentClassesMetadata> from(XProcessingEnv env) {
58     return from(
59         AggregatedElements.from(
60             ClassNames.DEFINE_COMPONENT_CLASSES_PACKAGE, ClassNames.DEFINE_COMPONENT_CLASSES, env));
61   }
62 
63   /** Returns metadata for each aggregated element. */
from( ImmutableSet<XTypeElement> aggregatedElements)64   public static ImmutableSet<DefineComponentClassesMetadata> from(
65       ImmutableSet<XTypeElement> aggregatedElements) {
66     return aggregatedElements.stream()
67         .map(aggregatedElement -> create(aggregatedElement))
68         .collect(toImmutableSet());
69   }
70 
create(XTypeElement element)71   private static DefineComponentClassesMetadata create(XTypeElement element) {
72     XAnnotation annotation = element.getAnnotation(ClassNames.DEFINE_COMPONENT_CLASSES);
73 
74     String componentName = annotation.getAsString("component");
75     String builderName = annotation.getAsString("builder");
76 
77     ProcessorErrors.checkState(
78         !(componentName.isEmpty() && builderName.isEmpty()),
79         element,
80         "@DefineComponentClasses missing both `component` and `builder` members.");
81 
82     ProcessorErrors.checkState(
83         componentName.isEmpty() || builderName.isEmpty(),
84         element,
85         "@DefineComponentClasses should not include both `component` and `builder` members.");
86 
87     boolean isComponent = !componentName.isEmpty();
88     String componentOrBuilderName = isComponent ? componentName : builderName;
89     XTypeElement componentOrBuilderElement =
90         getProcessingEnv(element).findTypeElement(componentOrBuilderName);
91     ProcessorErrors.checkState(
92         componentOrBuilderElement != null,
93         componentOrBuilderElement,
94         "%s.%s(), has invalid value: `%s`.",
95         ClassNames.DEFINE_COMPONENT_CLASSES.simpleName(),
96         isComponent ? "component" : "builder",
97         componentOrBuilderName);
98     return new AutoValue_DefineComponentClassesMetadata(
99         element, componentOrBuilderElement, isComponent);
100   }
101 
toIr(DefineComponentClassesMetadata metadata)102   public static DefineComponentClassesIr toIr(DefineComponentClassesMetadata metadata) {
103     return new DefineComponentClassesIr(
104         metadata.aggregatingElement().getClassName(),
105         metadata.element().getClassName().canonicalName());
106   }
107 }
108