• 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.internal.codegen.xprocessing;
18 
19 import static androidx.room.compiler.processing.XElementKt.isConstructor;
20 import static androidx.room.compiler.processing.XElementKt.isField;
21 import static androidx.room.compiler.processing.XElementKt.isMethod;
22 import static androidx.room.compiler.processing.XElementKt.isMethodParameter;
23 import static androidx.room.compiler.processing.XElementKt.isTypeElement;
24 import static androidx.room.compiler.processing.XElementKt.isVariableElement;
25 import static androidx.room.compiler.processing.compat.XConverters.toJavac;
26 import static com.google.common.base.Preconditions.checkState;
27 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
28 
29 import androidx.room.compiler.processing.XAnnotated;
30 import androidx.room.compiler.processing.XAnnotation;
31 import androidx.room.compiler.processing.XConstructorElement;
32 import androidx.room.compiler.processing.XElement;
33 import androidx.room.compiler.processing.XEnumEntry;
34 import androidx.room.compiler.processing.XExecutableElement;
35 import androidx.room.compiler.processing.XExecutableParameterElement;
36 import androidx.room.compiler.processing.XFieldElement;
37 import androidx.room.compiler.processing.XMethodElement;
38 import androidx.room.compiler.processing.XTypeElement;
39 import androidx.room.compiler.processing.XVariableElement;
40 import com.google.common.collect.ImmutableSet;
41 import com.squareup.javapoet.ClassName;
42 import java.util.Collection;
43 import java.util.Optional;
44 import javax.lang.model.element.ElementKind;
45 
46 // TODO(bcorso): Consider moving these methods into XProcessing library.
47 /** A utility class for {@link XElement} helper methods. */
48 public final class XElements {
49 
50   // TODO(bcorso): Replace usages with getJvmName() once it exists.
51   /** Returns the simple name of the element. */
getSimpleName(XElement element)52   public static String getSimpleName(XElement element) {
53     return toJavac(element).getSimpleName().toString();
54   }
55 
56   /**
57    * Returns the closest enclosing element that is a {@link XTypeElement} or throws an {@link
58    * IllegalStateException} if one doesn't exists.
59    */
closestEnclosingTypeElement(XElement element)60   public static XTypeElement closestEnclosingTypeElement(XElement element) {
61     return optionalClosestEnclosingTypeElement(element)
62         .orElseThrow(() -> new IllegalStateException("No enclosing TypeElement for: " + element));
63   }
64 
optionalClosestEnclosingTypeElement(XElement element)65   private static Optional<XTypeElement> optionalClosestEnclosingTypeElement(XElement element) {
66     if (isTypeElement(element)) {
67       return Optional.of(asTypeElement(element));
68     } else if (isConstructor(element)) {
69       return Optional.of(asConstructor(element).getEnclosingElement());
70     } else if (isMethod(element)) {
71       return optionalClosestEnclosingTypeElement(asMethod(element).getEnclosingElement());
72     } else if (isField(element)) {
73       return optionalClosestEnclosingTypeElement(asField(element).getEnclosingElement());
74     } else if (isMethodParameter(element)) {
75       return optionalClosestEnclosingTypeElement(
76           asMethodParameter(element).getEnclosingMethodElement());
77     }
78     return Optional.empty();
79   }
80 
isEnumEntry(XElement element)81   public static boolean isEnumEntry(XElement element) {
82     return element instanceof XEnumEntry;
83   }
84 
isEnum(XElement element)85   public static boolean isEnum(XElement element) {
86     return toJavac(element).getKind() == ElementKind.ENUM;
87   }
88 
isExecutable(XElement element)89   public static boolean isExecutable(XElement element) {
90     return isConstructor(element) || isMethod(element);
91   }
92 
asExecutable(XElement element)93   public static XExecutableElement asExecutable(XElement element) {
94     checkState(isExecutable(element));
95     return (XExecutableElement) element;
96   }
97 
asTypeElement(XElement element)98   public static XTypeElement asTypeElement(XElement element) {
99     checkState(isTypeElement(element));
100     return (XTypeElement) element;
101   }
102 
103   // TODO(bcorso): Rename this and the XElementKt.isMethodParameter to isExecutableParameter.
asMethodParameter(XElement element)104   public static XExecutableParameterElement asMethodParameter(XElement element) {
105     checkState(isMethodParameter(element));
106     return (XExecutableParameterElement) element;
107   }
108 
asField(XElement element)109   public static XFieldElement asField(XElement element) {
110     checkState(isField(element));
111     return (XFieldElement) element;
112   }
113 
asVariable(XElement element)114   public static XVariableElement asVariable(XElement element) {
115     checkState(isVariableElement(element));
116     return (XVariableElement) element;
117   }
118 
asConstructor(XElement element)119   public static XConstructorElement asConstructor(XElement element) {
120     checkState(isConstructor(element));
121     return (XConstructorElement) element;
122   }
123 
asMethod(XElement element)124   public static XMethodElement asMethod(XElement element) {
125     checkState(isMethod(element));
126     return (XMethodElement) element;
127   }
128 
getAnnotatedAnnotations( XAnnotated annotated, ClassName annotationName)129   public static ImmutableSet<XAnnotation> getAnnotatedAnnotations(
130       XAnnotated annotated, ClassName annotationName) {
131     return annotated.getAllAnnotations().stream()
132         .filter(annotation -> annotation.getType().getTypeElement().hasAnnotation(annotationName))
133         .collect(toImmutableSet());
134   }
135 
136   /** Returns {@code true} if {@code annotated} is annotated with any of the given annotations. */
hasAnyAnnotation(XAnnotated annotated, ClassName... annotations)137   public static boolean hasAnyAnnotation(XAnnotated annotated, ClassName... annotations) {
138     return hasAnyAnnotation(annotated, ImmutableSet.copyOf(annotations));
139   }
140 
141   /** Returns {@code true} if {@code annotated} is annotated with any of the given annotations. */
hasAnyAnnotation(XAnnotated annotated, Collection<ClassName> annotations)142   public static boolean hasAnyAnnotation(XAnnotated annotated, Collection<ClassName> annotations) {
143     return annotations.stream().anyMatch(annotated::hasAnnotation);
144   }
145 
146   /**
147    * Returns any annotation from {@code annotations} that annotates {@code annotated} or else {@code
148    * Optional.empty()}.
149    */
getAnyAnnotation( XAnnotated annotated, ClassName... annotations)150   public static Optional<XAnnotation> getAnyAnnotation(
151       XAnnotated annotated, ClassName... annotations) {
152     return getAnyAnnotation(annotated, ImmutableSet.copyOf(annotations));
153   }
154 
155   /**
156    * Returns any annotation from {@code annotations} that annotates {@code annotated} or else
157    * {@code Optional.empty()}.
158    */
getAnyAnnotation( XAnnotated annotated, Collection<ClassName> annotations)159   public static Optional<XAnnotation> getAnyAnnotation(
160       XAnnotated annotated, Collection<ClassName> annotations) {
161     return annotations.stream()
162         .filter(annotated::hasAnnotation)
163         .map(annotated::getAnnotation)
164         .findFirst();
165   }
166 
167   /** Returns all annotations from {@code annotations} that annotate {@code annotated}. */
getAllAnnotations( XAnnotated annotated, Collection<ClassName> annotations)168   public static ImmutableSet<XAnnotation> getAllAnnotations(
169       XAnnotated annotated, Collection<ClassName> annotations) {
170     return annotations.stream()
171         .filter(annotated::hasAnnotation)
172         .map(annotated::getAnnotation)
173         .collect(toImmutableSet());
174   }
175 
XElements()176   private XElements() {}
177 }
178