getAnnotationElement
return entry;
}
}
- throw new IllegalArgumentException(String.format("@%s does not define an element %s()",
- MoreElements.asType(annotationMirror.getAnnotationType().asElement()).getQualifiedName(),
- elementName));
+ throw new IllegalArgumentException(
+ String.format(
+ "@%s does not define an element %s()",
+ MoreElements.asType(annotationMirror.getAnnotationType().asElement())
+ .getQualifiedName(),
+ elementName));
+ }
+
+ /**
+ * 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, Class extends Annotation> annotationClass) {
+ String name = annotationClass.getCanonicalName();
+ if (name == null) {
+ return ImmutableSet.of();
+ }
+ return getAnnotatedAnnotations(element, name);
}
/**
- * 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 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());
+ }
+
+ /**
+ * Returns a string representation of the given annotation mirror, suitable for inclusion in a
+ * Java source file to reproduce the annotation in source form.
+ *
+ * Fully qualified names are used for types in annotations, class literals, and enum constants,
+ * ensuring that the source form will compile without requiring additional imports.
*/
- 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() {
- @Override public boolean apply(AnnotationMirror input) {
- return isAnnotationPresent(input.getAnnotationType().asElement(), annotationType);
- }
- })
- .toSet();
+ public static String toString(AnnotationMirror annotationMirror) {
+ return AnnotationOutput.toString(annotationMirror);
}
private AnnotationMirrors() {}
diff --git a/common/src/main/java/com/google/auto/common/AnnotationOutput.java b/common/src/main/java/com/google/auto/common/AnnotationOutput.java
new file mode 100644
index 0000000000..e52bde66c7
--- /dev/null
+++ b/common/src/main/java/com/google/auto/common/AnnotationOutput.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2014 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.auto.common;
+
+import static com.google.auto.common.MoreTypes.asTypeElement;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.AnnotationValueVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleAnnotationValueVisitor8;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * Handling of default values for annotation members.
+ *
+ * @author emcmanus@google.com (Éamonn McManus)
+ */
+final class AnnotationOutput {
+ private AnnotationOutput() {} // There are no instances of this class.
+
+ /**
+ * Visitor that produces a string representation of an annotation value, suitable for inclusion in
+ * a Java source file as an annotation member or as the initializer of a variable of the
+ * appropriate type. The syntax for the two is the same except for annotation members that are
+ * themselves annotations. Within an annotation, an annotation member can be written as
+ * {@code @NestedAnnotation(...)}, while in an initializer it must be written as an object, for
+ * example the construction of an {@code @AutoAnnotation} class. That's why we have this abstract
+ * class and two concrete subclasses.
+ */
+ private static class SourceFormVisitor
+ extends SimpleAnnotationValueVisitor8<@Nullable Void, StringBuilder> {
+
+ private String formatType(TypeMirror typeMirror) {
+ return asTypeElement(typeMirror).getQualifiedName().toString();
+ }
+
+ @Override
+ protected @Nullable Void defaultAction(Object value, StringBuilder sb) {
+ sb.append(value);
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitArray(List extends AnnotationValue> values, StringBuilder sb) {
+ sb.append('{');
+ String sep = "";
+ for (AnnotationValue value : values) {
+ sb.append(sep);
+ visit(value, sb);
+ sep = ", ";
+ }
+ sb.append('}');
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitByte(byte b, StringBuilder sb) {
+ sb.append("(byte) ").append(b);
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitShort(short s, StringBuilder sb) {
+ sb.append("(short) ").append(s);
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitChar(char c, StringBuilder sb) {
+ appendQuoted(sb, c);
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitLong(long i, StringBuilder sb) {
+ sb.append(i).append('L');
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitDouble(double d, StringBuilder sb) {
+ if (Double.isNaN(d)) {
+ sb.append("Double.NaN");
+ } else if (d == Double.POSITIVE_INFINITY) {
+ sb.append("Double.POSITIVE_INFINITY");
+ } else if (d == Double.NEGATIVE_INFINITY) {
+ sb.append("Double.NEGATIVE_INFINITY");
+ } else {
+ sb.append(d);
+ }
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitFloat(float f, StringBuilder sb) {
+ if (Float.isNaN(f)) {
+ sb.append("Float.NaN");
+ } else if (f == Float.POSITIVE_INFINITY) {
+ sb.append("Float.POSITIVE_INFINITY");
+ } else if (f == Float.NEGATIVE_INFINITY) {
+ sb.append("Float.NEGATIVE_INFINITY");
+ } else {
+ sb.append(f).append('F');
+ }
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitEnumConstant(VariableElement c, StringBuilder sb) {
+ sb.append(formatType(c.asType())).append('.').append(c.getSimpleName());
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitString(String s, StringBuilder sb) {
+ appendQuoted(sb, s);
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitType(TypeMirror classConstant, StringBuilder sb) {
+ sb.append(formatType(classConstant)).append(".class");
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitAnnotation(AnnotationMirror a, StringBuilder sb) {
+ sb.append('@').append(formatType(a.getAnnotationType()));
+ ImmutableMap map =
+ ImmutableMap.copyOf(a.getElementValues());
+ if (!map.isEmpty()) {
+ sb.append('(');
+ Optional shortForm = shortForm(map);
+ if (shortForm.isPresent()) {
+ this.visit(maybeShorten(shortForm.get()), sb);
+ } else {
+ String sep = "";
+ for (Map.Entry entry : map.entrySet()) {
+ sb.append(sep).append(entry.getKey().getSimpleName()).append(" = ");
+ sep = ", ";
+ this.visit(maybeShorten(entry.getValue()), sb);
+ }
+ }
+ sb.append(')');
+ }
+ return null;
+ }
+ }
+
+ private static AnnotationValue maybeShorten(AnnotationValue value) {
+ return ARRAY_VISITOR.visit(value, value);
+ }
+
+ private static final AnnotationValueVisitor ARRAY_VISITOR =
+ new SimpleAnnotationValueVisitor8() {
+ @Override
+ public AnnotationValue visitArray(
+ List extends AnnotationValue> values, AnnotationValue input) {
+ if (values.size() == 1) {
+ // We can shorten @Foo(a = {23}) to @Foo(a = 23). For the specific case where `a` is
+ // actually `value`, we'll already have shortened that in visitAnnotation, so
+ // effectively we go from @Foo(value = {23}) to @Foo({23}) to @Foo(23).
+ return Iterables.getOnlyElement(values);
+ }
+ return input;
+ }
+
+ @Override
+ protected AnnotationValue defaultAction(Object o, AnnotationValue input) {
+ return input;
+ }
+ };
+
+ // We can shorten @Annot(value = 23) to @Annot(23).
+ private static Optional shortForm(
+ Map values) {
+ if (values.size() == 1
+ && Iterables.getOnlyElement(values.keySet()).getSimpleName().contentEquals("value")) {
+ return Optional.of(Iterables.getOnlyElement(values.values()));
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * Returns a string representation of the given annotation value, suitable for inclusion in a Java
+ * source file as the initializer of a variable of the appropriate type.
+ */
+ static String toString(AnnotationValue annotationValue) {
+ StringBuilder sb = new StringBuilder();
+ new SourceFormVisitor().visit(annotationValue, sb);
+ return sb.toString();
+ }
+
+ /**
+ * Returns a string representation of the given annotation mirror, suitable for inclusion in a
+ * Java source file to reproduce the annotation in source form.
+ */
+ static String toString(AnnotationMirror annotationMirror) {
+ StringBuilder sb = new StringBuilder();
+ new SourceFormVisitor().visitAnnotation(annotationMirror, sb);
+ return sb.toString();
+ }
+
+ private static StringBuilder appendQuoted(StringBuilder sb, String s) {
+ sb.append('"');
+ for (int i = 0; i < s.length(); i++) {
+ appendEscaped(sb, s.charAt(i));
+ }
+ return sb.append('"');
+ }
+
+ private static StringBuilder appendQuoted(StringBuilder sb, char c) {
+ sb.append('\'');
+ appendEscaped(sb, c);
+ return sb.append('\'');
+ }
+
+ private static void appendEscaped(StringBuilder sb, char c) {
+ switch (c) {
+ case '\\':
+ case '"':
+ case '\'':
+ sb.append('\\').append(c);
+ break;
+ case '\n':
+ sb.append("\\n");
+ break;
+ case '\r':
+ sb.append("\\r");
+ break;
+ case '\t':
+ sb.append("\\t");
+ break;
+ default:
+ if (c < 0x20) {
+ sb.append(String.format("\\%03o", (int) c));
+ } else if (c < 0x7f || Character.isLetter(c)) {
+ sb.append(c);
+ } else {
+ sb.append(String.format("\\u%04x", (int) c));
+ }
+ break;
+ }
+ }
+}
diff --git a/common/src/main/java/com/google/auto/common/AnnotationValues.java b/common/src/main/java/com/google/auto/common/AnnotationValues.java
index a5db2cca0a..f301238271 100644
--- a/common/src/main/java/com/google/auto/common/AnnotationValues.java
+++ b/common/src/main/java/com/google/auto/common/AnnotationValues.java
@@ -15,8 +15,8 @@
*/
package com.google.auto.common;
+import static com.google.auto.common.MoreStreams.toImmutableList;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.ImmutableList.toImmutableList;
import com.google.common.base.Equivalence;
import com.google.common.collect.ImmutableList;
@@ -37,91 +37,125 @@
public final class AnnotationValues {
private static final Equivalence ANNOTATION_VALUE_EQUIVALENCE =
new Equivalence() {
- @Override protected boolean doEquivalent(AnnotationValue left, AnnotationValue right) {
- return left.accept(new SimpleAnnotationValueVisitor8() {
- // LHS is not an annotation or array of annotation values, so just test equality.
- @Override protected Boolean defaultAction(Object left, AnnotationValue right) {
- return left.equals(right.accept(
- new SimpleAnnotationValueVisitor8() {
- @Override protected Object defaultAction(Object object, Void unused) {
- return object;
- }
- }, null));
- }
-
- // LHS is an annotation mirror so test equivalence for RHS annotation mirrors
- // and false for other types.
- @Override public Boolean visitAnnotation(AnnotationMirror left, AnnotationValue right) {
- return right.accept(
- new SimpleAnnotationValueVisitor8() {
- @Override protected Boolean defaultAction(Object right, AnnotationMirror left) {
- return false; // Not an annotation mirror, so can't be equal to such.
- }
- @Override
- public Boolean visitAnnotation(AnnotationMirror right, AnnotationMirror left) {
- return AnnotationMirrors.equivalence().equivalent(left, right);
- }
- }, left);
- }
-
- // LHS is a list of annotation values have to collect-test equivalences, or false
- // for any other types.
- @Override
- public Boolean visitArray(List extends AnnotationValue> left, AnnotationValue right) {
- return right.accept(
- new SimpleAnnotationValueVisitor8>() {
- @Override protected Boolean defaultAction(
- Object ignored, List extends AnnotationValue> alsoIgnored) {
- return false; // Not an array, so can't be equal to such.
- }
-
- @SuppressWarnings("unchecked") // safe covariant cast
- @Override public Boolean visitArray(
- List extends AnnotationValue> right ,
- List extends AnnotationValue> left) {
- return AnnotationValues.equivalence().pairwise().equivalent(
- (List) left, (List) right);
- }
- }, left);
- }
-
- @Override
- public Boolean visitType(TypeMirror left, AnnotationValue right) {
- return right.accept(
- new SimpleAnnotationValueVisitor8() {
- @Override protected Boolean defaultAction(
- Object ignored, TypeMirror alsoIgnored) {
- return false; // Not an annotation mirror, so can't be equal to such.
- }
-
- @Override public Boolean visitType(TypeMirror right, TypeMirror left) {
- return MoreTypes.equivalence().equivalent(left, right);
- }
- }, left);
- }
- }, right);
+ @Override
+ protected boolean doEquivalent(AnnotationValue left, AnnotationValue right) {
+ return left.accept(
+ new SimpleAnnotationValueVisitor8() {
+ // LHS is not an annotation or array of annotation values, so just test equality.
+ @Override
+ protected Boolean defaultAction(Object left, AnnotationValue right) {
+ return left.equals(
+ right.accept(
+ new SimpleAnnotationValueVisitor8() {
+ @Override
+ protected Object defaultAction(Object object, Void unused) {
+ return object;
+ }
+ },
+ null));
+ }
+
+ // LHS is an annotation mirror so test equivalence for RHS annotation mirrors
+ // and false for other types.
+ @Override
+ public Boolean visitAnnotation(AnnotationMirror left, AnnotationValue right) {
+ return right.accept(
+ new SimpleAnnotationValueVisitor8() {
+ @Override
+ protected Boolean defaultAction(Object right, AnnotationMirror left) {
+ return false; // Not an annotation mirror, so can't be equal to such.
+ }
+
+ @Override
+ public Boolean visitAnnotation(
+ AnnotationMirror right, AnnotationMirror left) {
+ return AnnotationMirrors.equivalence().equivalent(left, right);
+ }
+ },
+ left);
+ }
+
+ // LHS is a list of annotation values have to collect-test equivalences, or false
+ // for any other types.
+ @Override
+ public Boolean visitArray(
+ List extends AnnotationValue> left, AnnotationValue right) {
+ return right.accept(
+ new SimpleAnnotationValueVisitor8<
+ Boolean, List extends AnnotationValue>>() {
+ @Override
+ protected Boolean defaultAction(
+ Object ignored, List extends AnnotationValue> alsoIgnored) {
+ return false; // Not an array, so can't be equal to such.
+ }
+
+ @SuppressWarnings("unchecked") // safe covariant cast
+ @Override
+ public Boolean visitArray(
+ List extends AnnotationValue> right,
+ List extends AnnotationValue> left) {
+ return AnnotationValues.equivalence()
+ .pairwise()
+ .equivalent(
+ (List) left, (List) right);
+ }
+ },
+ left);
+ }
+
+ @Override
+ public Boolean visitType(TypeMirror left, AnnotationValue right) {
+ return right.accept(
+ new SimpleAnnotationValueVisitor8() {
+ @Override
+ protected Boolean defaultAction(Object ignored, TypeMirror alsoIgnored) {
+ return false; // Not an annotation mirror, so can't be equal to such.
+ }
+
+ @Override
+ public Boolean visitType(TypeMirror right, TypeMirror left) {
+ return MoreTypes.equivalence().equivalent(left, right);
+ }
+ },
+ left);
+ }
+ },
+ right);
}
- @Override protected int doHash(AnnotationValue value) {
- return value.accept(new SimpleAnnotationValueVisitor8() {
- @Override public Integer visitAnnotation(AnnotationMirror value, Void ignore) {
- return AnnotationMirrors.equivalence().hash(value);
- }
-
- @SuppressWarnings("unchecked") // safe covariant cast
- @Override public Integer visitArray(
- List extends AnnotationValue> values, Void ignore) {
- return AnnotationValues.equivalence().pairwise().hash((List) values);
- }
-
- @Override public Integer visitType(TypeMirror value, Void ignore) {
- return MoreTypes.equivalence().hash(value);
- }
-
- @Override protected Integer defaultAction(Object value, Void ignored) {
- return value.hashCode();
- }
- }, null);
+ @Override
+ protected int doHash(AnnotationValue value) {
+ return value.accept(
+ new SimpleAnnotationValueVisitor8() {
+ @Override
+ public Integer visitAnnotation(AnnotationMirror value, Void ignore) {
+ return AnnotationMirrors.equivalence().hash(value);
+ }
+
+ @SuppressWarnings("unchecked") // safe covariant cast
+ @Override
+ public Integer visitArray(List extends AnnotationValue> values, Void ignore) {
+ return AnnotationValues.equivalence()
+ .pairwise()
+ .hash((List) values);
+ }
+
+ @Override
+ public Integer visitType(TypeMirror value, Void ignore) {
+ return MoreTypes.equivalence().hash(value);
+ }
+
+ @Override
+ protected Integer defaultAction(Object value, Void ignored) {
+ return value.hashCode();
+ }
+ },
+ null);
+ }
+
+ @Override
+ public String toString() {
+ return "AnnotationValues.equivalence()";
}
};
@@ -319,7 +353,7 @@ private static final class ArrayVisitor
@Override
public ImmutableList defaultAction(Object o, Void unused) {
- throw new IllegalStateException("Expected an array, got instead: " + o);
+ throw new IllegalArgumentException("Expected an array, got instead: " + o);
}
@Override
@@ -483,6 +517,22 @@ public static ImmutableList getAnnotationValues(AnnotationValue
return ANNOTATION_VALUES_VISITOR.visit(value);
}
+ /**
+ * Returns a string representation of the given annotation value, suitable for inclusion in a Java
+ * source file as part of an annotation. For example, if {@code annotationValue} represents the
+ * string {@code unchecked} in the annotation {@code @SuppressWarnings("unchecked")}, this method
+ * will return the string {@code "unchecked"}, which you can then use as part of an annotation
+ * being generated.
+ *
+ * For all annotation values other than nested annotations, the returned string can also be
+ * used to initialize a variable of the appropriate type.
+ *
+ *
Fully qualified names are used for types in annotations, class literals, and enum constants,
+ * ensuring that the source form will compile without requiring additional imports.
+ */
+ public static String toString(AnnotationValue annotationValue) {
+ return AnnotationOutput.toString(annotationValue);
+ }
+
private AnnotationValues() {}
}
-
diff --git a/common/src/main/java/com/google/auto/common/BasicAnnotationProcessor.java b/common/src/main/java/com/google/auto/common/BasicAnnotationProcessor.java
index 31336cc35c..7b69d33271 100644
--- a/common/src/main/java/com/google/auto/common/BasicAnnotationProcessor.java
+++ b/common/src/main/java/com/google/auto/common/BasicAnnotationProcessor.java
@@ -17,19 +17,19 @@
import static com.google.auto.common.MoreElements.asExecutable;
import static com.google.auto.common.MoreElements.asPackage;
+import static com.google.auto.common.MoreElements.isAnnotationPresent;
+import static com.google.auto.common.MoreStreams.toImmutableMap;
+import static com.google.auto.common.MoreStreams.toImmutableSet;
import static com.google.auto.common.SuperficialValidation.validateElement;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Multimaps.filterKeys;
-import static java.util.stream.Collectors.collectingAndThen;
-import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toMap;
+import static java.util.Objects.requireNonNull;
import static javax.lang.model.element.ElementKind.PACKAGE;
import static javax.tools.Diagnostic.Kind.ERROR;
import com.google.common.base.Ascii;
-import com.google.common.base.Optional;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -42,6 +42,7 @@
import java.lang.annotation.Annotation;
import java.util.LinkedHashSet;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
@@ -49,13 +50,13 @@
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.ErrorType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleElementVisitor8;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* An abstract {@link Processor} implementation that defers processing of {@link Element}s to later
@@ -162,14 +163,14 @@ private ImmutableSet getSupportedAnnotationTypeElements() {
checkState(steps != null);
return steps.stream()
.flatMap(step -> getSupportedAnnotationTypeElements(step).stream())
- .collect(collectingAndThen(toList(), ImmutableSet::copyOf));
+ .collect(toImmutableSet());
}
private ImmutableSet getSupportedAnnotationTypeElements(Step step) {
return step.annotations().stream()
.map(elements::getTypeElement)
.filter(Objects::nonNull)
- .collect(collectingAndThen(toList(), ImmutableSet::copyOf));
+ .collect(toImmutableSet());
}
/**
@@ -179,9 +180,7 @@ private ImmutableSet getSupportedAnnotationTypeElements(Step step)
@Override
public final ImmutableSet getSupportedAnnotationTypes() {
checkState(steps != null);
- return steps.stream()
- .flatMap(step -> step.annotations().stream())
- .collect(collectingAndThen(toList(), ImmutableSet::copyOf));
+ return steps.stream().flatMap(step -> step.annotations().stream()).collect(toImmutableSet());
}
@Override
@@ -287,10 +286,7 @@ private ImmutableSetMultimap validElements(RoundEnvironmen
// Look at the elements we've found and the new elements from this round and validate them.
for (TypeElement annotationType : getSupportedAnnotationTypeElements()) {
- Set extends Element> roundElements =
- (annotationType == null)
- ? ImmutableSet.of()
- : roundEnv.getElementsAnnotatedWith(annotationType);
+ Set extends Element> roundElements = roundEnv.getElementsAnnotatedWith(annotationType);
ImmutableSet prevRoundElements = deferredElementsByAnnotation.get(annotationType);
for (Element element : Sets.union(roundElements, prevRoundElements)) {
ElementName elementName = ElementName.forAnnotatedElement(element);
@@ -353,10 +349,14 @@ private static void findAnnotatedElements(
}
// element.getEnclosedElements() does NOT return parameter elements
- if (element instanceof ExecutableElement) {
- for (Element parameterElement : asExecutable(element).getParameters()) {
- findAnnotatedElements(parameterElement, annotationTypes, annotatedElements);
- }
+ switch (element.getKind()) {
+ case METHOD:
+ case CONSTRUCTOR:
+ for (Element parameterElement : asExecutable(element).getParameters()) {
+ findAnnotatedElements(parameterElement, annotationTypes, annotatedElements);
+ }
+ break;
+ default: // do nothing
}
for (TypeElement annotationType : annotationTypes) {
if (isAnnotationPresent(element, annotationType)) {
@@ -365,12 +365,6 @@ private static void findAnnotatedElements(
}
}
- private static boolean isAnnotationPresent(Element element, TypeElement annotationType) {
- return element.getAnnotationMirrors().stream()
- .anyMatch(
- mirror -> MoreTypes.asTypeElement(mirror.getAnnotationType()).equals(annotationType));
- }
-
/**
* Returns the nearest enclosing {@link TypeElement} to the current element, throwing an {@link
* IllegalArgumentException} if the provided {@link Element} is a {@link PackageElement} or is
@@ -478,10 +472,9 @@ private static class ProcessingStepAsStep implements Step {
this.annotationsByName =
processingStep.annotations().stream()
.collect(
- collectingAndThen(
- toMap(
- Class::getCanonicalName, (Class extends Annotation> aClass) -> aClass),
- ImmutableMap::copyOf));
+ toImmutableMap(
+ c -> requireNonNull(c.getCanonicalName()),
+ (Class extends Annotation> aClass) -> aClass));
}
@Override
@@ -502,8 +495,12 @@ private ImmutableSetMultimap, Element> toClassKeyedM
elements
.asMap()
.forEach(
- (annotation, annotatedElements) ->
- builder.putAll(annotationsByName.get(annotation), annotatedElements));
+ (annotationName, annotatedElements) -> {
+ Class extends Annotation> annotation = annotationsByName.get(annotationName);
+ if (annotation != null) { // should not be null
+ builder.putAll(annotation, annotatedElements);
+ }
+ });
return builder.build();
}
}
@@ -537,6 +534,9 @@ private ElementName(Kind kind, Name name) {
* An {@link ElementName} for an annotated element. If {@code element} is a package, uses the
* fully qualified name of the package. If it's a type, uses its fully qualified name.
* Otherwise, uses the fully-qualified name of the nearest enclosing type.
+ *
+ * A package can be annotated if it has a {@code package-info.java} with annotations on the
+ * package declaration.
*/
static ElementName forAnnotatedElement(Element element) {
return element.getKind() == PACKAGE
@@ -550,18 +550,18 @@ String name() {
}
/**
- * The {@link Element} whose fully-qualified name is {@link #name()}. Absent if the relevant
+ * The {@link Element} whose fully-qualified name is {@link #name()}. Empty if the relevant
* method on {@link Elements} returns {@code null}.
*/
Optional extends Element> getElement(Elements elements) {
- return Optional.fromNullable(
+ return Optional.ofNullable(
kind == Kind.PACKAGE_NAME
? elements.getPackageElement(name)
: elements.getTypeElement(name));
}
@Override
- public boolean equals(Object object) {
+ public boolean equals(@Nullable Object object) {
if (!(object instanceof ElementName)) {
return false;
}
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 5e8e3541f0..dfbbaeef14 100644
--- a/common/src/main/java/com/google/auto/common/MoreElements.java
+++ b/common/src/main/java/com/google/auto/common/MoreElements.java
@@ -16,6 +16,7 @@
*/
package com.google.auto.common;
+import static com.google.auto.common.MoreStreams.toImmutableSet;
import static javax.lang.model.element.ElementKind.PACKAGE;
import static javax.lang.model.element.Modifier.STATIC;
@@ -212,29 +213,80 @@ public static ExecutableElement asExecutable(Element element) {
}
/**
- * 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(Element element,
- Class extends Annotation> annotationClass) {
+ public static boolean isAnnotationPresent(
+ Element element, Class extends Annotation> annotationClass) {
return getAnnotationMirror(element, annotationClass).isPresent();
}
+ /**
+ * 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
* annotation proxies.
*/
- public static Optional getAnnotationMirror(Element element,
- Class extends Annotation> annotationClass) {
- String annotationClassName = annotationClass.getCanonicalName();
+ public static Optional getAnnotationMirror(
+ Element element, Class extends Annotation> annotationClass) {
+ String name = annotationClass.getCanonicalName();
+ if (name == null) {
+ return Optional.absent();
+ }
+ return getAnnotationMirror(element, name);
+ }
+
+ /**
+ * 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 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 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);
}
}
@@ -435,9 +487,9 @@ private static ImmutableSet getAllMethods(
}
}
}
- Set methods = new LinkedHashSet(methodMap.values());
- methods.removeAll(overridden);
- return ImmutableSet.copyOf(methods);
+ return methodMap.values().stream()
+ .filter(m -> !overridden.contains(m))
+ .collect(toImmutableSet());
}
// Add to `methods` the static and instance methods from `type`. This means all methods from
diff --git a/common/src/main/java/com/google/auto/common/MoreStreams.java b/common/src/main/java/com/google/auto/common/MoreStreams.java
new file mode 100644
index 0000000000..934514ab47
--- /dev/null
+++ b/common/src/main/java/com/google/auto/common/MoreStreams.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.auto.common;
+
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.toList;
+
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+
+/**
+ * A utility class that provides Android compatible alternatives to Guava's streaming APIs.
+ *
+ * This is useful when the Android flavor of Guava somehow finds its way onto the processor
+ * classpath.
+ */
+public final class MoreStreams {
+
+ /** Returns a collector for an {@link ImmutableList}. */
+ public static Collector> toImmutableList() {
+ return collectingAndThen(toList(), ImmutableList::copyOf);
+ }
+
+ /** Returns a collector for an {@link ImmutableSet}. */
+ public static Collector> toImmutableSet() {
+ return collectingAndThen(toList(), ImmutableSet::copyOf);
+ }
+
+ /** Returns a collector for an {@link ImmutableMap}. */
+ public static Collector> toImmutableMap(
+ Function super T, K> keyMapper, Function super T, V> valueMapper) {
+ return Collectors.mapping(
+ value -> Maps.immutableEntry(keyMapper.apply(value), valueMapper.apply(value)),
+ Collector.of(
+ ImmutableMap::builder,
+ (ImmutableMap.Builder builder, Map.Entry entry) -> builder.put(entry),
+ (left, right) -> left.putAll(right.build()),
+ ImmutableMap.Builder::build));
+ }
+
+ /** Returns a collector for an {@link ImmutableBiMap}. */
+ public static Collector> toImmutableBiMap(
+ Function super T, K> keyMapper, Function super T, V> valueMapper) {
+ return Collectors.mapping(
+ value -> Maps.immutableEntry(keyMapper.apply(value), valueMapper.apply(value)),
+ Collector.of(
+ ImmutableBiMap::builder,
+ (ImmutableBiMap.Builder builder, Map.Entry entry) -> builder.put(entry),
+ (left, right) -> left.putAll(right.build()),
+ ImmutableBiMap.Builder::build));
+ }
+
+ private MoreStreams() {}
+}
diff --git a/common/src/main/java/com/google/auto/common/MoreTypes.java b/common/src/main/java/com/google/auto/common/MoreTypes.java
index af433aa06a..c8be62556b 100644
--- a/common/src/main/java/com/google/auto/common/MoreTypes.java
+++ b/common/src/main/java/com/google/auto/common/MoreTypes.java
@@ -25,7 +25,6 @@
import static javax.lang.model.type.TypeKind.WILDCARD;
import com.google.common.base.Equivalence;
-import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -55,6 +54,7 @@
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleTypeVisitor8;
import javax.lang.model.util.Types;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Utilities related to {@link TypeMirror} instances.
@@ -140,25 +140,45 @@ private static class ComparedElements {
}
@Override
- public boolean equals(Object o) {
- if (o instanceof ComparedElements) {
- ComparedElements that = (ComparedElements) o;
- int nArguments = aArguments.size();
- if (!this.a.equals(that.a)
- || !this.b.equals(that.b)
- || nArguments != bArguments.size()) {
- // The arguments must be the same size, but we check anyway.
+ public boolean equals(@Nullable Object o) {
+ if (!(o instanceof ComparedElements)) {
+ return false;
+ }
+ ComparedElements that = (ComparedElements) o;
+
+ int nArguments = this.aArguments.size();
+ if (nArguments != that.aArguments.size()) {
+ return false;
+ }
+ // The arguments must be the same size, but we check anyway.
+ if (nArguments != this.bArguments.size() || nArguments != that.bArguments.size()) {
+ return false;
+ }
+
+ if (!this.a.equals(that.a) || !this.b.equals(that.b)) {
+ return false;
+ }
+
+ /*
+ * The purpose here is just to avoid the infinite recursion that we would otherwise have
+ * if Enum> is compared against itself, for example. If we are able to
+ * see that the inner Enum is the same object as the outer one then we don't need a
+ * recursive call to compare the "a" Enum against the "b" Enum. The same-object check
+ * may not be completely justified, but it relies on the practical assumption that the
+ * compiler is not going to conjure up an infinite regress of objects to represent this
+ * recursive type. Other comparison methods like comparing their toString() are expensive
+ * and not warranted.
+ */
+ for (int i = 0; i < nArguments; i++) {
+ if (this.aArguments.get(i) != that.aArguments.get(i)) {
return false;
}
- for (int i = 0; i < nArguments; i++) {
- if (aArguments.get(i) != bArguments.get(i)) {
- return false;
- }
+ if (this.bArguments.get(i) != that.bArguments.get(i)) {
+ return false;
}
- return true;
- } else {
- return false;
}
+
+ return true;
}
@Override
@@ -299,7 +319,14 @@ private Set visitingSetPlus(
}
@SuppressWarnings("TypeEquals")
- private static boolean equal(TypeMirror a, TypeMirror b, Set visiting) {
+ private static boolean equal(
+ @Nullable TypeMirror a, @Nullable TypeMirror b, Set visiting) {
+ if (a == b) {
+ return true;
+ }
+ if (a == null || b == null) {
+ return false;
+ }
// TypeMirror.equals is not guaranteed to return true for types that are equal, but we can
// assume that if it does return true then the types are equal. This check also avoids getting
// stuck in infinite recursion when Eclipse decrees that the upper bound of the second K in
@@ -307,13 +334,15 @@ private static boolean equal(TypeMirror a, TypeMirror b, Set v
// The javac implementation of ExecutableType, at least in some versions, does not take thrown
// exceptions into account in its equals implementation, so avoid this optimization for
// ExecutableType.
- if (Objects.equal(a, b) && !(a instanceof ExecutableType)) {
+ @SuppressWarnings("TypesEquals")
+ boolean equal = a.equals(b);
+ if (equal && a.getKind() != TypeKind.EXECUTABLE) {
return true;
}
EqualVisitorParam p = new EqualVisitorParam();
p.type = b;
p.visiting = visiting;
- return (a == b) || (a != null && b != null && a.accept(EqualVisitor.INSTANCE, p));
+ return a.accept(EqualVisitor.INSTANCE, p);
}
/**
@@ -323,7 +352,7 @@ private static boolean equal(TypeMirror a, TypeMirror b, Set v
* this bug whereby
* the Eclipse compiler returns a value for static classes that is not NoType.
*/
- private static TypeMirror enclosingType(DeclaredType t) {
+ private static @Nullable TypeMirror enclosingType(DeclaredType t) {
TypeMirror enclosing = t.getEnclosingType();
if (enclosing.getKind().equals(TypeKind.NONE)
|| t.asElement().getModifiers().contains(Modifier.STATIC)) {
@@ -436,7 +465,7 @@ public Integer visitWildcard(WildcardType t, Set visiting) {
public Integer visitUnknown(TypeMirror t, Set visiting) {
throw new UnsupportedOperationException();
}
- };
+ }
private static int hashList(List extends TypeMirror> mirrors, Set visiting) {
int result = HASH_SEED;
@@ -463,17 +492,17 @@ public static ImmutableSet referencedTypes(TypeMirror type) {
}
private static final class ReferencedTypes
- extends SimpleTypeVisitor8> {
+ extends SimpleTypeVisitor8<@Nullable Void, ImmutableSet.Builder> {
private static final ReferencedTypes INSTANCE = new ReferencedTypes();
@Override
- public Void visitArray(ArrayType t, ImmutableSet.Builder p) {
+ public @Nullable Void visitArray(ArrayType t, ImmutableSet.Builder p) {
t.getComponentType().accept(this, p);
return null;
}
@Override
- public Void visitDeclared(DeclaredType t, ImmutableSet.Builder p) {
+ public @Nullable Void visitDeclared(DeclaredType t, ImmutableSet.Builder p) {
p.add(MoreElements.asType(t.asElement()));
for (TypeMirror typeArgument : t.getTypeArguments()) {
typeArgument.accept(this, p);
@@ -482,14 +511,14 @@ public Void visitDeclared(DeclaredType t, ImmutableSet.Builder p) {
}
@Override
- public Void visitTypeVariable(TypeVariable t, ImmutableSet.Builder p) {
+ public @Nullable Void visitTypeVariable(TypeVariable t, ImmutableSet.Builder p) {
t.getLowerBound().accept(this, p);
t.getUpperBound().accept(this, p);
return null;
}
@Override
- public Void visitWildcard(WildcardType t, ImmutableSet.Builder p) {
+ public @Nullable Void visitWildcard(WildcardType t, ImmutableSet.Builder p) {
TypeMirror extendsBound = t.getExtendsBound();
if (extendsBound != null) {
extendsBound.accept(this, p);
@@ -537,7 +566,8 @@ public Element visitError(ErrorType t, Void p) {
public Element visitTypeVariable(TypeVariable t, Void p) {
return t.asElement();
}
- };
+ }
+ ;
// TODO(gak): consider removing these two methods as they're pretty trivial now
public static TypeElement asTypeElement(TypeMirror mirror) {
@@ -882,10 +912,10 @@ public Boolean visitDeclared(DeclaredType type, Void ignored) {
* is {@link Object}.
*/
// TODO(bcorso): Remove unused parameter Elements?
- public static Optional nonObjectSuperclass(Types types, Elements elements,
- DeclaredType type) {
+ public static Optional nonObjectSuperclass(
+ Types types, Elements elements, DeclaredType type) {
checkNotNull(types);
- checkNotNull(elements); // This is no longer used, but here to avoid changing the API.
+ checkNotNull(elements); // This is no longer used, but here to avoid changing the API.
checkNotNull(type);
TypeMirror superclassType = asTypeElement(type).getSuperclass();
@@ -893,7 +923,7 @@ public static Optional nonObjectSuperclass(Types types, Elements e
return Optional.absent();
}
- DeclaredType superclass = asDeclared(superclassType);
+ DeclaredType superclass = asDeclared(superclassType);
if (isObjectType(superclass)) {
return Optional.absent();
}
@@ -920,8 +950,8 @@ private static boolean isObjectType(DeclaredType type) {
* {@code container} of type {@code Set}, and a variable corresponding to the {@code E e}
* parameter in the {@code Set.add(E e)} method, this will return a TypeMirror for {@code String}.
*/
- public static TypeMirror asMemberOf(Types types, DeclaredType container,
- VariableElement variable) {
+ public static TypeMirror asMemberOf(
+ Types types, DeclaredType container, VariableElement variable) {
if (variable.getKind().equals(ElementKind.PARAMETER)) {
ExecutableElement methodOrConstructor =
MoreElements.asExecutable(variable.getEnclosingElement());
@@ -1013,7 +1043,7 @@ private static boolean uncheckedTypeArgument(TypeMirror arg) {
}
return true;
}
-
+
private static boolean isJavaLangObject(TypeMirror type) {
if (type.getKind() != TypeKind.DECLARED) {
return false;
diff --git a/common/src/main/java/com/google/auto/common/Overrides.java b/common/src/main/java/com/google/auto/common/Overrides.java
index 19a4586223..46d765bcdd 100644
--- a/common/src/main/java/com/google/auto/common/Overrides.java
+++ b/common/src/main/java/com/google/auto/common/Overrides.java
@@ -15,6 +15,8 @@
*/
package com.google.auto.common;
+import static java.util.stream.Collectors.toList;
+
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
@@ -23,6 +25,7 @@
import java.util.List;
import java.util.Map;
import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
@@ -38,6 +41,7 @@
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleTypeVisitor8;
import javax.lang.model.util.Types;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Determines if one method overrides another. This class defines two ways of doing that:
@@ -114,12 +118,11 @@ public boolean overrides(
// can't be overridden.
return false;
}
- TypeElement overriddenType;
- if (!(overridden.getEnclosingElement() instanceof TypeElement)) {
+ if (!MoreElements.isType(overridden.getEnclosingElement())) {
return false;
// We don't know how this could happen but we avoid blowing up if it does.
}
- overriddenType = MoreElements.asType(overridden.getEnclosingElement());
+ TypeElement overriddenType = MoreElements.asType(overridden.getEnclosingElement());
// We erase the types before checking subtypes, because the TypeMirror we get for List is
// not a subtype of the one we get for Collection since the two E instances are not the
// same. For the purposes of overriding, type parameters in the containing type should not
@@ -141,7 +144,8 @@ public boolean overrides(
// the enclosing elements rather than the methods themselves for the reason described
// at the start of the method.
ExecutableElement inherited = methodFromSuperclasses(in, overridden);
- return !overridden.getEnclosingElement().equals(inherited.getEnclosingElement());
+ return inherited != null
+ && !overridden.getEnclosingElement().equals(inherited.getEnclosingElement());
} else if (overriddenType.getKind().isInterface()) {
// ...overrides from C another method mI declared in interface I. We've already checked
// the conditions (assuming that the only alternative to mI being abstract or default is
@@ -157,7 +161,8 @@ public boolean overrides(
// to methodFromSuperclasses above.
if (overrider.getModifiers().contains(Modifier.ABSTRACT)) {
ExecutableElement inherited = methodFromSuperinterfaces(in, overridden);
- return !overridden.getEnclosingElement().equals(inherited.getEnclosingElement());
+ return inherited != null
+ && !overridden.getEnclosingElement().equals(inherited.getEnclosingElement());
} else {
return true;
}
@@ -166,9 +171,14 @@ public boolean overrides(
return false;
}
} else {
- return in.getKind().isInterface();
- // Method mI in or inherited by interface I (JLS 9.4.1.1). We've already checked everything.
+ // Method mI in or inherited by interface I (JLS 9.4.1.1). We've already checked everything,
+ // except that `overrider` must also be in a subinterface of `overridden`.
// If this is not an interface then we don't know what it is so we say no.
+ TypeElement overriderType = MoreElements.asType(overrider.getEnclosingElement());
+ return in.getKind().isInterface()
+ && typeUtils.isSubtype(
+ typeUtils.erasure(overriderType.asType()),
+ typeUtils.erasure(overriddenType.asType()));
}
}
@@ -215,6 +225,7 @@ private boolean isSubsignature(
* implements List}. The parameter types are erased since the purpose of this method is to
* determine whether two methods are candidates for one to override the other.
*/
+ @Nullable
ImmutableList erasedParameterTypes(ExecutableElement method, TypeElement in) {
if (method.getParameters().isEmpty()) {
return ImmutableList.of();
@@ -241,6 +252,7 @@ private class TypeSubstVisitor extends SimpleTypeVisitor8 {
*/
private final Map typeBindings = Maps.newLinkedHashMap();
+ @Nullable
ImmutableList erasedParameterTypes(ExecutableElement method, TypeElement in) {
if (method.getEnclosingElement().equals(in)) {
ImmutableList.Builder params = ImmutableList.builder();
@@ -261,6 +273,10 @@ ImmutableList erasedParameterTypes(ExecutableElement method, TypeEle
TypeElement element = MoreElements.asType(declared.asElement());
List extends TypeMirror> actuals = declared.getTypeArguments();
List extends TypeParameterElement> formals = element.getTypeParameters();
+ if (actuals.isEmpty()) {
+ // Either the formal type arguments are also empty or `declared` is raw.
+ actuals = formals.stream().map(t -> t.getBounds().get(0)).collect(toList());
+ }
Verify.verify(actuals.size() == formals.size());
for (int i = 0; i < actuals.size(); i++) {
typeBindings.put(formals.get(i), actuals.get(i));
@@ -280,8 +296,8 @@ protected TypeMirror defaultAction(TypeMirror e, Void p) {
@Override
public TypeMirror visitTypeVariable(TypeVariable t, Void p) {
- Element element = typeUtils.asElement(t);
- if (element instanceof TypeParameterElement) {
+ Element element = t.asElement();
+ if (element.getKind() == ElementKind.TYPE_PARAMETER) {
TypeParameterElement e = (TypeParameterElement) element;
if (typeBindings.containsKey(e)) {
return visit(typeBindings.get(e));
@@ -315,7 +331,7 @@ public TypeMirror visitArray(ArrayType t, Void p) {
* or the nearest override in a superclass of the given type, or null if the method is not
* found in the given type or any of its superclasses.
*/
- ExecutableElement methodFromSuperclasses(TypeElement in, ExecutableElement method) {
+ @Nullable ExecutableElement methodFromSuperclasses(TypeElement in, ExecutableElement method) {
for (TypeElement t = in; t != null; t = superclass(t)) {
ExecutableElement tMethod = methodInType(t, method);
if (tMethod != null) {
@@ -330,6 +346,7 @@ ExecutableElement methodFromSuperclasses(TypeElement in, ExecutableElement metho
* itself, or the nearest override in a superinterface of the given type, or null if the method
* is not found in the given type or any of its transitive superinterfaces.
*/
+ @Nullable
ExecutableElement methodFromSuperinterfaces(TypeElement in, ExecutableElement method) {
TypeElement methodContainer = MoreElements.asType(method.getEnclosingElement());
Preconditions.checkArgument(methodContainer.getKind().isInterface());
@@ -366,7 +383,7 @@ ExecutableElement methodFromSuperinterfaces(TypeElement in, ExecutableElement me
* Returns the method from within the given type that has the same erased signature as the given
* method, or null if there is no such method.
*/
- private ExecutableElement methodInType(TypeElement type, ExecutableElement method) {
+ private @Nullable ExecutableElement methodInType(TypeElement type, ExecutableElement method) {
int nParams = method.getParameters().size();
List params = erasedParameterTypes(method, type);
if (params == null) {
@@ -388,7 +405,7 @@ private ExecutableElement methodInType(TypeElement type, ExecutableElement metho
return null;
}
- private TypeElement superclass(TypeElement type) {
+ private @Nullable TypeElement superclass(TypeElement type) {
TypeMirror sup = type.getSuperclass();
if (sup.getKind() == TypeKind.DECLARED) {
return MoreElements.asType(typeUtils.asElement(sup));
diff --git a/common/src/main/java/com/google/auto/common/SimpleAnnotationMirror.java b/common/src/main/java/com/google/auto/common/SimpleAnnotationMirror.java
index 7d508e32ae..7952eb3748 100644
--- a/common/src/main/java/com/google/auto/common/SimpleAnnotationMirror.java
+++ b/common/src/main/java/com/google/auto/common/SimpleAnnotationMirror.java
@@ -16,8 +16,8 @@
package com.google.auto.common;
+import static com.google.auto.common.MoreStreams.toImmutableMap;
import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static javax.lang.model.util.ElementFilter.methodsIn;
import com.google.common.base.Joiner;
@@ -32,6 +32,7 @@
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A simple implementation of the {@link AnnotationMirror} interface.
@@ -65,7 +66,7 @@ private SimpleAnnotationMirror(
missingMembers.add(memberName);
}
}
-
+
checkArgument(
unusedValues.isEmpty(),
"namedValues has entries for members that are not in %s: %s",
@@ -77,8 +78,7 @@ private SimpleAnnotationMirror(
this.annotationType = annotationType;
this.namedValues = ImmutableMap.copyOf(namedValues);
this.elementValues =
- methodsIn(annotationType.getEnclosedElements())
- .stream()
+ methodsIn(annotationType.getEnclosedElements()).stream()
.collect(toImmutableMap(e -> e, e -> values.get(e.getSimpleName().toString())));
}
@@ -123,7 +123,7 @@ public String toString() {
}
@Override
- public boolean equals(Object other) {
+ public boolean equals(@Nullable Object other) {
return other instanceof AnnotationMirror
&& AnnotationMirrors.equivalence().equivalent(this, (AnnotationMirror) other);
}
diff --git a/common/src/main/java/com/google/auto/common/SuperficialValidation.java b/common/src/main/java/com/google/auto/common/SuperficialValidation.java
index 5ef4dbf2b3..614e26265f 100644
--- a/common/src/main/java/com/google/auto/common/SuperficialValidation.java
+++ b/common/src/main/java/com/google/auto/common/SuperficialValidation.java
@@ -57,23 +57,27 @@ public static boolean validateElements(Iterable extends Element> elements) {
private static final ElementVisitor ELEMENT_VALIDATING_VISITOR =
new AbstractElementVisitor8() {
- @Override public Boolean visitPackage(PackageElement e, Void p) {
+ @Override
+ public Boolean visitPackage(PackageElement e, Void p) {
// don't validate enclosed elements because it will return types in the package
return validateAnnotations(e.getAnnotationMirrors());
}
- @Override public Boolean visitType(TypeElement e, Void p) {
+ @Override
+ public Boolean visitType(TypeElement e, Void p) {
return isValidBaseElement(e)
&& validateElements(e.getTypeParameters())
&& validateTypes(e.getInterfaces())
&& validateType(e.getSuperclass());
}
- @Override public Boolean visitVariable(VariableElement e, Void p) {
+ @Override
+ public Boolean visitVariable(VariableElement e, Void p) {
return isValidBaseElement(e);
}
- @Override public Boolean visitExecutable(ExecutableElement e, Void p) {
+ @Override
+ public Boolean visitExecutable(ExecutableElement e, Void p) {
AnnotationValue defaultValue = e.getDefaultValue();
return isValidBaseElement(e)
&& (defaultValue == null || validateAnnotationValue(defaultValue, e.getReturnType()))
@@ -83,12 +87,13 @@ && validateElements(e.getTypeParameters())
&& validateElements(e.getParameters());
}
- @Override public Boolean visitTypeParameter(TypeParameterElement e, Void p) {
- return isValidBaseElement(e)
- && validateTypes(e.getBounds());
+ @Override
+ public Boolean visitTypeParameter(TypeParameterElement e, Void p) {
+ return isValidBaseElement(e) && validateTypes(e.getBounds());
}
- @Override public Boolean visitUnknown(Element e, Void p) {
+ @Override
+ public Boolean visitUnknown(Element e, Void p) {
// just assume that unknown elements are OK
return true;
}
@@ -206,16 +211,19 @@ private static boolean validateAnnotationValues(
private static final AnnotationValueVisitor VALUE_VALIDATING_VISITOR =
new SimpleAnnotationValueVisitor8() {
- @Override protected Boolean defaultAction(Object o, TypeMirror expectedType) {
+ @Override
+ protected Boolean defaultAction(Object o, TypeMirror expectedType) {
return MoreTypes.isTypeOf(o.getClass(), expectedType);
}
- @Override public Boolean visitUnknown(AnnotationValue av, TypeMirror expectedType) {
+ @Override
+ public Boolean visitUnknown(AnnotationValue av, TypeMirror expectedType) {
// just take the default action for the unknown
return defaultAction(av, expectedType);
}
- @Override public Boolean visitAnnotation(AnnotationMirror a, TypeMirror expectedType) {
+ @Override
+ public Boolean visitAnnotation(AnnotationMirror a, TypeMirror expectedType) {
return MoreTypes.equivalence().equivalent(a.getAnnotationType(), expectedType)
&& validateAnnotation(a);
}
@@ -235,7 +243,8 @@ public Boolean visitEnumConstant(VariableElement enumConstant, TypeMirror expect
&& validateElement(enumConstant);
}
- @Override public Boolean visitType(TypeMirror type, TypeMirror ignored) {
+ @Override
+ public Boolean visitType(TypeMirror type, TypeMirror ignored) {
// We could check assignability here, but would require a Types instance. Since this
// isn't really the sort of thing that shows up in a bad AST from upstream compilation
// we ignore the expected type and just validate the type. It might be wrong, but
@@ -243,35 +252,43 @@ public Boolean visitEnumConstant(VariableElement enumConstant, TypeMirror expect
return validateType(type);
}
- @Override public Boolean visitBoolean(boolean b, TypeMirror expectedType) {
+ @Override
+ public Boolean visitBoolean(boolean b, TypeMirror expectedType) {
return MoreTypes.isTypeOf(Boolean.TYPE, expectedType);
}
- @Override public Boolean visitByte(byte b, TypeMirror expectedType) {
+ @Override
+ public Boolean visitByte(byte b, TypeMirror expectedType) {
return MoreTypes.isTypeOf(Byte.TYPE, expectedType);
}
- @Override public Boolean visitChar(char c, TypeMirror expectedType) {
+ @Override
+ public Boolean visitChar(char c, TypeMirror expectedType) {
return MoreTypes.isTypeOf(Character.TYPE, expectedType);
}
- @Override public Boolean visitDouble(double d, TypeMirror expectedType) {
+ @Override
+ public Boolean visitDouble(double d, TypeMirror expectedType) {
return MoreTypes.isTypeOf(Double.TYPE, expectedType);
}
- @Override public Boolean visitFloat(float f, TypeMirror expectedType) {
+ @Override
+ public Boolean visitFloat(float f, TypeMirror expectedType) {
return MoreTypes.isTypeOf(Float.TYPE, expectedType);
}
- @Override public Boolean visitInt(int i, TypeMirror expectedType) {
+ @Override
+ public Boolean visitInt(int i, TypeMirror expectedType) {
return MoreTypes.isTypeOf(Integer.TYPE, expectedType);
}
- @Override public Boolean visitLong(long l, TypeMirror expectedType) {
+ @Override
+ public Boolean visitLong(long l, TypeMirror expectedType) {
return MoreTypes.isTypeOf(Long.TYPE, expectedType);
}
- @Override public Boolean visitShort(short s, TypeMirror expectedType) {
+ @Override
+ public Boolean visitShort(short s, TypeMirror expectedType) {
return MoreTypes.isTypeOf(Short.TYPE, expectedType);
}
};
diff --git a/common/src/main/java/com/google/auto/common/Visibility.java b/common/src/main/java/com/google/auto/common/Visibility.java
index f82fdd5933..db15f8bd43 100644
--- a/common/src/main/java/com/google/auto/common/Visibility.java
+++ b/common/src/main/java/com/google/auto/common/Visibility.java
@@ -24,6 +24,7 @@
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents the visibility of a given {@link Element}: {@code public}, {@code protected},
@@ -41,7 +42,7 @@ public enum Visibility {
// TODO(ronshapiro): remove this and reference ElementKind.MODULE directly once we start building
// with -source 9
- private static final ElementKind MODULE =
+ private static final @Nullable ElementKind MODULE =
Enums.getIfPresent(ElementKind.class, "MODULE").orNull();
/**
@@ -76,8 +77,9 @@ public static Visibility effectiveVisibilityOfElement(Element element) {
Visibility effectiveVisibility = PUBLIC;
Element currentElement = element;
while (currentElement != null) {
- effectiveVisibility =
- Ordering.natural().min(effectiveVisibility, ofElement(currentElement));
+ // NOTE: We don't use Guava's Comparators.min() because that requires Guava 30, which would
+ // make this library unusable in annotation processors using Bazel < 5.0.
+ effectiveVisibility = Ordering.natural().min(effectiveVisibility, ofElement(currentElement));
currentElement = currentElement.getEnclosingElement();
}
return effectiveVisibility;
diff --git a/common/src/main/java/com/google/auto/common/package-info.java b/common/src/main/java/com/google/auto/common/package-info.java
new file mode 100644
index 0000000000..22b0c45ac8
--- /dev/null
+++ b/common/src/main/java/com/google/auto/common/package-info.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.auto.common;
+
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 f63ee031d2..83494a8467 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.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;
@@ -46,110 +51,134 @@ public class AnnotationMirrorsTest {
private Elements elements;
- @Before public void setUp() {
+ @Before
+ public void setUp() {
this.elements = compilationRule.getElements();
}
@interface SimpleAnnotation {}
- @SimpleAnnotation class SimplyAnnotated {}
- @SimpleAnnotation class AlsoSimplyAnnotated {}
+ @SimpleAnnotation
+ static class SimplyAnnotated {}
+
+ @SimpleAnnotation
+ static class AlsoSimplyAnnotated {}
enum SimpleEnum {
- BLAH, FOO
+ BLAH,
+ FOO
}
@interface Outer {
SimpleEnum value();
}
- @Outer(BLAH) static class TestClassBlah {}
- @Outer(BLAH) static class TestClassBlah2 {}
- @Outer(FOO) static class TestClassFoo {}
+ @Outer(BLAH)
+ static class TestClassBlah {}
+
+ @Outer(BLAH)
+ static class TestClassBlah2 {}
+
+ @Outer(FOO)
+ static class TestClassFoo {}
@interface DefaultingOuter {
SimpleEnum value() default SimpleEnum.BLAH;
}
- @DefaultingOuter class TestWithDefaultingOuterDefault {}
- @DefaultingOuter(BLAH) class TestWithDefaultingOuterBlah {}
- @DefaultingOuter(FOO) class TestWithDefaultingOuterFoo {}
+ @DefaultingOuter
+ static class TestWithDefaultingOuterDefault {}
+
+ @DefaultingOuter(BLAH)
+ static class TestWithDefaultingOuterBlah {}
+
+ @DefaultingOuter(FOO)
+ static class TestWithDefaultingOuterFoo {}
@interface AnnotatedOuter {
DefaultingOuter value();
}
- @AnnotatedOuter(@DefaultingOuter) class TestDefaultNestedAnnotated {}
- @AnnotatedOuter(@DefaultingOuter(BLAH)) class TestBlahNestedAnnotated {}
- @AnnotatedOuter(@DefaultingOuter(FOO)) class TestFooNestedAnnotated {}
+ @AnnotatedOuter(@DefaultingOuter)
+ static class TestDefaultNestedAnnotated {}
+
+ @AnnotatedOuter(@DefaultingOuter(BLAH))
+ static class TestBlahNestedAnnotated {}
+
+ @AnnotatedOuter(@DefaultingOuter(FOO))
+ static class TestFooNestedAnnotated {}
@interface OuterWithValueArray {
DefaultingOuter[] value() default {};
}
- @OuterWithValueArray class TestValueArrayWithDefault {}
- @OuterWithValueArray({}) class TestValueArrayWithEmpty {}
+ @OuterWithValueArray
+ static class TestValueArrayWithDefault {}
+
+ @OuterWithValueArray({})
+ static class TestValueArrayWithEmpty {}
+
+ @OuterWithValueArray({@DefaultingOuter})
+ static class TestValueArrayWithOneDefault {}
- @OuterWithValueArray({@DefaultingOuter}) class TestValueArrayWithOneDefault {}
- @OuterWithValueArray(@DefaultingOuter(BLAH)) class TestValueArrayWithOneBlah {}
- @OuterWithValueArray(@DefaultingOuter(FOO)) class TestValueArrayWithOneFoo {}
+ @OuterWithValueArray(@DefaultingOuter(BLAH))
+ static class TestValueArrayWithOneBlah {}
+
+ @OuterWithValueArray(@DefaultingOuter(FOO))
+ static class TestValueArrayWithOneFoo {}
@OuterWithValueArray({@DefaultingOuter(FOO), @DefaultingOuter})
class TestValueArrayWithFooAndDefaultBlah {}
+
@OuterWithValueArray({@DefaultingOuter(FOO), @DefaultingOuter(BLAH)})
class TestValueArrayWithFooBlah {}
+
@OuterWithValueArray({@DefaultingOuter(FOO), @DefaultingOuter(BLAH)})
class TestValueArrayWithFooBlah2 {} // Different instances than on TestValueArrayWithFooBlah.
+
@OuterWithValueArray({@DefaultingOuter(BLAH), @DefaultingOuter(FOO)})
class TestValueArrayWithBlahFoo {}
- @Test public void testEquivalences() {
+ @Test
+ public void testEquivalences() {
EquivalenceTester tester =
EquivalenceTester.of(AnnotationMirrors.equivalence());
tester.addEquivalenceGroup(
- annotationOn(SimplyAnnotated.class),
- annotationOn(AlsoSimplyAnnotated.class));
+ annotationOn(SimplyAnnotated.class), annotationOn(AlsoSimplyAnnotated.class));
tester.addEquivalenceGroup(
- annotationOn(TestClassBlah.class),
- annotationOn(TestClassBlah2.class));
+ annotationOn(TestClassBlah.class), annotationOn(TestClassBlah2.class));
- tester.addEquivalenceGroup(
- annotationOn(TestClassFoo.class));
+ tester.addEquivalenceGroup(annotationOn(TestClassFoo.class));
tester.addEquivalenceGroup(
annotationOn(TestWithDefaultingOuterDefault.class),
annotationOn(TestWithDefaultingOuterBlah.class));
- tester.addEquivalenceGroup(
- annotationOn(TestWithDefaultingOuterFoo.class));
+ tester.addEquivalenceGroup(annotationOn(TestWithDefaultingOuterFoo.class));
tester.addEquivalenceGroup(
annotationOn(TestDefaultNestedAnnotated.class),
annotationOn(TestBlahNestedAnnotated.class));
- tester.addEquivalenceGroup(
- annotationOn(TestFooNestedAnnotated.class));
+ tester.addEquivalenceGroup(annotationOn(TestFooNestedAnnotated.class));
tester.addEquivalenceGroup(
- annotationOn(TestValueArrayWithDefault.class),
- annotationOn(TestValueArrayWithEmpty.class));
+ annotationOn(TestValueArrayWithDefault.class), annotationOn(TestValueArrayWithEmpty.class));
tester.addEquivalenceGroup(
annotationOn(TestValueArrayWithOneDefault.class),
annotationOn(TestValueArrayWithOneBlah.class));
- tester.addEquivalenceGroup(
- annotationOn(TestValueArrayWithOneFoo.class));
+ tester.addEquivalenceGroup(annotationOn(TestValueArrayWithOneFoo.class));
tester.addEquivalenceGroup(
annotationOn(TestValueArrayWithFooAndDefaultBlah.class),
annotationOn(TestValueArrayWithFooBlah.class),
annotationOn(TestValueArrayWithFooBlah2.class));
- tester.addEquivalenceGroup(
- annotationOn(TestValueArrayWithBlahFoo.class));
+ tester.addEquivalenceGroup(annotationOn(TestValueArrayWithBlahFoo.class));
tester.test();
}
@@ -158,44 +187,61 @@ class TestValueArrayWithBlahFoo {}
String value() default "default";
}
- @Stringy class StringyUnset {}
- @Stringy("foo") class StringySet {}
+ @Stringy
+ static class StringyUnset {}
+
+ @Stringy("foo")
+ static class StringySet {}
- @Test public void testGetDefaultValuesUnset() {
+ @Test
+ public void testGetDefaultValuesUnset() {
assertThat(annotationOn(StringyUnset.class).getElementValues()).isEmpty();
- Iterable values = AnnotationMirrors.getAnnotationValuesWithDefaults(
- annotationOn(StringyUnset.class)).values();
- String value = getOnlyElement(values).accept(new SimpleAnnotationValueVisitor6() {
- @Override public String visitString(String value, Void ignored) {
- return value;
- }
- }, null);
+ Iterable values =
+ AnnotationMirrors.getAnnotationValuesWithDefaults(annotationOn(StringyUnset.class))
+ .values();
+ String value =
+ getOnlyElement(values)
+ .accept(
+ new SimpleAnnotationValueVisitor6() {
+ @Override
+ public String visitString(String value, Void ignored) {
+ return value;
+ }
+ },
+ null);
assertThat(value).isEqualTo("default");
}
- @Test public void testGetDefaultValuesSet() {
- Iterable values = AnnotationMirrors.getAnnotationValuesWithDefaults(
- annotationOn(StringySet.class)).values();
- String value = getOnlyElement(values).accept(new SimpleAnnotationValueVisitor6() {
- @Override public String visitString(String value, Void ignored) {
- return value;
- }
- }, null);
+ @Test
+ public void testGetDefaultValuesSet() {
+ Iterable values =
+ AnnotationMirrors.getAnnotationValuesWithDefaults(annotationOn(StringySet.class)).values();
+ String value =
+ getOnlyElement(values)
+ .accept(
+ new SimpleAnnotationValueVisitor6() {
+ @Override
+ public String visitString(String value, Void ignored) {
+ return value;
+ }
+ },
+ null);
assertThat(value).isEqualTo("foo");
}
- @Test public void testGetValueEntry() {
+ @Test
+ public void testGetValueEntry() {
Map.Entry elementValue =
- AnnotationMirrors.getAnnotationElementAndValue(
- annotationOn(TestClassBlah.class), "value");
+ AnnotationMirrors.getAnnotationElementAndValue(annotationOn(TestClassBlah.class), "value");
assertThat(elementValue.getKey().getSimpleName().toString()).isEqualTo("value");
assertThat(elementValue.getValue().getValue()).isInstanceOf(VariableElement.class);
- AnnotationValue value = AnnotationMirrors.getAnnotationValue(
- annotationOn(TestClassBlah.class), "value");
+ AnnotationValue value =
+ AnnotationMirrors.getAnnotationValue(annotationOn(TestClassBlah.class), "value");
assertThat(value.getValue()).isInstanceOf(VariableElement.class);
}
- @Test public void testGetValueEntryFailure() {
+ @Test
+ public void testGetValueEntryFailure() {
try {
AnnotationMirrors.getAnnotationValue(annotationOn(TestClassBlah.class), "a");
} catch (IllegalArgumentException e) {
@@ -211,4 +257,120 @@ class TestValueArrayWithBlahFoo {}
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));
+ }
+
+ @Test
+ public void toSourceString() {
+ assertThat(AnnotationMirrors.toString(annotationOn(AlsoSimplyAnnotated.class)))
+ .isEqualTo("@com.google.auto.common.AnnotationMirrorsTest.SimpleAnnotation");
+ assertThat(AnnotationMirrors.toString(annotationOn(SimplyAnnotated.class)))
+ .isEqualTo("@com.google.auto.common.AnnotationMirrorsTest.SimpleAnnotation");
+ assertThat(AnnotationMirrors.toString(annotationOn(StringySet.class)))
+ .isEqualTo("@com.google.auto.common.AnnotationMirrorsTest.Stringy(\"foo\")");
+ assertThat(AnnotationMirrors.toString(annotationOn(StringyUnset.class)))
+ .isEqualTo("@com.google.auto.common.AnnotationMirrorsTest.Stringy");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestBlahNestedAnnotated.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.AnnotatedOuter(@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.BLAH))");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestClassBlah2.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.Outer(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.BLAH)");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestClassBlah.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.Outer(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.BLAH)");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestClassFoo.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.Outer(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.FOO)");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestDefaultNestedAnnotated.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.AnnotatedOuter(@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter)");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestFooNestedAnnotated.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.AnnotatedOuter(@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.FOO))");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestValueArrayWithBlahFoo.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.OuterWithValueArray({@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.BLAH),"
+ + " @com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.FOO)})");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestValueArrayWithDefault.class)))
+ .isEqualTo("@com.google.auto.common.AnnotationMirrorsTest.OuterWithValueArray");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestValueArrayWithEmpty.class)))
+ .isEqualTo("@com.google.auto.common.AnnotationMirrorsTest.OuterWithValueArray({})");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestValueArrayWithFooAndDefaultBlah.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.OuterWithValueArray({@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.FOO),"
+ + " @com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter})");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestValueArrayWithFooBlah2.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.OuterWithValueArray({@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.FOO),"
+ + " @com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.BLAH)})");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestValueArrayWithFooBlah.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.OuterWithValueArray({@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.FOO),"
+ + " @com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.BLAH)})");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestValueArrayWithOneBlah.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.OuterWithValueArray(@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.BLAH))");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestValueArrayWithOneDefault.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.OuterWithValueArray(@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter)");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestValueArrayWithOneFoo.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.OuterWithValueArray(@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.FOO))");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestWithDefaultingOuterBlah.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.BLAH)");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestWithDefaultingOuterDefault.class)))
+ .isEqualTo("@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter");
+ assertThat(AnnotationMirrors.toString(annotationOn(TestWithDefaultingOuterFoo.class)))
+ .isEqualTo(
+ "@com.google.auto.common.AnnotationMirrorsTest.DefaultingOuter(com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.FOO)");
+ }
+
+ 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/AnnotationValuesTest.java b/common/src/test/java/com/google/auto/common/AnnotationValuesTest.java
index 825c85afb1..c6997b2aca 100644
--- a/common/src/test/java/com/google/auto/common/AnnotationValuesTest.java
+++ b/common/src/test/java/com/google/auto/common/AnnotationValuesTest.java
@@ -17,8 +17,10 @@
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
+import static java.util.stream.Collectors.joining;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.truth.Correspondence;
import com.google.testing.compile.CompilationRule;
import javax.lang.model.element.AnnotationMirror;
@@ -344,6 +346,66 @@ public void getChars() {
assertThat(AnnotationValues.getChars(value)).containsExactly('b', 'c').inOrder();
}
+ @Test
+ public void toSourceString() {
+ ImmutableMap inputs =
+ ImmutableMap.builder()
+ .put("classValue", "com.google.auto.common.AnnotationValuesTest.InsideClassA.class")
+ .put(
+ "classValues",
+ "{com.google.auto.common.AnnotationValuesTest.InsideClassA.class,"
+ + " com.google.auto.common.AnnotationValuesTest.InsideClassB.class}")
+ .put(
+ "genericClassValue",
+ "com.google.auto.common.AnnotationValuesTest.GenericClass.class")
+ .put(
+ "insideAnnotationValue",
+ "@com.google.auto.common.AnnotationValuesTest.InsideAnnotation(19)")
+ .put(
+ "insideAnnotationValues",
+ "{@com.google.auto.common.AnnotationValuesTest.InsideAnnotation(20),"
+ + " @com.google.auto.common.AnnotationValuesTest.InsideAnnotation(21)}")
+ .put("stringValue", "\"hello\"")
+ .put("stringValues", "{\"it\\'s\", \"me\"}")
+ .put("enumValue", "com.google.auto.common.AnnotationValuesTest.Foo.BAR")
+ .put(
+ "enumValues",
+ "{com.google.auto.common.AnnotationValuesTest.Foo.BAZ,"
+ + " com.google.auto.common.AnnotationValuesTest.Foo.BAH}")
+ .put("intValue", "5")
+ .put("intValues", "{1, 2}")
+ .put("longValue", "6L")
+ .put("longValues", "{3L, 4L}")
+ .put("byteValue", "(byte) 7")
+ .put("byteValues", "{(byte) 8, (byte) 9}")
+ .put("shortValue", "(short) 10")
+ .put("shortValues", "{(short) 11, (short) 12}")
+ .put("floatValue", "13.0F")
+ .put("floatValues", "{14.0F, 15.0F}")
+ .put("doubleValue", "16.0")
+ .put("doubleValues", "{17.0, 18.0}")
+ .put("booleanValue", "true")
+ .put("booleanValues", "{true, false}")
+ .put("charValue", "'a'")
+ .put("charValues", "{'b', 'c'}")
+ .build();
+ inputs.forEach(
+ (name, expected) ->
+ assertThat(
+ AnnotationValues.toString(
+ AnnotationMirrors.getAnnotationValue(annotationMirror, name)))
+ .isEqualTo(expected));
+ assertThat(AnnotationMirrors.toString(annotationMirror))
+ .isEqualTo(
+ inputs.entrySet().stream()
+ .map(e -> e.getKey() + " = " + e.getValue())
+ .collect(
+ joining(
+ ", ",
+ "@com.google.auto.common.AnnotationValuesTest.MultiValueAnnotation(",
+ ")")));
+ }
+
private TypeElement getTypeElement(Class> clazz) {
return elements.getTypeElement(clazz.getCanonicalName());
}
diff --git a/common/src/test/java/com/google/auto/common/BasicAnnotationProcessorTest.java b/common/src/test/java/com/google/auto/common/BasicAnnotationProcessorTest.java
index f75345032d..03944e5df9 100644
--- a/common/src/test/java/com/google/auto/common/BasicAnnotationProcessorTest.java
+++ b/common/src/test/java/com/google/auto/common/BasicAnnotationProcessorTest.java
@@ -79,7 +79,7 @@ private static class RequiresGeneratedCodeProcessor extends BaseAnnotationProces
@Override
protected Iterable extends Step> steps() {
- return ImmutableSet.of(
+ return ImmutableList.of(
new Step() {
@Override
public ImmutableSet extends Element> process(
@@ -126,7 +126,7 @@ ImmutableList> processArguments() {
public static class GeneratesCodeProcessor extends BaseAnnotationProcessor {
@Override
protected Iterable extends Step> steps() {
- return ImmutableSet.of(
+ return ImmutableList.of(
new Step() {
@Override
public ImmutableSet extends Element> process(
@@ -150,7 +150,7 @@ public static class AnAnnotationProcessor extends BaseAnnotationProcessor {
@Override
protected Iterable extends Step> steps() {
- return ImmutableSet.of(
+ return ImmutableList.of(
new Step() {
@Override
public ImmutableSet process(
@@ -177,7 +177,7 @@ public static class CauseErrorProcessor extends BaseAnnotationProcessor {
@Override
protected Iterable extends Step> steps() {
- return ImmutableSet.of(
+ return ImmutableList.of(
new Step() {
@Override
public ImmutableSet process(
@@ -202,7 +202,7 @@ public static class MissingAnnotationProcessor extends BaseAnnotationProcessor {
@Override
protected Iterable extends Step> steps() {
- return ImmutableSet.of(
+ return ImmutableList.of(
new Step() {
@Override
public ImmutableSet process(
diff --git a/common/src/test/java/com/google/auto/common/GeneratedAnnotationsTest.java b/common/src/test/java/com/google/auto/common/GeneratedAnnotationsTest.java
index 1c816c1043..f9426527ba 100644
--- a/common/src/test/java/com/google/auto/common/GeneratedAnnotationsTest.java
+++ b/common/src/test/java/com/google/auto/common/GeneratedAnnotationsTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Objects.requireNonNull;
import static org.junit.Assume.assumeTrue;
import com.google.common.collect.ImmutableList;
@@ -31,6 +32,7 @@
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.file.Files;
+import java.util.Objects;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
@@ -44,6 +46,7 @@
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -99,12 +102,12 @@ public boolean process(Set extends TypeElement> annotations, RoundEnvironment
* Run {@link TestProcessor} in a compilation with the given {@code options}, and prevent the
* compilation from accessing classes with the qualified names in {@code maskFromClasspath}.
*/
- private String runProcessor(ImmutableList options, String packageToMask)
+ private String runProcessor(ImmutableList options, @Nullable String packageToMask)
throws IOException {
File tempDir = temporaryFolder.newFolder();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager standardFileManager =
- compiler.getStandardFileManager(/* diagnostics= */ null, /* locale= */ null, UTF_8);
+ compiler.getStandardFileManager(/* diagnosticListener= */ null, /* locale= */ null, UTF_8);
standardFileManager.setLocation(StandardLocation.CLASS_OUTPUT, ImmutableList.of(tempDir));
StandardJavaFileManager proxyFileManager =
Reflection.newProxy(
@@ -142,18 +145,20 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors)
*/
private static class FileManagerInvocationHandler implements InvocationHandler {
private final StandardJavaFileManager fileManager;
- private final String packageToMask;
+ private final @Nullable String packageToMask;
- FileManagerInvocationHandler(StandardJavaFileManager fileManager, String packageToMask) {
+ FileManagerInvocationHandler(
+ StandardJavaFileManager fileManager, @Nullable String packageToMask) {
this.fileManager = fileManager;
this.packageToMask = packageToMask;
}
@Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ public Object invoke(Object proxy, Method method, @Nullable Object @Nullable [] args)
+ throws Throwable {
if (method.getName().equals("list")) {
- String packageName = (String) args[1];
- if (packageName.equals(packageToMask)) {
+ String packageName = (String) requireNonNull(args)[1];
+ if (Objects.equals(packageName, packageToMask)) {
return ImmutableList.of();
}
}
@@ -187,8 +192,7 @@ public void source8_masked() throws Exception {
// An alternative would be to delete this test method. JDK8 always has
// javax.annotation.Generated so it isn't really meaningful to test it without.
ImmutableList options = ImmutableList.of("-source", "8", "-target", "8");
- String generated =
- runProcessor(options, "javax.annotation");
+ String generated = runProcessor(options, "javax.annotation");
assertThat(generated).doesNotContain(JAVAX_ANNOTATION_GENERATED);
assertThat(generated).doesNotContain(JAVAX_ANNOTATION_PROCESSING_GENERATED);
}
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 95043cf376..eaa504a10a 100644
--- a/common/src/test/java/com/google/auto/common/MoreElementsTest.java
+++ b/common/src/test/java/com/google/auto/common/MoreElementsTest.java
@@ -18,6 +18,7 @@
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static java.util.Objects.requireNonNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -58,13 +59,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());
@@ -80,8 +82,7 @@ public void getPackage() {
@Test
public void asPackage() {
- assertThat(MoreElements.asPackage(javaLangPackageElement))
- .isEqualTo(javaLangPackageElement);
+ assertThat(MoreElements.asPackage(javaLangPackageElement)).isEqualTo(javaLangPackageElement);
}
@Test
@@ -89,19 +90,20 @@ public void asPackage_illegalArgument() {
try {
MoreElements.asPackage(stringElement);
fail();
- } catch (IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) {
+ }
}
- @Test public void asTypeElement() {
- Element typeElement =
- compilation.getElements().getTypeElement(String.class.getCanonicalName());
+ @Test
+ public void asTypeElement() {
+ 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());
+ @Test
+ public void asTypeElement_notATypeElement() {
+ TypeElement typeElement = elements.getTypeElement(String.class.getCanonicalName());
for (ExecutableElement e : ElementFilter.methodsIn(typeElement.getEnclosedElements())) {
assertFalse(MoreElements.isType(e));
try {
@@ -143,7 +145,8 @@ public void asType_illegalArgument() {
try {
MoreElements.asType(javaLangPackageElement);
fail();
- } catch (IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) {
+ }
}
@Test
@@ -158,7 +161,8 @@ public void asVariable_illegalArgument() {
try {
MoreElements.asVariable(javaLangPackageElement);
fail();
- } catch (IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) {
+ }
}
@Test
@@ -166,8 +170,8 @@ public void asExecutable() {
for (Element methodElement : ElementFilter.methodsIn(stringElement.getEnclosedElements())) {
assertThat(MoreElements.asExecutable(methodElement)).isEqualTo(methodElement);
}
- for (Element methodElement
- : ElementFilter.constructorsIn(stringElement.getEnclosedElements())) {
+ for (Element methodElement :
+ ElementFilter.constructorsIn(stringElement.getEnclosedElements())) {
assertThat(MoreElements.asExecutable(methodElement)).isEqualTo(methodElement);
}
}
@@ -177,7 +181,8 @@ public void asExecutable_illegalArgument() {
try {
MoreElements.asExecutable(javaLangPackageElement);
fail();
- } catch (IllegalArgumentException expected) {}
+ } catch (IllegalArgumentException expected) {
+ }
}
@Retention(RetentionPolicy.RUNTIME)
@@ -190,39 +195,90 @@ public void asExecutable_illegalArgument() {
@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 documented =
- MoreElements.getAnnotationMirror(element, Documented.class);
- Optional innerAnnotation =
- MoreElements.getAnnotationMirror(element, InnerAnnotation.class);
- Optional 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 documented,
+ Optional innerAnnotation,
+ Optional suppressWarnings) {
expect.that(documented).isPresent();
expect.that(innerAnnotation).isPresent();
expect.that(suppressWarnings).isAbsent();
Element annotationElement = documented.get().getAnnotationType().asElement();
expect.that(MoreElements.isType(annotationElement)).isTrue();
- expect.that(MoreElements.asType(annotationElement).getQualifiedName().toString())
+ expect
+ .that(MoreElements.asType(annotationElement).getQualifiedName().toString())
.isEqualTo(Documented.class.getCanonicalName());
annotationElement = innerAnnotation.get().getAnnotationType().asElement();
expect.that(MoreElements.isType(annotationElement)).isTrue();
- expect.that(MoreElements.asType(annotationElement).getQualifiedName().toString())
+ expect
+ .that(MoreElements.asType(annotationElement).getQualifiedName().toString())
.isEqualTo(InnerAnnotation.class.getCanonicalName());
}
@@ -231,6 +287,7 @@ static void staticMethod() {}
abstract String foo();
+ @SuppressWarnings("unused")
private void privateMethod() {}
}
@@ -259,7 +316,6 @@ void buh(int x, int y) {}
@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);
@@ -270,19 +326,20 @@ public void getLocalAndInheritedMethods_Old() {
Set objectMethods = visibleMethodsFromObject();
assertThat(childTypeMethods).containsAtLeastElementsIn(objectMethods);
Set nonObjectMethods = Sets.difference(childTypeMethods, objectMethods);
- assertThat(nonObjectMethods).containsExactly(
+ assertThat(nonObjectMethods)
+ .containsExactly(
getMethod(ParentInterface.class, "bar", longMirror),
getMethod(ParentClass.class, "foo"),
getMethod(Child.class, "bar"),
getMethod(Child.class, "baz"),
getMethod(Child.class, "buh", intMirror),
getMethod(Child.class, "buh", intMirror, intMirror))
- .inOrder();;
+ .inOrder();
+ ;
}
@Test
public void getLocalAndInheritedMethods() {
- Elements elements = compilation.getElements();
Types types = compilation.getTypes();
TypeMirror intMirror = types.getPrimitiveType(TypeKind.INT);
TypeMirror longMirror = types.getPrimitiveType(TypeKind.LONG);
@@ -293,7 +350,8 @@ public void getLocalAndInheritedMethods() {
Set objectMethods = visibleMethodsFromObject();
assertThat(childTypeMethods).containsAtLeastElementsIn(objectMethods);
Set nonObjectMethods = Sets.difference(childTypeMethods, objectMethods);
- assertThat(nonObjectMethods).containsExactly(
+ assertThat(nonObjectMethods)
+ .containsExactly(
getMethod(ParentInterface.class, "bar", longMirror),
getMethod(ParentClass.class, "foo"),
getMethod(Child.class, "bar"),
@@ -305,7 +363,6 @@ public void getLocalAndInheritedMethods() {
@Test
public void getAllMethods() {
- Elements elements = compilation.getElements();
Types types = compilation.getTypes();
TypeMirror intMirror = types.getPrimitiveType(TypeKind.INT);
TypeMirror longMirror = types.getPrimitiveType(TypeKind.LONG);
@@ -316,7 +373,8 @@ public void getAllMethods() {
Set objectMethods = allMethodsFromObject();
assertThat(childTypeMethods).containsAtLeastElementsIn(objectMethods);
Set nonObjectMethods = Sets.difference(childTypeMethods, objectMethods);
- assertThat(nonObjectMethods).containsExactly(
+ assertThat(nonObjectMethods)
+ .containsExactly(
getMethod(ParentInterface.class, "staticMethod"),
getMethod(ParentInterface.class, "bar", longMirror),
getMethod(ParentClass.class, "staticMethod"),
@@ -330,41 +388,6 @@ public void getAllMethods() {
.inOrder();
}
- static class Injectable {}
-
- public static class MenuManager {
- public interface ParentComponent extends MenuItemA.ParentComponent, MenuItemB.ParentComponent {}
- }
-
- public static class MenuItemA {
- public interface ParentComponent {
- Injectable injectable();
- }
- }
-
- public static class MenuItemB {
- public interface ParentComponent {
- Injectable injectable();
- }
- }
-
- public static class Main {
- public interface ParentComponent extends MenuManager.ParentComponent {}
- }
-
- // Example from https://github.com/williamlian/daggerbug
- @Test
- public void getLocalAndInheritedMethods_DaggerBug() {
- Elements elementUtils = compilation.getElements();
- TypeElement main = elementUtils.getTypeElement(Main.ParentComponent.class.getCanonicalName());
- Set methods = MoreElements.getLocalAndInheritedMethods(
- main, compilation.getTypes(), elementUtils);
- assertThat(methods).hasSize(1);
- ExecutableElement method = methods.iterator().next();
- assertThat(method.getSimpleName().toString()).isEqualTo("injectable");
- assertThat(method.getParameters()).isEmpty();
- }
-
private Set visibleMethodsFromObject() {
Types types = compilation.getTypes();
TypeMirror intMirror = types.getPrimitiveType(TypeKind.INT);
@@ -404,7 +427,7 @@ private Set allMethodsFromObject() {
}
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())) {
@@ -423,7 +446,7 @@ private ExecutableElement getMethod(Class> c, String methodName, TypeMirror...
}
}
assertWithMessage(methodName + Arrays.toString(parameterTypes)).that(found).isNotNull();
- return found;
+ return requireNonNull(found);
}
private abstract static class AbstractAbstractList extends AbstractList {}
@@ -458,8 +481,6 @@ private Set abstractMethodNamesFrom(Set methods) {
// are implemented in AbstractList.
@Test
public void getLocalAndInheritedMethods_AbstractList() {
- Elements elements = compilation.getElements();
-
TypeElement abstractType =
elements.getTypeElement(AbstractAbstractList.class.getCanonicalName());
Set abstractTypeMethods =
diff --git a/common/src/test/java/com/google/auto/common/MoreTypesIsTypeOfTest.java b/common/src/test/java/com/google/auto/common/MoreTypesIsTypeOfTest.java
index 05a0a1194e..ba8fccebdd 100644
--- a/common/src/test/java/com/google/auto/common/MoreTypesIsTypeOfTest.java
+++ b/common/src/test/java/com/google/auto/common/MoreTypesIsTypeOfTest.java
@@ -15,182 +15,172 @@
*/
package com.google.auto.common;
-import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.testing.compile.CompilationRule;
-import javax.lang.model.element.Element;
+import java.util.List;
+import java.util.SortedMap;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-/**
- * Tests {@link MoreTypes#isTypeOf}.
- */
+/** Tests {@link MoreTypes#isTypeOf(Class, TypeMirror)}. */
@RunWith(JUnit4.class)
public class MoreTypesIsTypeOfTest {
@Rule public CompilationRule compilationRule = new CompilationRule();
- private Elements elements;
-
- @Before public void setUp() {
- this.elements = compilationRule.getElements();
- }
-
- private interface TestType {}
-
- @Test public void isTypeOf_DeclaredType() {
- assertTrue(MoreTypes.isType(typeElementFor(TestType.class).asType()));
- assertWithMessage("mirror represents the TestType")
- .that(MoreTypes.isTypeOf(TestType.class, typeElementFor(TestType.class).asType()))
+ private Elements elementUtils;
+ private Types typeUtils;
+
+ @Before
+ public void setUp() {
+ this.elementUtils = compilationRule.getElements();
+ this.typeUtils = compilationRule.getTypes();
+ }
+
+ @Test
+ public void isTypeOf_primitiveAndBoxedPrimitiveTypes() {
+ class PrimitiveTypeInfo {
+ final Class> CLASS_TYPE;
+ final Class> BOXED_CLASS_TYPE;
+ final TypeKind TYPE_KIND;
+
+ PrimitiveTypeInfo(Class> classType, Class> boxedClassType, TypeKind typeKind) {
+ this.CLASS_TYPE = classType;
+ this.BOXED_CLASS_TYPE = boxedClassType;
+ this.TYPE_KIND = typeKind;
+ }
+ }
+ final List primitivesTypeInfo =
+ ImmutableList.of(
+ new PrimitiveTypeInfo(Byte.TYPE, Byte.class, TypeKind.BYTE),
+ new PrimitiveTypeInfo(Short.TYPE, Short.class, TypeKind.SHORT),
+ new PrimitiveTypeInfo(Integer.TYPE, Integer.class, TypeKind.INT),
+ new PrimitiveTypeInfo(Long.TYPE, Long.class, TypeKind.LONG),
+ new PrimitiveTypeInfo(Float.TYPE, Float.class, TypeKind.FLOAT),
+ new PrimitiveTypeInfo(Double.TYPE, Double.class, TypeKind.DOUBLE),
+ new PrimitiveTypeInfo(Boolean.TYPE, Boolean.class, TypeKind.BOOLEAN),
+ new PrimitiveTypeInfo(Character.TYPE, Character.class, TypeKind.CHAR));
+
+ for (boolean isBoxedI : new boolean[] {false, true}) {
+ for (int i = 0; i < primitivesTypeInfo.size(); i++) { // For the Class> arg
+ Class> clazz =
+ isBoxedI
+ ? primitivesTypeInfo.get(i).BOXED_CLASS_TYPE
+ : primitivesTypeInfo.get(i).CLASS_TYPE;
+
+ for (boolean isBoxedJ : new boolean[] {false, true}) {
+ for (int j = 0; j < primitivesTypeInfo.size(); j++) { // For the TypeMirror arg
+ TypeKind typeKind = primitivesTypeInfo.get(j).TYPE_KIND;
+ TypeMirror typeMirror =
+ isBoxedJ
+ ? typeUtils.boxedClass(typeUtils.getPrimitiveType(typeKind)).asType()
+ : typeUtils.getPrimitiveType(typeKind);
+
+ String message =
+ "Mirror:\t" + typeMirror.toString() + "\nClass:\t" + clazz.getCanonicalName();
+ if (isBoxedI == isBoxedJ && i == j) {
+ assertWithMessage(message).that(MoreTypes.isTypeOf(clazz, typeMirror)).isTrue();
+ } else {
+ assertWithMessage(message).that(MoreTypes.isTypeOf(clazz, typeMirror)).isFalse();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ public void isTypeOf_voidAndPseudoVoidTypes() {
+ TypeMirror voidType = typeUtils.getNoType(TypeKind.VOID);
+ TypeMirror pseudoVoidType = getTypeElementFor(Void.class).asType();
+
+ assertWithMessage("Mirror:\t" + voidType + "\nClass:\t" + Void.TYPE.getCanonicalName())
+ .that(MoreTypes.isTypeOf(Void.TYPE, voidType))
.isTrue();
- assertWithMessage("mirror does not represent a String")
- .that(MoreTypes.isTypeOf(String.class, typeElementFor(TestType.class).asType()))
+ assertWithMessage("Mirror:\t" + pseudoVoidType + "\nClass:\t" + Void.TYPE.getCanonicalName())
+ .that(MoreTypes.isTypeOf(Void.TYPE, pseudoVoidType))
.isFalse();
- }
- private interface ArrayType {
- String[] array();
+ assertWithMessage("Mirror:\t" + voidType + "\nClass:\t" + Void.class.getCanonicalName())
+ .that(MoreTypes.isTypeOf(Void.class, voidType))
+ .isFalse();
+ assertWithMessage("Mirror:\t" + pseudoVoidType + "\nClass:\t" + Void.class.getCanonicalName())
+ .that(MoreTypes.isTypeOf(Void.class, pseudoVoidType))
+ .isTrue();
}
- @Test public void isTypeOf_ArrayType() {
- assertTrue(MoreTypes.isType(typeElementFor(ArrayType.class).asType()));
- TypeMirror type = extractReturnTypeFromHolder(typeElementFor(ArrayType.class));
- assertWithMessage("array mirror represents an array Class object")
+ @Test
+ public void isTypeOf_arrayType() {
+ TypeMirror type = typeUtils.getArrayType(getTypeElementFor(String.class).asType());
+ assertWithMessage("Mirror:\t" + type + "\nClass:\t" + String[].class.getCanonicalName())
.that(MoreTypes.isTypeOf(String[].class, type))
.isTrue();
- }
-
- private interface PrimitiveBoolean {
- boolean method();
- }
-
- @Test public void isTypeOf_PrimitiveBoolean() {
- assertTrue(MoreTypes.isType(typeElementFor(PrimitiveBoolean.class).asType()));
- TypeMirror type = extractReturnTypeFromHolder(typeElementFor(PrimitiveBoolean.class));
- assertWithMessage("mirror of a boolean").that(MoreTypes.isTypeOf(Boolean.TYPE, type)).isTrue();
- }
-
- private interface PrimitiveByte {
- byte method();
- }
-
- @Test public void isTypeOf_PrimitiveByte() {
- assertTrue(MoreTypes.isType(typeElementFor(PrimitiveByte.class).asType()));
- TypeMirror type = extractReturnTypeFromHolder(typeElementFor(PrimitiveByte.class));
- assertWithMessage("mirror of a byte").that(MoreTypes.isTypeOf(Byte.TYPE, type)).isTrue();
- }
-
- private interface PrimitiveChar {
- char method();
- }
-
- @Test public void isTypeOf_PrimitiveChar() {
- assertTrue(MoreTypes.isType(typeElementFor(PrimitiveChar.class).asType()));
- TypeMirror type = extractReturnTypeFromHolder(typeElementFor(PrimitiveChar.class));
- assertWithMessage("mirror of a char").that(MoreTypes.isTypeOf(Character.TYPE, type)).isTrue();
- }
-
- private interface PrimitiveDouble {
- double method();
- }
-
- @Test public void isTypeOf_PrimitiveDouble() {
- assertTrue(MoreTypes.isType(typeElementFor(PrimitiveDouble.class).asType()));
- TypeMirror type = extractReturnTypeFromHolder(typeElementFor(PrimitiveDouble.class));
- assertWithMessage("mirror of a double").that(MoreTypes.isTypeOf(Double.TYPE, type)).isTrue();
- }
-
- private interface PrimitiveFloat {
- float method();
- }
-
- @Test public void isTypeOf_PrimitiveFloat() {
- assertTrue(MoreTypes.isType(typeElementFor(PrimitiveFloat.class).asType()));
- TypeMirror type = extractReturnTypeFromHolder(typeElementFor(PrimitiveFloat.class));
- assertWithMessage("mirror of a float").that(MoreTypes.isTypeOf(Float.TYPE, type)).isTrue();
- }
-
- private interface PrimitiveInt {
- int method();
- }
-
- @Test public void isTypeOf_PrimitiveInt() {
- assertTrue(MoreTypes.isType(typeElementFor(PrimitiveInt.class).asType()));
- TypeMirror type = extractReturnTypeFromHolder(typeElementFor(PrimitiveInt.class));
- assertWithMessage("mirror of a int").that(MoreTypes.isTypeOf(Integer.TYPE, type)).isTrue();
- }
-
- private interface PrimitiveLong {
- long method();
- }
-
- @Test public void isTypeOf_PrimitiveLong() {
- assertTrue(MoreTypes.isType(typeElementFor(PrimitiveLong.class).asType()));
- TypeMirror type = extractReturnTypeFromHolder(typeElementFor(PrimitiveLong.class));
- assertWithMessage("mirror of a long").that(MoreTypes.isTypeOf(Long.TYPE, type)).isTrue();
- }
-
- private interface PrimitiveShort {
- short method();
- }
-
- @Test public void isTypeOf_PrimitiveShort() {
- assertTrue(MoreTypes.isType(typeElementFor(PrimitiveShort.class).asType()));
- TypeMirror type = extractReturnTypeFromHolder(typeElementFor(PrimitiveShort.class));
- assertWithMessage("mirror of a short").that(MoreTypes.isTypeOf(Short.TYPE, type)).isTrue();
- }
-
- private interface PrimitiveVoid {
- void method();
- }
+ assertWithMessage("Mirror:\t" + type + "\nClass:\t" + Integer[].class.getCanonicalName())
+ .that(MoreTypes.isTypeOf(Integer[].class, type))
+ .isFalse();
+ assertWithMessage("Mirror:\t" + type + "\nClass:\t" + int[].class.getCanonicalName())
+ .that(MoreTypes.isTypeOf(int[].class, type))
+ .isFalse();
- @Test public void isTypeOf_void() {
- assertTrue(MoreTypes.isType(typeElementFor(PrimitiveVoid.class).asType()));
- TypeMirror primitive = extractReturnTypeFromHolder(typeElementFor(PrimitiveVoid.class));
- assertWithMessage("mirror of a void").that(MoreTypes.isTypeOf(Void.TYPE, primitive)).isTrue();
+ type = typeUtils.getArrayType(typeUtils.getPrimitiveType(TypeKind.INT));
+ assertWithMessage("Mirror:\t" + type + "\nClass:\t" + String[].class.getCanonicalName())
+ .that(MoreTypes.isTypeOf(String[].class, type))
+ .isFalse();
+ assertWithMessage("Mirror:\t" + type + "\nClass:\t" + Integer[].class.getCanonicalName())
+ .that(MoreTypes.isTypeOf(Integer[].class, type))
+ .isFalse();
+ assertWithMessage("Mirror:\t" + type + "\nClass:\t" + int[].class.getCanonicalName())
+ .that(MoreTypes.isTypeOf(int[].class, type))
+ .isTrue();
}
- private interface DeclaredVoid {
- Void method();
+ private interface TestType {
+ @SuppressWarnings("unused")
+ > T method0();
}
- @Test public void isTypeOf_Void() {
- assertTrue(MoreTypes.isType(typeElementFor(DeclaredVoid.class).asType()));
- TypeMirror declared = extractReturnTypeFromHolder(typeElementFor(DeclaredVoid.class));
- assertWithMessage("mirror of a void").that(MoreTypes.isTypeOf(Void.class, declared)).isTrue();
+ @Test
+ public void isTypeOf_declaredType() {
+ TypeMirror TestTypeTypeMirror = getTypeElementFor(TestType.class).asType();
+ assertTrue(MoreTypes.isType(TestTypeTypeMirror));
+ assertWithMessage(
+ "Mirror:\t" + TestTypeTypeMirror + "\nClass:\t" + TestType.class.getCanonicalName())
+ .that(MoreTypes.isTypeOf(TestType.class, TestTypeTypeMirror))
+ .isTrue();
+ assertWithMessage(
+ "Mirror:\t" + TestTypeTypeMirror + "\nClass:\t" + String.class.getCanonicalName())
+ .that(MoreTypes.isTypeOf(String.class, TestTypeTypeMirror))
+ .isFalse();
}
- @Test public void isTypeOf_fail() {
- assertFalse(MoreTypes.isType(
- getOnlyElement(typeElementFor(DeclaredVoid.class).getEnclosedElements()).asType()));
- TypeMirror method =
- getOnlyElement(typeElementFor(DeclaredVoid.class).getEnclosedElements()).asType();
+ @Test
+ public void isTypeOf_fail() {
+ TypeMirror methodType =
+ Iterables.getOnlyElement(getTypeElementFor(TestType.class).getEnclosedElements()).asType();
+ assertFalse(MoreTypes.isType(methodType));
try {
- MoreTypes.isTypeOf(String.class, method);
+ MoreTypes.isTypeOf(List.class, methodType);
fail();
- } catch (IllegalArgumentException expected) {}
- }
-
- // Utility methods for this test.
-
- private TypeMirror extractReturnTypeFromHolder(TypeElement typeElement) {
- Element element = Iterables.getOnlyElement(typeElement.getEnclosedElements());
- TypeMirror arrayType = MoreElements.asExecutable(element).getReturnType();
- return arrayType;
+ } catch (IllegalArgumentException expected) {
+ }
}
- private TypeElement typeElementFor(Class> clazz) {
- return elements.getTypeElement(clazz.getCanonicalName());
+ /* Utility method(s) */
+ private TypeElement getTypeElementFor(Class> clazz) {
+ return elementUtils.getTypeElement(clazz.getCanonicalName());
}
}
diff --git a/common/src/test/java/com/google/auto/common/MoreTypesTest.java b/common/src/test/java/com/google/auto/common/MoreTypesTest.java
index ff33ffc1d9..b8e84e0859 100644
--- a/common/src/test/java/com/google/auto/common/MoreTypesTest.java
+++ b/common/src/test/java/com/google/auto/common/MoreTypesTest.java
@@ -16,12 +16,12 @@
package com.google.auto.common;
import static com.google.common.truth.Truth.assertThat;
+import static java.util.Objects.requireNonNull;
import static javax.lang.model.type.TypeKind.NONE;
import static javax.lang.model.type.TypeKind.VOID;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
-import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
@@ -50,6 +50,7 @@
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -91,48 +92,51 @@ public void equivalence() {
DeclaredType containerOfString = types.getDeclaredType(container, stringType);
TypeMirror containedInObject = types.asMemberOf(containerOfObject, contained);
TypeMirror containedInString = types.asMemberOf(containerOfString, contained);
- EquivalenceTester tester = EquivalenceTester.of(MoreTypes.equivalence())
- .addEquivalenceGroup(types.getNullType())
- .addEquivalenceGroup(types.getNoType(NONE))
- .addEquivalenceGroup(types.getNoType(VOID))
- .addEquivalenceGroup(objectType)
- .addEquivalenceGroup(stringType)
- .addEquivalenceGroup(containedInObject)
- .addEquivalenceGroup(containedInString)
- .addEquivalenceGroup(funkyBounds.asType())
- .addEquivalenceGroup(funkyBounds2.asType())
- .addEquivalenceGroup(funkierBounds.asType())
- .addEquivalenceGroup(funkyBoundsVar, funkyBounds2Var)
- .addEquivalenceGroup(funkierBoundsVar)
- // Enum>
- .addEquivalenceGroup(enumElement.asType())
- // Map
- .addEquivalenceGroup(mapType)
- .addEquivalenceGroup(mapOfObjectToObjectType)
- // Map, ?>
- .addEquivalenceGroup(types.getDeclaredType(mapElement, wildcard, wildcard))
- // Map
- .addEquivalenceGroup(types.erasure(mapType), types.erasure(mapOfObjectToObjectType))
- .addEquivalenceGroup(types.getDeclaredType(mapElement, objectType, stringType))
- .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType, objectType))
- .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType, stringType))
- .addEquivalenceGroup(setOfSetOfObject)
- .addEquivalenceGroup(setOfSetOfString)
- .addEquivalenceGroup(setOfSetOfSetOfObject)
- .addEquivalenceGroup(setOfSetOfSetOfString)
- .addEquivalenceGroup(wildcard)
- // ? extends Object
- .addEquivalenceGroup(types.getWildcardType(objectType, null))
- // ? extends String
- .addEquivalenceGroup(types.getWildcardType(stringType, null))
- // ? super String
- .addEquivalenceGroup(types.getWildcardType(null, stringType))
- // Map>>
- .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType,
- types.getDeclaredType(mapElement, stringType,
- types.getDeclaredType(setElement, objectType))))
- .addEquivalenceGroup(FAKE_ERROR_TYPE)
- ;
+ EquivalenceTester tester =
+ EquivalenceTester.of(MoreTypes.equivalence())
+ .addEquivalenceGroup(types.getNullType())
+ .addEquivalenceGroup(types.getNoType(NONE))
+ .addEquivalenceGroup(types.getNoType(VOID))
+ .addEquivalenceGroup(objectType)
+ .addEquivalenceGroup(stringType)
+ .addEquivalenceGroup(containedInObject)
+ .addEquivalenceGroup(containedInString)
+ .addEquivalenceGroup(funkyBounds.asType())
+ .addEquivalenceGroup(funkyBounds2.asType())
+ .addEquivalenceGroup(funkierBounds.asType())
+ .addEquivalenceGroup(funkyBoundsVar, funkyBounds2Var)
+ .addEquivalenceGroup(funkierBoundsVar)
+ // Enum>
+ .addEquivalenceGroup(enumElement.asType())
+ // Map
+ .addEquivalenceGroup(mapType)
+ .addEquivalenceGroup(mapOfObjectToObjectType)
+ // Map, ?>
+ .addEquivalenceGroup(types.getDeclaredType(mapElement, wildcard, wildcard))
+ // Map
+ .addEquivalenceGroup(types.erasure(mapType), types.erasure(mapOfObjectToObjectType))
+ .addEquivalenceGroup(types.getDeclaredType(mapElement, objectType, stringType))
+ .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType, objectType))
+ .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType, stringType))
+ .addEquivalenceGroup(setOfSetOfObject)
+ .addEquivalenceGroup(setOfSetOfString)
+ .addEquivalenceGroup(setOfSetOfSetOfObject)
+ .addEquivalenceGroup(setOfSetOfSetOfString)
+ .addEquivalenceGroup(wildcard)
+ // ? extends Object
+ .addEquivalenceGroup(types.getWildcardType(objectType, null))
+ // ? extends String
+ .addEquivalenceGroup(types.getWildcardType(stringType, null))
+ // ? super String
+ .addEquivalenceGroup(types.getWildcardType(null, stringType))
+ // Map>>
+ .addEquivalenceGroup(
+ types.getDeclaredType(
+ mapElement,
+ stringType,
+ types.getDeclaredType(
+ mapElement, stringType, types.getDeclaredType(setElement, objectType))))
+ .addEquivalenceGroup(FAKE_ERROR_TYPE);
for (TypeKind kind : TypeKind.values()) {
if (kind.isPrimitive()) {
@@ -145,20 +149,18 @@ public void equivalence() {
}
}
- ImmutableSet> testClasses = ImmutableSet.of(
- ExecutableElementsGroupA.class,
- ExecutableElementsGroupB.class,
- ExecutableElementsGroupC.class,
- ExecutableElementsGroupD.class,
- ExecutableElementsGroupE.class);
+ ImmutableSet> testClasses =
+ ImmutableSet.of(
+ ExecutableElementsGroupA.class,
+ ExecutableElementsGroupB.class,
+ ExecutableElementsGroupC.class,
+ ExecutableElementsGroupD.class,
+ ExecutableElementsGroupE.class);
for (Class> testClass : testClasses) {
- ImmutableList equivalenceGroup = FluentIterable.from(
- elements.getTypeElement(testClass.getCanonicalName()).getEnclosedElements())
- .transform(new Function() {
- @Override public TypeMirror apply(Element input) {
- return input.asType();
- }
- })
+ ImmutableList equivalenceGroup =
+ FluentIterable.from(
+ elements.getTypeElement(testClass.getCanonicalName()).getEnclosedElements())
+ .transform(Element::asType)
.toList();
tester.addEquivalenceGroup(equivalenceGroup);
}
@@ -169,35 +171,45 @@ public void equivalence() {
@SuppressWarnings("unused")
private static final class ExecutableElementsGroupA {
ExecutableElementsGroupA() {}
+
void a() {}
+
public static void b() {}
}
@SuppressWarnings("unused")
private static final class ExecutableElementsGroupB {
ExecutableElementsGroupB(String s) {}
+
void a(String s) {}
+
public static void b(String s) {}
}
@SuppressWarnings("unused")
private static final class ExecutableElementsGroupC {
ExecutableElementsGroupC() throws Exception {}
+
void a() throws Exception {}
+
public static void b() throws Exception {}
}
@SuppressWarnings("unused")
private static final class ExecutableElementsGroupD {
ExecutableElementsGroupD() throws RuntimeException {}
+
void a() throws RuntimeException {}
+
public static void b() throws RuntimeException {}
}
@SuppressWarnings("unused")
private static final class ExecutableElementsGroupE {
ExecutableElementsGroupE() {}
+
void a() {}
+
public static void b() {}
}
@@ -215,53 +227,44 @@ private static final class FunkyBounds2> {}
@SuppressWarnings("unused")
private static final class FunkierBounds & Cloneable> {}
- @Test public void testReferencedTypes() {
+ @Test
+ public void testReferencedTypes() {
Elements elements = compilationRule.getElements();
- TypeElement testDataElement = elements
- .getTypeElement(ReferencedTypesTestData.class.getCanonicalName());
+ TypeElement testDataElement =
+ elements.getTypeElement(ReferencedTypesTestData.class.getCanonicalName());
ImmutableMap fieldIndex =
FluentIterable.from(ElementFilter.fieldsIn(testDataElement.getEnclosedElements()))
- .uniqueIndex(new Function() {
- @Override public String apply(VariableElement input) {
- return input.getSimpleName().toString();
- }
- });
-
- TypeElement objectElement =
- elements.getTypeElement(Object.class.getCanonicalName());
- TypeElement stringElement =
- elements.getTypeElement(String.class.getCanonicalName());
- TypeElement integerElement =
- elements.getTypeElement(Integer.class.getCanonicalName());
- TypeElement setElement =
- elements.getTypeElement(Set.class.getCanonicalName());
- TypeElement mapElement =
- elements.getTypeElement(Map.class.getCanonicalName());
+ .uniqueIndex(input -> input.getSimpleName().toString());
+
+ TypeElement objectElement = elements.getTypeElement(Object.class.getCanonicalName());
+ TypeElement stringElement = elements.getTypeElement(String.class.getCanonicalName());
+ TypeElement integerElement = elements.getTypeElement(Integer.class.getCanonicalName());
+ TypeElement setElement = elements.getTypeElement(Set.class.getCanonicalName());
+ TypeElement mapElement = elements.getTypeElement(Map.class.getCanonicalName());
TypeElement charSequenceElement =
elements.getTypeElement(CharSequence.class.getCanonicalName());
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f1").asType()))
- .containsExactly(objectElement);
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f2").asType()))
- .containsExactly(setElement, stringElement);
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f3").asType()))
+ assertThat(referencedTypes(fieldIndex, "f1")).containsExactly(objectElement);
+ assertThat(referencedTypes(fieldIndex, "f2")).containsExactly(setElement, stringElement);
+ assertThat(referencedTypes(fieldIndex, "f3"))
.containsExactly(mapElement, stringElement, objectElement);
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f4").asType()))
- .containsExactly(integerElement);
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f5").asType()))
- .containsExactly(setElement);
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f6").asType()))
- .containsExactly(setElement, charSequenceElement);
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f7").asType()))
+ assertThat(referencedTypes(fieldIndex, "f4")).containsExactly(integerElement);
+ assertThat(referencedTypes(fieldIndex, "f5")).containsExactly(setElement);
+ assertThat(referencedTypes(fieldIndex, "f6")).containsExactly(setElement, charSequenceElement);
+ assertThat(referencedTypes(fieldIndex, "f7"))
.containsExactly(mapElement, stringElement, setElement, charSequenceElement);
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f8").asType()))
- .containsExactly(stringElement);
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f9").asType()))
- .containsExactly(stringElement);
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f10").asType())).isEmpty();
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f11").asType())).isEmpty();
- assertThat(MoreTypes.referencedTypes(fieldIndex.get("f12").asType()))
- .containsExactly(setElement, stringElement);
+ assertThat(referencedTypes(fieldIndex, "f8")).containsExactly(stringElement);
+ assertThat(referencedTypes(fieldIndex, "f9")).containsExactly(stringElement);
+ assertThat(referencedTypes(fieldIndex, "f10")).isEmpty();
+ assertThat(referencedTypes(fieldIndex, "f11")).isEmpty();
+ assertThat(referencedTypes(fieldIndex, "f12")).containsExactly(setElement, stringElement);
+ }
+
+ private static ImmutableSet referencedTypes(
+ ImmutableMap fieldIndex, String fieldName) {
+ VariableElement field = fieldIndex.get(fieldName);
+ requireNonNull(field, fieldName);
+ return MoreTypes.referencedTypes(field.asType());
}
@SuppressWarnings("unused") // types used in compiler tests
@@ -281,20 +284,23 @@ private static final class ReferencedTypesTestData {
}
private static class Parent {}
+
private static class ChildA extends Parent {}
+
private static class ChildB extends Parent {}
+
private static class GenericChild extends Parent {}
+
private interface InterfaceType {}
@Test
public void asElement_throws() {
- TypeMirror javaDotLang =
- compilationRule.getElements().getPackageElement("java.lang").asType();
+ TypeMirror javaDotLang = compilationRule.getElements().getPackageElement("java.lang").asType();
try {
MoreTypes.asElement(javaDotLang);
fail();
- } catch (IllegalArgumentException expected) {}
-
+ } catch (IllegalArgumentException expected) {
+ }
}
@Test
@@ -302,8 +308,9 @@ public void asElement() {
Elements elements = compilationRule.getElements();
TypeElement stringElement = elements.getTypeElement("java.lang.String");
assertThat(MoreTypes.asElement(stringElement.asType())).isEqualTo(stringElement);
- TypeParameterElement setParameterElement = Iterables.getOnlyElement(
- compilationRule.getElements().getTypeElement("java.util.Set").getTypeParameters());
+ TypeParameterElement setParameterElement =
+ Iterables.getOnlyElement(
+ compilationRule.getElements().getTypeElement("java.util.Set").getTypeParameters());
assertThat(MoreTypes.asElement(setParameterElement.asType())).isEqualTo(setParameterElement);
// we don't test error types because those are very hard to get predictably
}
@@ -321,8 +328,7 @@ public void testNonObjectSuperclass() {
TypeElement genericChild = elements.getTypeElement(GenericChild.class.getCanonicalName());
TypeMirror genericChildOfNumber = types.getDeclaredType(genericChild, numberType);
TypeMirror genericChildOfInteger = types.getDeclaredType(genericChild, integerType);
- TypeMirror objectType =
- elements.getTypeElement(Object.class.getCanonicalName()).asType();
+ TypeMirror objectType = elements.getTypeElement(Object.class.getCanonicalName()).asType();
TypeMirror interfaceType =
elements.getTypeElement(InterfaceType.class.getCanonicalName()).asType();
@@ -344,18 +350,20 @@ public void testNonObjectSuperclass() {
Optional parentOfGenericChildOfInteger =
MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) genericChildOfInteger);
- EquivalenceTester tester = EquivalenceTester.of(MoreTypes.equivalence())
- .addEquivalenceGroup(parentOfChildA.get(),
- types.getDeclaredType(parent, numberType),
- parentOfGenericChildOfNumber.get())
- .addEquivalenceGroup(parentOfChildB.get(), types.getDeclaredType(parent, stringType))
- .addEquivalenceGroup(parentOfGenericChild.get(), parent.asType())
- .addEquivalenceGroup(parentOfGenericChildOfInteger.get(),
- types.getDeclaredType(parent, integerType));
+ EquivalenceTester tester =
+ EquivalenceTester.of(MoreTypes.equivalence())
+ .addEquivalenceGroup(
+ parentOfChildA.get(),
+ types.getDeclaredType(parent, numberType),
+ parentOfGenericChildOfNumber.get())
+ .addEquivalenceGroup(parentOfChildB.get(), types.getDeclaredType(parent, stringType))
+ .addEquivalenceGroup(parentOfGenericChild.get(), parent.asType())
+ .addEquivalenceGroup(
+ parentOfGenericChildOfInteger.get(), types.getDeclaredType(parent, integerType));
tester.test();
}
-
+
@Test
public void testAsMemberOf_variableElement() {
Types types = compilationRule.getTypes();
@@ -365,11 +373,13 @@ public void testAsMemberOf_variableElement() {
TypeMirror integerType = elements.getTypeElement(Integer.class.getCanonicalName()).asType();
TypeElement paramsElement = elements.getTypeElement(Params.class.getCanonicalName());
- VariableElement tParam = Iterables.getOnlyElement(Iterables.getOnlyElement(
- ElementFilter.methodsIn(paramsElement.getEnclosedElements())).getParameters());
+ VariableElement tParam =
+ Iterables.getOnlyElement(
+ Iterables.getOnlyElement(ElementFilter.methodsIn(paramsElement.getEnclosedElements()))
+ .getParameters());
VariableElement tField =
- Iterables.getOnlyElement(ElementFilter.fieldsIn(paramsElement.getEnclosedElements()));
-
+ Iterables.getOnlyElement(ElementFilter.fieldsIn(paramsElement.getEnclosedElements()));
+
DeclaredType numberParams =
(DeclaredType) elements.getTypeElement(NumberParams.class.getCanonicalName()).asType();
DeclaredType stringParams =
@@ -377,7 +387,7 @@ public void testAsMemberOf_variableElement() {
TypeElement genericParams = elements.getTypeElement(GenericParams.class.getCanonicalName());
DeclaredType genericParamsOfNumber = types.getDeclaredType(genericParams, numberType);
DeclaredType genericParamsOfInteger = types.getDeclaredType(genericParams, integerType);
-
+
TypeMirror fieldOfNumberParams = MoreTypes.asMemberOf(types, numberParams, tField);
TypeMirror paramOfNumberParams = MoreTypes.asMemberOf(types, numberParams, tParam);
TypeMirror fieldOfStringParams = MoreTypes.asMemberOf(types, stringParams, tField);
@@ -389,62 +399,76 @@ public void testAsMemberOf_variableElement() {
TypeMirror paramOfGenericOfInteger =
MoreTypes.asMemberOf(types, genericParamsOfInteger, tParam);
- EquivalenceTester tester = EquivalenceTester.of(MoreTypes.equivalence())
- .addEquivalenceGroup(fieldOfNumberParams, paramOfNumberParams, fieldOfGenericOfNumber,
- paramOfGenericOfNumber, numberType)
- .addEquivalenceGroup(fieldOfStringParams, paramOfStringParams, stringType)
- .addEquivalenceGroup(fieldOfGenericOfInteger, paramOfGenericOfInteger, integerType);
+ EquivalenceTester tester =
+ EquivalenceTester.of(MoreTypes.equivalence())
+ .addEquivalenceGroup(
+ fieldOfNumberParams,
+ paramOfNumberParams,
+ fieldOfGenericOfNumber,
+ paramOfGenericOfNumber,
+ numberType)
+ .addEquivalenceGroup(fieldOfStringParams, paramOfStringParams, stringType)
+ .addEquivalenceGroup(fieldOfGenericOfInteger, paramOfGenericOfInteger, integerType);
tester.test();
}
-
- private static class Params {
- @SuppressWarnings("unused") T t;
- @SuppressWarnings("unused") void add(T t) {}
- }
- private static class NumberParams extends Params {}
- private static class StringParams extends Params {}
- private static class GenericParams extends Params {}
-
- private static final ErrorType FAKE_ERROR_TYPE = new ErrorType() {
- @Override
- public TypeKind getKind() {
- return TypeKind.ERROR;
- }
- @Override
- public R accept(TypeVisitor v, P p) {
- return v.visitError(this, p);
- }
-
- @Override
- public List extends TypeMirror> getTypeArguments() {
- return ImmutableList.of();
- }
-
- @Override
- public TypeMirror getEnclosingType() {
- return null;
- }
+ private static class Params {
+ @SuppressWarnings("unused")
+ T t;
- @Override
- public Element asElement() {
- return null;
- }
+ @SuppressWarnings("unused")
+ void add(T t) {}
+ }
- // JDK8 Compatibility:
+ private static class NumberParams extends Params {}
- public A[] getAnnotationsByType(Class annotationType) {
- return null;
- }
+ private static class StringParams extends Params {}
- public A getAnnotation(Class annotationType) {
- return null;
- }
+ private static class GenericParams extends Params {}
- public List extends AnnotationMirror> getAnnotationMirrors() {
- return null;
- }
- };
+ private static final ErrorType FAKE_ERROR_TYPE =
+ new ErrorType() {
+ @Override
+ public TypeKind getKind() {
+ return TypeKind.ERROR;
+ }
+
+ @Override
+ public R accept(TypeVisitor v, P p) {
+ return v.visitError(this, p);
+ }
+
+ @Override
+ public ImmutableList extends TypeMirror> getTypeArguments() {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public @Nullable TypeMirror getEnclosingType() {
+ return null;
+ }
+
+ @Override
+ public @Nullable Element asElement() {
+ return null;
+ }
+
+ @Override
+ public A @Nullable [] getAnnotationsByType(Class annotationType) {
+ return null;
+ }
+
+ @Override
+ public @Nullable A getAnnotation(Class annotationType) {
+ return null;
+ }
+
+ @Override
+ @SuppressWarnings("MutableMethodReturnType")
+ public List extends AnnotationMirror> getAnnotationMirrors() {
+ return ImmutableList.of();
+ }
+ };
@Test
public void testIsConversionFromObjectUnchecked_yes() {
diff --git a/common/src/test/java/com/google/auto/common/OverridesTest.java b/common/src/test/java/com/google/auto/common/OverridesTest.java
index afb797606a..8d77fc7631 100644
--- a/common/src/test/java/com/google/auto/common/OverridesTest.java
+++ b/common/src/test/java/com/google/auto/common/OverridesTest.java
@@ -17,6 +17,7 @@
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Objects.requireNonNull;
import static javax.lang.model.util.ElementFilter.methodsIn;
import com.google.common.base.Converter;
@@ -57,6 +58,7 @@
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -77,8 +79,8 @@
@RunWith(Parameterized.class)
public class OverridesTest {
@Parameterized.Parameters(name = "{0}")
- public static ImmutableList data() {
- return ImmutableList.of(CompilerType.JAVAC, CompilerType.ECJ);
+ public static CompilerType[] data() {
+ return CompilerType.values();
}
@Rule public CompilationRule compilation = new CompilationRule();
@@ -103,6 +105,7 @@ void initUtils(OverridesTest test) {
abstract void initUtils(OverridesTest test);
}
+
private final CompilerType compilerType;
private Types typeUtils;
@@ -126,13 +129,20 @@ public void initializeTestElements() {
static class TypesForInheritance {
interface One {
void m();
+
void m(String x);
+
void n();
+
+ Number number();
}
interface Two {
void m();
+
void m(int x);
+
+ Integer number();
}
static class Parent {
@@ -142,28 +152,70 @@ public void m() {}
static class ChildOfParent extends Parent {}
static class ChildOfOne implements One {
- @Override public void m() {}
- @Override public void m(String x) {}
- @Override public void n() {}
+ @Override
+ public void m() {}
+
+ @Override
+ public void m(String x) {}
+
+ @Override
+ public void n() {}
+
+ @Override
+ public Number number() {
+ return 0;
+ }
}
static class ChildOfOneAndTwo implements One, Two {
- @Override public void m() {}
- @Override public void m(String x) {}
- @Override public void m(int x) {}
- @Override public void n() {}
+ @Override
+ public void m() {}
+
+ @Override
+ public void m(String x) {}
+
+ @Override
+ public void m(int x) {}
+
+ @Override
+ public void n() {}
+
+ @Override
+ public Integer number() {
+ return 0;
+ }
}
static class ChildOfParentAndOne extends Parent implements One {
- @Override public void m() {}
- @Override public void m(String x) {}
- @Override public void n() {}
+ @Override
+ public void m() {}
+
+ @Override
+ public void m(String x) {}
+
+ @Override
+ public void n() {}
+
+ @Override
+ public Number number() {
+ return 0;
+ }
}
static class ChildOfParentAndOneAndTwo extends Parent implements One, Two {
- @Override public void m(String x) {}
- @Override public void m(int x) {}
- @Override public void n() {}
+ @Override
+ public void m(String x) {}
+
+ @Override
+ public void m(int x) {}
+
+ @Override
+ public void n() {}
+
+ @Override
+ public Integer number() {
+ return 0;
+ }
}
abstract static class AbstractChildOfOne implements One {}
@@ -171,6 +223,8 @@ abstract static class AbstractChildOfOne implements One {}
abstract static class AbstractChildOfOneAndTwo implements One, Two {}
abstract static class AbstractChildOfParentAndOneAndTwo extends Parent implements One, Two {}
+
+ interface ExtendingOneAndTwo extends One, Two {}
}
static class MoreTypesForInheritance {
@@ -194,14 +248,20 @@ interface HasContributionType {
abstract static class BindingDeclaration implements HasKey {
abstract Optional bindingElement();
+
abstract Optional contributingModule();
}
- abstract static class MultibindingDeclaration
- extends BindingDeclaration implements HasBindingType, HasContributionType {
- @Override public abstract Key key();
- @Override public abstract ContributionType contributionType();
- @Override public abstract BindingType bindingType();
+ abstract static class MultibindingDeclaration extends BindingDeclaration
+ implements HasBindingType, HasContributionType {
+ @Override
+ public abstract Key key();
+
+ @Override
+ public abstract ContributionType contributionType();
+
+ @Override
+ public abstract BindingType bindingType();
}
}
@@ -221,16 +281,26 @@ static class Child extends PrivateParent {}
}
static class TypesForGenerics {
- interface XCollection {
+ interface GCollection {
boolean add(E x);
}
- interface XList extends XCollection {
- @Override public boolean add(E x);
+ interface GList extends GCollection {
+ @Override
+ boolean add(E x);
}
- static class StringList implements XList {
- @Override public boolean add(String x) {
+ static class StringList implements GList {
+ @Override
+ public boolean add(String x) {
+ return false;
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ static class RawList implements GList {
+ @Override
+ public boolean add(Object x) {
return false;
}
}
@@ -243,7 +313,8 @@ void frob(List x) {}
}
static class RawChildOfRaw extends RawParent {
- @Override void frob(List x) {}
+ @Override
+ void frob(List x) {}
}
static class NonRawParent {
@@ -251,7 +322,8 @@ void frob(List x) {}
}
static class RawChildOfNonRaw extends NonRawParent {
- @Override void frob(List x) {}
+ @Override
+ void frob(List x) {}
}
}
@@ -291,8 +363,9 @@ public void overridesRaw() {
// since the two Es are not the same.
@Test
public void overridesDiamond() {
- checkOverridesInSet(ImmutableSet.>of(
- Collection.class, List.class, AbstractCollection.class, AbstractList.class));
+ checkOverridesInSet(
+ ImmutableSet.>of(
+ Collection.class, List.class, AbstractCollection.class, AbstractList.class));
}
private void checkOverridesInContainedClasses(Class> container) {
@@ -324,10 +397,13 @@ private void checkOverridesInSet(ImmutableSet> testClasses) {
expect
.withMessage(
"%s.%s overrides %s.%s in %s: javac says %s, we say %s",
- overrider.getEnclosingElement(), overrider,
- overridden.getEnclosingElement(), overridden,
+ overrider.getEnclosingElement(),
+ overrider,
+ overridden.getEnclosingElement(),
+ overridden,
in,
- javacSays, weSay)
+ javacSays,
+ weSay)
.fail();
}
}
@@ -355,7 +431,7 @@ private ExecutableElement getMethod(TypeElement in, String name, TypeKind... par
}
}
assertThat(found).isNotNull();
- return found;
+ return requireNonNull(found);
}
// These skeletal parallels to the real collection classes ensure that the test is independent
@@ -375,8 +451,8 @@ public boolean add(E e) {
}
}
- private abstract static class XAbstractList
- extends XAbstractCollection implements XList {
+ private abstract static class XAbstractList extends XAbstractCollection
+ implements XList {
@Override
public boolean add(E e) {
return true;
@@ -440,7 +516,7 @@ private abstract static class StringToRangeConverter>
extends Converter> {
@Override
protected String doBackward(Range b) {
- return null;
+ return "";
}
}
@@ -470,9 +546,8 @@ public void methodFromSuperclasses() {
explicitOverrides.methodFromSuperclasses(xAbstractStringList, add);
assertThat(addInAbstractStringList).isNull();
- ExecutableElement addInStringList =
- explicitOverrides.methodFromSuperclasses(xStringList, add);
- assertThat(addInStringList.getEnclosingElement()).isEqualTo(xAbstractList);
+ ExecutableElement addInStringList = explicitOverrides.methodFromSuperclasses(xStringList, add);
+ assertThat(requireNonNull(addInStringList).getEnclosingElement()).isEqualTo(xAbstractList);
}
@Test
@@ -487,20 +562,21 @@ public void methodFromSuperinterfaces() {
ExecutableElement addInAbstractStringList =
explicitOverrides.methodFromSuperinterfaces(xAbstractStringList, add);
- assertThat(addInAbstractStringList.getEnclosingElement()).isEqualTo(xCollection);
+ assertThat(requireNonNull(addInAbstractStringList).getEnclosingElement())
+ .isEqualTo(xCollection);
ExecutableElement addInNumberList =
explicitOverrides.methodFromSuperinterfaces(xNumberList, add);
- assertThat(addInNumberList.getEnclosingElement()).isEqualTo(xAbstractList);
+ assertThat(requireNonNull(addInNumberList).getEnclosingElement()).isEqualTo(xAbstractList);
- ExecutableElement addInList =
- explicitOverrides.methodFromSuperinterfaces(xList, add);
- assertThat(addInList.getEnclosingElement()).isEqualTo(xCollection);
+ ExecutableElement addInList = explicitOverrides.methodFromSuperinterfaces(xList, add);
+ assertThat(requireNonNull(addInList).getEnclosingElement()).isEqualTo(xCollection);
}
- private void assertTypeListsEqual(List actual, List expected) {
- assertThat(actual.size()).isEqualTo(expected.size());
- for (int i = 0; i < actual.size(); i++) {
+ private void assertTypeListsEqual(@Nullable List actual, List expected) {
+ requireNonNull(actual);
+ assertThat(actual).hasSize(expected.size());
+ for (int i = 0; i < actual.size(); i++) {
assertThat(typeUtils.isSameType(actual.get(i), expected.get(i))).isTrue();
}
}
@@ -552,10 +628,11 @@ private void evaluate(File dummySourceFile) throws Throwable {
// it hard for ecj to find the boot class path. Elsewhere it is unnecessary but harmless.
File rtJar = new File(StandardSystemProperty.JAVA_HOME.value() + "/lib/rt.jar");
if (rtJar.exists()) {
- List bootClassPath = ImmutableList.builder()
- .add(rtJar)
- .addAll(fileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH))
- .build();
+ List bootClassPath =
+ ImmutableList.builder()
+ .add(rtJar)
+ .addAll(fileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH))
+ .build();
fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
}
Iterable extends JavaFileObject> sources = fileManager.getJavaFileObjects(dummySourceFile);
@@ -583,8 +660,7 @@ public SourceVersion getSupportedSourceVersion() {
}
@Override
- public boolean process(
- Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
ecjCompilation.elements = processingEnv.getElementUtils();
ecjCompilation.types = processingEnv.getTypeUtils();
@@ -643,24 +719,24 @@ private static String erasedToString(TypeMirror type) {
private static final TypeVisitor ERASED_STRING_TYPE_VISITOR =
new SimpleTypeVisitor6() {
- @Override
- protected String defaultAction(TypeMirror e, Void p) {
- return e.toString();
- }
+ @Override
+ protected String defaultAction(TypeMirror e, Void p) {
+ return e.toString();
+ }
- @Override
- public String visitArray(ArrayType t, Void p) {
- return visit(t.getComponentType()) + "[]";
- }
+ @Override
+ public String visitArray(ArrayType t, Void p) {
+ return visit(t.getComponentType()) + "[]";
+ }
- @Override
- public String visitDeclared(DeclaredType t, Void p) {
- return MoreElements.asType(t.asElement()).getQualifiedName().toString();
- }
+ @Override
+ public String visitDeclared(DeclaredType t, Void p) {
+ return MoreElements.asType(t.asElement()).getQualifiedName().toString();
+ }
- @Override
- public String visitTypeVariable(TypeVariable t, Void p) {
- return visit(t.getUpperBound());
- }
- };
+ @Override
+ public String visitTypeVariable(TypeVariable t, Void p) {
+ return visit(t.getUpperBound());
+ }
+ };
}
diff --git a/common/src/test/java/com/google/auto/common/SimpleAnnotationMirrorTest.java b/common/src/test/java/com/google/auto/common/SimpleAnnotationMirrorTest.java
index d73e1b6c59..0bad83db65 100644
--- a/common/src/test/java/com/google/auto/common/SimpleAnnotationMirrorTest.java
+++ b/common/src/test/java/com/google/auto/common/SimpleAnnotationMirrorTest.java
@@ -46,6 +46,7 @@ public class SimpleAnnotationMirrorTest {
@interface MultipleValues {
int value1();
+
int value2();
}
diff --git a/common/src/test/java/com/google/auto/common/SimpleTypeAnnotationValueTest.java b/common/src/test/java/com/google/auto/common/SimpleTypeAnnotationValueTest.java
index 4fc61b51d6..ea85365bae 100644
--- a/common/src/test/java/com/google/auto/common/SimpleTypeAnnotationValueTest.java
+++ b/common/src/test/java/com/google/auto/common/SimpleTypeAnnotationValueTest.java
@@ -28,6 +28,7 @@
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleAnnotationValueVisitor8;
import javax.lang.model.util.Types;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -70,18 +71,21 @@ public void declaredType() {
@Test
public void visitorMethod() {
- SimpleTypeAnnotationValue.of(objectType).accept(new SimpleAnnotationValueVisitor8(){
- @Override
- public Void visitType(TypeMirror typeMirror, Void aVoid) {
- // do nothing, expected case
- return null;
- }
+ SimpleTypeAnnotationValue.of(objectType)
+ .accept(
+ new SimpleAnnotationValueVisitor8<@Nullable Void, @Nullable Void>() {
+ @Override
+ public @Nullable Void visitType(TypeMirror typeMirror, @Nullable Void aVoid) {
+ // do nothing, expected case
+ return null;
+ }
- @Override
- protected Void defaultAction(Object o, Void aVoid) {
- throw new AssertionError();
- }
- }, null);
+ @Override
+ protected @Nullable Void defaultAction(Object o, @Nullable Void aVoid) {
+ throw new AssertionError();
+ }
+ },
+ null);
}
@Test
diff --git a/common/src/test/java/com/google/auto/common/SuperficialValidationTest.java b/common/src/test/java/com/google/auto/common/SuperficialValidationTest.java
index 15e54fff52..c9bcf77847 100644
--- a/common/src/test/java/com/google/auto/common/SuperficialValidationTest.java
+++ b/common/src/test/java/com/google/auto/common/SuperficialValidationTest.java
@@ -35,231 +35,263 @@
public class SuperficialValidationTest {
@Test
public void missingReturnType() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "abstract class TestClass {",
- " abstract MissingType blah();",
- "}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass",
+ "package test;",
+ "",
+ "abstract class TestClass {",
+ " abstract MissingType blah();",
+ "}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
+ }
+ })
.failsToCompile();
}
@Test
public void missingGenericReturnType() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "abstract class TestClass {",
- " abstract MissingType> blah();",
- "}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass",
+ "package test;",
+ "",
+ "abstract class TestClass {",
+ " abstract MissingType> blah();",
+ "}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
+ }
+ })
.failsToCompile();
}
@Test
public void missingReturnTypeTypeParameter() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "import java.util.Map;",
- "import java.util.Set;",
- "",
- "abstract class TestClass {",
- " abstract Map, MissingType>> blah();",
- "}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass",
+ "package test;",
+ "",
+ "import java.util.Map;",
+ "import java.util.Set;",
+ "",
+ "abstract class TestClass {",
+ " abstract Map, MissingType>> blah();",
+ "}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
+ }
+ })
.failsToCompile();
}
@Test
public void missingTypeParameter() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "class TestClass {}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass", //
+ "package test;",
+ "",
+ "class TestClass {}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
+ }
+ })
.failsToCompile();
}
@Test
public void missingParameterType() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "abstract class TestClass {",
- " abstract void foo(MissingType x);",
- "}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass",
+ "package test;",
+ "",
+ "abstract class TestClass {",
+ " abstract void foo(MissingType x);",
+ "}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
+ }
+ })
.failsToCompile();
}
@Test
public void missingAnnotation() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "@MissingAnnotation",
- "class TestClass {}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass", //
+ "package test;",
+ "",
+ "@MissingAnnotation",
+ "class TestClass {}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
+ }
+ })
.failsToCompile();
}
@Test
public void handlesRecursiveTypeParams() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "class TestClass> {}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass", //
+ "package test;",
+ "",
+ "class TestClass> {}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isTrue();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isTrue();
+ }
+ })
.compilesWithoutError();
}
@Test
public void handlesRecursiveType() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "abstract class TestClass {",
- " abstract TestClass foo(TestClass x);",
- "}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass",
+ "package test;",
+ "",
+ "abstract class TestClass {",
+ " abstract TestClass foo(TestClass x);",
+ "}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isTrue();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isTrue();
+ }
+ })
.compilesWithoutError();
}
@Test
public void missingWildcardBound() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "import java.util.Set;",
- "",
- "class TestClass {",
- " Set extends MissingType> extendsTest() {",
- " return null;",
- " }",
- "",
- " Set super MissingType> superTest() {",
- " return null;",
- " }",
- "}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass",
+ "package test;",
+ "",
+ "import java.util.Set;",
+ "",
+ "class TestClass {",
+ " Set extends MissingType> extendsTest() {",
+ " return null;",
+ " }",
+ "",
+ " Set super MissingType> superTest() {",
+ " return null;",
+ " }",
+ "}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
+ }
+ })
.failsToCompile();
}
@Test
public void missingIntersection() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
- "test.TestClass",
- "package test;",
- "",
- "class TestClass {}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.TestClass",
+ "package test;",
+ "",
+ "class TestClass {}");
assertAbout(javaSource())
.that(javaFileObject)
- .processedWith(new AssertingProcessor() {
- @Override void runAssertions() {
- TypeElement testClassElement =
- processingEnv.getElementUtils().getTypeElement("test.TestClass");
- assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
- }
- })
+ .processedWith(
+ new AssertingProcessor() {
+ @Override
+ void runAssertions() {
+ TypeElement testClassElement =
+ processingEnv.getElementUtils().getTypeElement("test.TestClass");
+ assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse();
+ }
+ })
.failsToCompile();
}
@Test
public void invalidAnnotationValue() {
- JavaFileObject javaFileObject = JavaFileObjects.forSourceLines("test.Outer",
- "package test;",
- "",
- "final class Outer {",
- " @interface TestAnnotation {",
- " Class[] classes();",
- " }",
- "",
- " @TestAnnotation(classes = Foo)",
- " static class TestClass {}",
- "}");
+ JavaFileObject javaFileObject =
+ JavaFileObjects.forSourceLines(
+ "test.Outer",
+ "package test;",
+ "",
+ "final class Outer {",
+ " @interface TestAnnotation {",
+ " Class[] classes();",
+ " }",
+ "",
+ " @TestAnnotation(classes = Foo)",
+ " static class TestClass {}",
+ "}");
assertAbout(javaSource())
.that(javaFileObject)
.processedWith(
diff --git a/common/src/test/java/com/google/auto/common/VisibilityTest.java b/common/src/test/java/com/google/auto/common/VisibilityTest.java
index 6a80b7af70..fc5e630b3d 100644
--- a/common/src/test/java/com/google/auto/common/VisibilityTest.java
+++ b/common/src/test/java/com/google/auto/common/VisibilityTest.java
@@ -39,9 +39,10 @@ public class VisibilityTest {
public void packageVisibility() {
assertThat(Visibility.ofElement(compilation.getElements().getPackageElement("java.lang")))
.isEqualTo(PUBLIC);
- assertThat(Visibility.ofElement(
- compilation.getElements().getPackageElement("com.google.auto.common")))
- .isEqualTo(PUBLIC);
+ assertThat(
+ Visibility.ofElement(
+ compilation.getElements().getPackageElement("com.google.auto.common")))
+ .isEqualTo(PUBLIC);
}
@Test
@@ -61,32 +62,44 @@ public void moduleVisibility() throws IllegalAccessException, InvocationTargetEx
@SuppressWarnings("unused")
public static class PublicClass {
public static class NestedPublicClass {}
+
protected static class NestedProtectedClass {}
+
static class NestedDefaultClass {}
+
private static class NestedPrivateClass {}
}
@SuppressWarnings("unused")
protected static class ProtectedClass {
public static class NestedPublicClass {}
+
protected static class NestedProtectedClass {}
+
static class NestedDefaultClass {}
+
private static class NestedPrivateClass {}
}
@SuppressWarnings("unused")
static class DefaultClass {
public static class NestedPublicClass {}
+
protected static class NestedProtectedClass {}
+
static class NestedDefaultClass {}
+
private static class NestedPrivateClass {}
}
@SuppressWarnings("unused")
private static class PrivateClass {
public static class NestedPublicClass {}
+
protected static class NestedProtectedClass {}
+
static class NestedDefaultClass {}
+
private static class NestedPrivateClass {}
}
@@ -94,21 +107,25 @@ private static class NestedPrivateClass {}
public void classVisibility() {
assertThat(Visibility.ofElement(compilation.getElements().getTypeElement("java.util.Map")))
.isEqualTo(PUBLIC);
- assertThat(Visibility.ofElement(
- compilation.getElements().getTypeElement("java.util.Map.Entry")))
- .isEqualTo(PUBLIC);
- assertThat(Visibility.ofElement(
- compilation.getElements().getTypeElement(PublicClass.class.getCanonicalName())))
- .isEqualTo(PUBLIC);
- assertThat(Visibility.ofElement(
- compilation.getElements().getTypeElement(ProtectedClass.class.getCanonicalName())))
- .isEqualTo(PROTECTED);
- assertThat(Visibility.ofElement(
- compilation.getElements().getTypeElement(DefaultClass.class.getCanonicalName())))
- .isEqualTo(DEFAULT);
- assertThat(Visibility.ofElement(
- compilation.getElements().getTypeElement(PrivateClass.class.getCanonicalName())))
- .isEqualTo(PRIVATE);
+ assertThat(
+ Visibility.ofElement(compilation.getElements().getTypeElement("java.util.Map.Entry")))
+ .isEqualTo(PUBLIC);
+ assertThat(
+ Visibility.ofElement(
+ compilation.getElements().getTypeElement(PublicClass.class.getCanonicalName())))
+ .isEqualTo(PUBLIC);
+ assertThat(
+ Visibility.ofElement(
+ compilation.getElements().getTypeElement(ProtectedClass.class.getCanonicalName())))
+ .isEqualTo(PROTECTED);
+ assertThat(
+ Visibility.ofElement(
+ compilation.getElements().getTypeElement(DefaultClass.class.getCanonicalName())))
+ .isEqualTo(DEFAULT);
+ assertThat(
+ Visibility.ofElement(
+ compilation.getElements().getTypeElement(PrivateClass.class.getCanonicalName())))
+ .isEqualTo(PRIVATE);
}
@Test
@@ -118,14 +135,11 @@ public void effectiveClassVisibility() {
assertThat(effectiveVisiblityOfClass(DefaultClass.class)).isEqualTo(DEFAULT);
assertThat(effectiveVisiblityOfClass(PrivateClass.class)).isEqualTo(PRIVATE);
- assertThat(effectiveVisiblityOfClass(PublicClass.NestedPublicClass.class))
- .isEqualTo(PUBLIC);
+ assertThat(effectiveVisiblityOfClass(PublicClass.NestedPublicClass.class)).isEqualTo(PUBLIC);
assertThat(effectiveVisiblityOfClass(PublicClass.NestedProtectedClass.class))
.isEqualTo(PROTECTED);
- assertThat(effectiveVisiblityOfClass(PublicClass.NestedDefaultClass.class))
- .isEqualTo(DEFAULT);
- assertThat(effectiveVisiblityOfClass(PublicClass.NestedPrivateClass.class))
- .isEqualTo(PRIVATE);
+ assertThat(effectiveVisiblityOfClass(PublicClass.NestedDefaultClass.class)).isEqualTo(DEFAULT);
+ assertThat(effectiveVisiblityOfClass(PublicClass.NestedPrivateClass.class)).isEqualTo(PRIVATE);
assertThat(effectiveVisiblityOfClass(ProtectedClass.NestedPublicClass.class))
.isEqualTo(PROTECTED);
@@ -136,23 +150,17 @@ public void effectiveClassVisibility() {
assertThat(effectiveVisiblityOfClass(ProtectedClass.NestedPrivateClass.class))
.isEqualTo(PRIVATE);
- assertThat(effectiveVisiblityOfClass(DefaultClass.NestedPublicClass.class))
- .isEqualTo(DEFAULT);
+ assertThat(effectiveVisiblityOfClass(DefaultClass.NestedPublicClass.class)).isEqualTo(DEFAULT);
assertThat(effectiveVisiblityOfClass(DefaultClass.NestedProtectedClass.class))
.isEqualTo(DEFAULT);
- assertThat(effectiveVisiblityOfClass(DefaultClass.NestedDefaultClass.class))
- .isEqualTo(DEFAULT);
- assertThat(effectiveVisiblityOfClass(DefaultClass.NestedPrivateClass.class))
- .isEqualTo(PRIVATE);
+ assertThat(effectiveVisiblityOfClass(DefaultClass.NestedDefaultClass.class)).isEqualTo(DEFAULT);
+ assertThat(effectiveVisiblityOfClass(DefaultClass.NestedPrivateClass.class)).isEqualTo(PRIVATE);
- assertThat(effectiveVisiblityOfClass(PrivateClass.NestedPublicClass.class))
- .isEqualTo(PRIVATE);
+ assertThat(effectiveVisiblityOfClass(PrivateClass.NestedPublicClass.class)).isEqualTo(PRIVATE);
assertThat(effectiveVisiblityOfClass(PrivateClass.NestedProtectedClass.class))
.isEqualTo(PRIVATE);
- assertThat(effectiveVisiblityOfClass(PrivateClass.NestedDefaultClass.class))
- .isEqualTo(PRIVATE);
- assertThat(effectiveVisiblityOfClass(PrivateClass.NestedPrivateClass.class))
- .isEqualTo(PRIVATE);
+ assertThat(effectiveVisiblityOfClass(PrivateClass.NestedDefaultClass.class)).isEqualTo(PRIVATE);
+ assertThat(effectiveVisiblityOfClass(PrivateClass.NestedPrivateClass.class)).isEqualTo(PRIVATE);
}
private Visibility effectiveVisiblityOfClass(Class> clazz) {
diff --git a/factory/README.md b/factory/README.md
index f5874fe9bd..5eccd90781 100644
--- a/factory/README.md
+++ b/factory/README.md
@@ -10,7 +10,9 @@ AutoWhat‽
AutoFactory generates factories that can be used on their own or with [JSR-330](http://jcp.org/en/jsr/detail?id=330)-compatible [dependency injectors](http://en.wikipedia.org/wiki/Dependency_injection) from a simple annotation. Any combination of parameters can either be passed through factory methods or provided to the factory at construction time. They can implement interfaces or extend abstract classes. They're what you would have written, but without the bugs.
-Save time. Save code. Save sanity.
+[Dagger](https://dagger.dev/) users: Dagger's own
+[assisted injection](https://dagger.dev/dev-guide/assisted-injection.html) is
+now usually preferred to AutoFactory.
Example
-------
@@ -58,6 +60,20 @@ final class SomeClassFactory {
> framework-specific annotations from Guice, Spring, etc are not
> supported (though these all support JSR-330)
+Mocking
+-------
+
+By default, the factory class generated by AutoFactory is final, and thus cannot
+be mocked. The generated factory class can be made mockable by setting
+`allowSubclasses = true`, as follows:
+
+```java
+@AutoFactory(allowSubclasses = true)
+final class SomeClass {
+ // …
+}
+```
+
Download
--------
diff --git a/factory/pom.xml b/factory/pom.xml
index 1003bb23dc..6e203abaf1 100644
--- a/factory/pom.xml
+++ b/factory/pom.xml
@@ -19,12 +19,6 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
-
- org.sonatype.oss
- oss-parent
- 7
-
-
com.google.auto.factory
auto-factory
HEAD-SNAPSHOT
@@ -36,11 +30,11 @@
UTF-8
- 1.0
- 1.8
+ 1.0.1
+ 1.10.1
1.8
- 30.1.1-jre
- 1.1.2
+ 31.1-jre
+ 1.1.3
@@ -67,11 +61,24 @@
http://www.google.com
+
+
+ sonatype-nexus-snapshots
+ Sonatype Nexus Snapshots
+ https://oss.sonatype.org/content/repositories/snapshots/
+
+
+ sonatype-nexus-staging
+ Nexus Release Repository
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+
com.google.auto
auto-common
- 1.0
+ 1.2.1
com.google.auto.value
@@ -141,7 +148,7 @@