aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Corso <bcorso@google.com>2021-06-03 07:52:09 -0700
committerGoogle Java Core Libraries <java-libraries-firehose+copybara@google.com>2021-06-03 07:52:41 -0700
commitdec3bf0ec7b72d9cec9f92b497570bc46590a65d (patch)
treefc5e1899e1790e949336c81d0f29cd042fd57063
parent57fdeb9996af4b19466701cac5a69e917abf249e (diff)
downloadauto-dec3bf0ec7b72d9cec9f92b497570bc46590a65d.tar.gz
Add String and TypeElement versions of auto-common APIs that currently take in Class.
These changes continue the effort to move away from referencing classes from the user API directly in processors, which can cause issues especially with Android dependencies. Note: I decided not to do anything with isTypeOf yet because I'm not sure of a great way to support that. RELNOTES=Add String and TypeElement versions of auto-common APIs that currently take in Class. PiperOrigin-RevId: 377287397
-rw-r--r--common/src/main/java/com/google/auto/common/AnnotationMirrors.java45
-rw-r--r--common/src/main/java/com/google/auto/common/MoreElements.java59
-rw-r--r--common/src/test/java/com/google/auto/common/AnnotationMirrorsTest.java54
-rw-r--r--common/src/test/java/com/google/auto/common/MoreElementsTest.java101
4 files changed, 208 insertions, 51 deletions
diff --git a/common/src/main/java/com/google/auto/common/AnnotationMirrors.java b/common/src/main/java/com/google/auto/common/AnnotationMirrors.java
index 80d2335d..f0771bcd 100644
--- a/common/src/main/java/com/google/auto/common/AnnotationMirrors.java
+++ b/common/src/main/java/com/google/auto/common/AnnotationMirrors.java
@@ -16,21 +16,20 @@
package com.google.auto.common;
import static com.google.auto.common.MoreElements.isAnnotationPresent;
+import static com.google.auto.common.MoreStreams.toImmutableSet;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Equivalence;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.lang.annotation.Annotation;
import java.util.Arrays;
-import java.util.List;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
@@ -154,21 +153,35 @@ public final class AnnotationMirrors {
}
/**
- * Returns all {@linkplain AnnotationMirror annotations} that are present on the given
- * {@link Element} which are themselves annotated with {@code annotationType}.
+ * Returns all {@linkplain AnnotationMirror annotations} that are present on the given {@link
+ * Element} which are themselves annotated with {@code annotationClass}.
*/
public static ImmutableSet<? extends AnnotationMirror> getAnnotatedAnnotations(
- Element element, final Class<? extends Annotation> annotationType) {
- List<? extends AnnotationMirror> annotations = element.getAnnotationMirrors();
- return FluentIterable.from(annotations)
- .filter(
- new Predicate<AnnotationMirror>() {
- @Override
- public boolean apply(AnnotationMirror input) {
- return isAnnotationPresent(input.getAnnotationType().asElement(), annotationType);
- }
- })
- .toSet();
+ Element element, Class<? extends Annotation> annotationClass) {
+ return getAnnotatedAnnotations(element, annotationClass.getCanonicalName());
+ }
+
+ /**
+ * Returns all {@linkplain AnnotationMirror annotations} that are present on the given {@link
+ * Element} which are themselves annotated with {@code annotation}.
+ */
+ public static ImmutableSet<? extends AnnotationMirror> getAnnotatedAnnotations(
+ Element element, TypeElement annotation) {
+ return element.getAnnotationMirrors().stream()
+ .filter(input -> isAnnotationPresent(input.getAnnotationType().asElement(), annotation))
+ .collect(toImmutableSet());
+ }
+
+ /**
+ * Returns all {@linkplain AnnotationMirror annotations} that are present on the given {@link
+ * Element} which are themselves annotated with an annotation whose type's canonical name is
+ * {@code annotationName}.
+ */
+ public static ImmutableSet<? extends AnnotationMirror> getAnnotatedAnnotations(
+ Element element, String annotationName) {
+ return element.getAnnotationMirrors().stream()
+ .filter(input -> isAnnotationPresent(input.getAnnotationType().asElement(), annotationName))
+ .collect(toImmutableSet());
}
private AnnotationMirrors() {}
diff --git a/common/src/main/java/com/google/auto/common/MoreElements.java b/common/src/main/java/com/google/auto/common/MoreElements.java
index bee157f6..8061cd57 100644
--- a/common/src/main/java/com/google/auto/common/MoreElements.java
+++ b/common/src/main/java/com/google/auto/common/MoreElements.java
@@ -212,10 +212,10 @@ public final class MoreElements {
}
/**
- * Returns {@code true} iff the given element has an {@link AnnotationMirror} whose
- * {@linkplain AnnotationMirror#getAnnotationType() annotation type} has the same canonical name
- * as that of {@code annotationClass}. This method is a safer alternative to calling
- * {@link Element#getAnnotation} and checking for {@code null} as it avoids any interaction with
+ * Returns {@code true} iff the given element has an {@link AnnotationMirror} whose {@linkplain
+ * AnnotationMirror#getAnnotationType() annotation type} has the same canonical name as that of
+ * {@code annotationClass}. This method is a safer alternative to calling {@link
+ * Element#getAnnotation} and checking for {@code null} as it avoids any interaction with
* annotation proxies.
*/
public static boolean isAnnotationPresent(
@@ -224,6 +224,27 @@ public final class MoreElements {
}
/**
+ * Returns {@code true} iff the given element has an {@link AnnotationMirror} whose {@linkplain
+ * AnnotationMirror#getAnnotationType() annotation type} has the same fully qualified name as that
+ * of {@code annotation}. This method is a safer alternative to calling {@link
+ * Element#getAnnotation} and checking for {@code null} as it avoids any interaction with
+ * annotation proxies.
+ */
+ public static boolean isAnnotationPresent(Element element, TypeElement annotation) {
+ return getAnnotationMirror(element, annotation).isPresent();
+ }
+
+ /**
+ * Returns {@code true} iff the given element has an {@link AnnotationMirror} whose {@linkplain
+ * AnnotationMirror#getAnnotationType() annotation type} has {@code annotationName} as its
+ * canonical name. This method is a safer alternative to calling {@link Element#getAnnotation} and
+ * checking for {@code null} as it avoids any interaction with annotation proxies.
+ */
+ public static boolean isAnnotationPresent(Element element, String annotationName) {
+ return getAnnotationMirror(element, annotationName).isPresent();
+ }
+
+ /**
* Returns an {@link AnnotationMirror} for the annotation of type {@code annotationClass} on
* {@code element}, or {@link Optional#absent()} if no such annotation exists. This method is a
* safer alternative to calling {@link Element#getAnnotation} as it avoids any interaction with
@@ -231,10 +252,36 @@ public final class MoreElements {
*/
public static Optional<AnnotationMirror> getAnnotationMirror(
Element element, Class<? extends Annotation> annotationClass) {
- String annotationClassName = annotationClass.getCanonicalName();
+ return getAnnotationMirror(element, annotationClass.getCanonicalName());
+ }
+
+ /**
+ * Returns an {@link AnnotationMirror} for the annotation of type {@code annotation} on {@code
+ * element}, or {@link Optional#absent()} if no such annotation exists. This method is a safer
+ * alternative to calling {@link Element#getAnnotation} as it avoids any interaction with
+ * annotation proxies.
+ */
+ public static Optional<AnnotationMirror> getAnnotationMirror(
+ Element element, TypeElement annotation) {
+ for (AnnotationMirror elementAnnotation : element.getAnnotationMirrors()) {
+ if (elementAnnotation.getAnnotationType().asElement().equals(annotation)) {
+ return Optional.of(elementAnnotation);
+ }
+ }
+ return Optional.absent();
+ }
+
+ /**
+ * Returns an {@link AnnotationMirror} for the annotation whose type's canonical name is on {@code
+ * element}, or {@link Optional#absent()} if no such annotation exists. This method is a safer
+ * alternative to calling {@link Element#getAnnotation} as it avoids any interaction with
+ * annotation proxies.
+ */
+ public static Optional<AnnotationMirror> getAnnotationMirror(
+ Element element, String annotationName) {
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
TypeElement annotationTypeElement = asType(annotationMirror.getAnnotationType().asElement());
- if (annotationTypeElement.getQualifiedName().contentEquals(annotationClassName)) {
+ if (annotationTypeElement.getQualifiedName().contentEquals(annotationName)) {
return Optional.of(annotationMirror);
}
}
diff --git a/common/src/test/java/com/google/auto/common/AnnotationMirrorsTest.java b/common/src/test/java/com/google/auto/common/AnnotationMirrorsTest.java
index b1a0a152..363fd24b 100644
--- a/common/src/test/java/com/google/auto/common/AnnotationMirrorsTest.java
+++ b/common/src/test/java/com/google/auto/common/AnnotationMirrorsTest.java
@@ -22,12 +22,17 @@ import static com.google.common.truth.Truth.assertThat;
import static com.google.testing.compile.CompilationSubject.assertThat;
import static org.junit.Assert.fail;
+import com.google.common.collect.ImmutableSet;
import com.google.common.testing.EquivalenceTester;
+import com.google.common.truth.Correspondence;
import com.google.testing.compile.CompilationRule;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleAnnotationValueVisitor6;
@@ -252,4 +257,53 @@ public class AnnotationMirrorsTest {
private AnnotationMirror annotationOn(Class<?> clazz) {
return getOnlyElement(elements.getTypeElement(clazz.getCanonicalName()).getAnnotationMirrors());
}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ private @interface AnnotatingAnnotation {}
+
+ @AnnotatingAnnotation
+ @Retention(RetentionPolicy.RUNTIME)
+ private @interface AnnotatedAnnotation1 {}
+
+ @AnnotatingAnnotation
+ @Retention(RetentionPolicy.RUNTIME)
+ private @interface AnnotatedAnnotation2 {}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ private @interface NotAnnotatedAnnotation {}
+
+ @AnnotatedAnnotation1
+ @NotAnnotatedAnnotation
+ @AnnotatedAnnotation2
+ private static final class AnnotatedClass {}
+
+ @Test
+ public void getAnnotatedAnnotations() {
+ TypeElement element = elements.getTypeElement(AnnotatedClass.class.getCanonicalName());
+
+ // Test Class API
+ getAnnotatedAnnotationsAsserts(
+ AnnotationMirrors.getAnnotatedAnnotations(element, AnnotatingAnnotation.class));
+
+ // Test String API
+ String annotatingAnnotationName = AnnotatingAnnotation.class.getCanonicalName();
+ getAnnotatedAnnotationsAsserts(
+ AnnotationMirrors.getAnnotatedAnnotations(element, annotatingAnnotationName));
+
+ // Test TypeElement API
+ TypeElement annotatingAnnotationElement = elements.getTypeElement(annotatingAnnotationName);
+ getAnnotatedAnnotationsAsserts(
+ AnnotationMirrors.getAnnotatedAnnotations(element, annotatingAnnotationElement));
+ }
+
+ private void getAnnotatedAnnotationsAsserts(
+ ImmutableSet<? extends AnnotationMirror> annotatedAnnotations) {
+ assertThat(annotatedAnnotations)
+ .comparingElementsUsing(
+ Correspondence.transforming(
+ (AnnotationMirror a) -> MoreTypes.asTypeElement(a.getAnnotationType()), "has type"))
+ .containsExactly(
+ elements.getTypeElement(AnnotatedAnnotation1.class.getCanonicalName()),
+ elements.getTypeElement(AnnotatedAnnotation2.class.getCanonicalName()));
+ }
}
diff --git a/common/src/test/java/com/google/auto/common/MoreElementsTest.java b/common/src/test/java/com/google/auto/common/MoreElementsTest.java
index de33c567..0677a7a0 100644
--- a/common/src/test/java/com/google/auto/common/MoreElementsTest.java
+++ b/common/src/test/java/com/google/auto/common/MoreElementsTest.java
@@ -58,13 +58,14 @@ public class MoreElementsTest {
@Rule public CompilationRule compilation = new CompilationRule();
@Rule public Expect expect = Expect.create();
+ private Elements elements;
private PackageElement javaLangPackageElement;
private TypeElement objectElement;
private TypeElement stringElement;
@Before
public void initializeTestElements() {
- Elements elements = compilation.getElements();
+ this.elements = compilation.getElements();
this.javaLangPackageElement = elements.getPackageElement("java.lang");
this.objectElement = elements.getTypeElement(Object.class.getCanonicalName());
this.stringElement = elements.getTypeElement(String.class.getCanonicalName());
@@ -94,15 +95,14 @@ public class MoreElementsTest {
@Test
public void asTypeElement() {
- Element typeElement = compilation.getElements().getTypeElement(String.class.getCanonicalName());
+ Element typeElement = elements.getTypeElement(String.class.getCanonicalName());
assertTrue(MoreElements.isType(typeElement));
assertThat(MoreElements.asType(typeElement)).isEqualTo(typeElement);
}
@Test
public void asTypeElement_notATypeElement() {
- TypeElement typeElement =
- compilation.getElements().getTypeElement(String.class.getCanonicalName());
+ TypeElement typeElement = elements.getTypeElement(String.class.getCanonicalName());
for (ExecutableElement e : ElementFilter.methodsIn(typeElement.getEnclosedElements())) {
assertFalse(MoreElements.isType(e));
try {
@@ -194,27 +194,76 @@ public class MoreElementsTest {
@Test
public void isAnnotationPresent() {
TypeElement annotatedAnnotationElement =
- compilation.getElements().getTypeElement(AnnotatedAnnotation.class.getCanonicalName());
- assertThat(MoreElements.isAnnotationPresent(annotatedAnnotationElement, Documented.class))
- .isTrue();
- assertThat(MoreElements.isAnnotationPresent(annotatedAnnotationElement, InnerAnnotation.class))
- .isTrue();
- assertThat(MoreElements.isAnnotationPresent(annotatedAnnotationElement, SuppressWarnings.class))
- .isFalse();
+ elements.getTypeElement(AnnotatedAnnotation.class.getCanonicalName());
+
+ // Test Class API
+ isAnnotationPresentAsserts(
+ MoreElements.isAnnotationPresent(annotatedAnnotationElement, Documented.class),
+ MoreElements.isAnnotationPresent(annotatedAnnotationElement, InnerAnnotation.class),
+ MoreElements.isAnnotationPresent(annotatedAnnotationElement, SuppressWarnings.class));
+
+ // Test String API
+ String documentedName = Documented.class.getCanonicalName();
+ String innerAnnotationName = InnerAnnotation.class.getCanonicalName();
+ String suppressWarningsName = SuppressWarnings.class.getCanonicalName();
+ isAnnotationPresentAsserts(
+ MoreElements.isAnnotationPresent(annotatedAnnotationElement, documentedName),
+ MoreElements.isAnnotationPresent(annotatedAnnotationElement, innerAnnotationName),
+ MoreElements.isAnnotationPresent(annotatedAnnotationElement, suppressWarningsName));
+
+ // Test TypeElement API
+ TypeElement documentedElement = elements.getTypeElement(documentedName);
+ TypeElement innerAnnotationElement = elements.getTypeElement(innerAnnotationName);
+ TypeElement suppressWarningsElement = elements.getTypeElement(suppressWarningsName);
+ isAnnotationPresentAsserts(
+ MoreElements.isAnnotationPresent(annotatedAnnotationElement, documentedElement),
+ MoreElements.isAnnotationPresent(annotatedAnnotationElement, innerAnnotationElement),
+ MoreElements.isAnnotationPresent(annotatedAnnotationElement, suppressWarningsElement));
+ }
+
+ private void isAnnotationPresentAsserts(
+ boolean isDocumentedPresent,
+ boolean isInnerAnnotationPresent,
+ boolean isSuppressWarningsPresent) {
+ assertThat(isDocumentedPresent).isTrue();
+ assertThat(isInnerAnnotationPresent).isTrue();
+ assertThat(isSuppressWarningsPresent).isFalse();
}
@Test
public void getAnnotationMirror() {
TypeElement element =
- compilation.getElements().getTypeElement(AnnotatedAnnotation.class.getCanonicalName());
-
- Optional<AnnotationMirror> documented =
- MoreElements.getAnnotationMirror(element, Documented.class);
- Optional<AnnotationMirror> innerAnnotation =
- MoreElements.getAnnotationMirror(element, InnerAnnotation.class);
- Optional<AnnotationMirror> suppressWarnings =
- MoreElements.getAnnotationMirror(element, SuppressWarnings.class);
-
+ elements.getTypeElement(AnnotatedAnnotation.class.getCanonicalName());
+
+ // Test Class API
+ getAnnotationMirrorAsserts(
+ MoreElements.getAnnotationMirror(element, Documented.class),
+ MoreElements.getAnnotationMirror(element, InnerAnnotation.class),
+ MoreElements.getAnnotationMirror(element, SuppressWarnings.class));
+
+ // Test String API
+ String documentedName = Documented.class.getCanonicalName();
+ String innerAnnotationName = InnerAnnotation.class.getCanonicalName();
+ String suppressWarningsName = SuppressWarnings.class.getCanonicalName();
+ getAnnotationMirrorAsserts(
+ MoreElements.getAnnotationMirror(element, documentedName),
+ MoreElements.getAnnotationMirror(element, innerAnnotationName),
+ MoreElements.getAnnotationMirror(element, suppressWarningsName));
+
+ // Test TypeElement API
+ TypeElement documentedElement = elements.getTypeElement(documentedName);
+ TypeElement innerAnnotationElement = elements.getTypeElement(innerAnnotationName);
+ TypeElement suppressWarningsElement = elements.getTypeElement(suppressWarningsName);
+ getAnnotationMirrorAsserts(
+ MoreElements.getAnnotationMirror(element, documentedElement),
+ MoreElements.getAnnotationMirror(element, innerAnnotationElement),
+ MoreElements.getAnnotationMirror(element, suppressWarningsElement));
+ }
+
+ private void getAnnotationMirrorAsserts(
+ Optional<AnnotationMirror> documented,
+ Optional<AnnotationMirror> innerAnnotation,
+ Optional<AnnotationMirror> suppressWarnings) {
expect.that(documented).isPresent();
expect.that(innerAnnotation).isPresent();
expect.that(suppressWarnings).isAbsent();
@@ -265,7 +314,6 @@ public class MoreElementsTest {
@Test
public void getLocalAndInheritedMethods_Old() {
- Elements elements = compilation.getElements();
Types types = compilation.getTypes();
TypeMirror intMirror = types.getPrimitiveType(TypeKind.INT);
TypeMirror longMirror = types.getPrimitiveType(TypeKind.LONG);
@@ -290,7 +338,6 @@ public class MoreElementsTest {
@Test
public void getLocalAndInheritedMethods() {
- Elements elements = compilation.getElements();
Types types = compilation.getTypes();
TypeMirror intMirror = types.getPrimitiveType(TypeKind.INT);
TypeMirror longMirror = types.getPrimitiveType(TypeKind.LONG);
@@ -314,7 +361,6 @@ public class MoreElementsTest {
@Test
public void getAllMethods() {
- Elements elements = compilation.getElements();
Types types = compilation.getTypes();
TypeMirror intMirror = types.getPrimitiveType(TypeKind.INT);
TypeMirror longMirror = types.getPrimitiveType(TypeKind.LONG);
@@ -365,10 +411,9 @@ public class MoreElementsTest {
// Example from https://github.com/williamlian/daggerbug
@Test
public void getLocalAndInheritedMethods_DaggerBug() {
- Elements elementUtils = compilation.getElements();
- TypeElement main = elementUtils.getTypeElement(Main.ParentComponent.class.getCanonicalName());
+ TypeElement main = elements.getTypeElement(Main.ParentComponent.class.getCanonicalName());
Set<ExecutableElement> methods =
- MoreElements.getLocalAndInheritedMethods(main, compilation.getTypes(), elementUtils);
+ MoreElements.getLocalAndInheritedMethods(main, compilation.getTypes(), elements);
assertThat(methods).hasSize(1);
ExecutableElement method = methods.iterator().next();
assertThat(method.getSimpleName().toString()).isEqualTo("injectable");
@@ -414,7 +459,7 @@ public class MoreElementsTest {
}
private ExecutableElement getMethod(Class<?> c, String methodName, TypeMirror... parameterTypes) {
- TypeElement type = compilation.getElements().getTypeElement(c.getCanonicalName());
+ TypeElement type = elements.getTypeElement(c.getCanonicalName());
Types types = compilation.getTypes();
ExecutableElement found = null;
for (ExecutableElement method : ElementFilter.methodsIn(type.getEnclosedElements())) {
@@ -468,8 +513,6 @@ public class MoreElementsTest {
// are implemented in AbstractList.
@Test
public void getLocalAndInheritedMethods_AbstractList() {
- Elements elements = compilation.getElements();
-
TypeElement abstractType =
elements.getTypeElement(AbstractAbstractList.class.getCanonicalName());
Set<ExecutableElement> abstractTypeMethods =