aboutsummaryrefslogtreecommitdiff
path: root/value/src/main/java/com/google/auto/value/extension/toprettystring/processor/ExtensionClassTypeSpecBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'value/src/main/java/com/google/auto/value/extension/toprettystring/processor/ExtensionClassTypeSpecBuilder.java')
-rw-r--r--value/src/main/java/com/google/auto/value/extension/toprettystring/processor/ExtensionClassTypeSpecBuilder.java183
1 files changed, 22 insertions, 161 deletions
diff --git a/value/src/main/java/com/google/auto/value/extension/toprettystring/processor/ExtensionClassTypeSpecBuilder.java b/value/src/main/java/com/google/auto/value/extension/toprettystring/processor/ExtensionClassTypeSpecBuilder.java
index e2381f7e..a8bcef53 100644
--- a/value/src/main/java/com/google/auto/value/extension/toprettystring/processor/ExtensionClassTypeSpecBuilder.java
+++ b/value/src/main/java/com/google/auto/value/extension/toprettystring/processor/ExtensionClassTypeSpecBuilder.java
@@ -16,29 +16,20 @@
package com.google.auto.value.extension.toprettystring.processor;
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
import static com.google.auto.common.GeneratedAnnotationSpecs.generatedAnnotationSpec;
-import static com.google.auto.common.MoreElements.getPackage;
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
import static com.google.auto.common.MoreStreams.toImmutableList;
-import static com.google.auto.common.MoreStreams.toImmutableSet;
-import static com.google.auto.value.extension.toprettystring.processor.Annotations.getAnnotationMirror;
-import static com.google.common.collect.Sets.union;
+import static com.google.auto.common.MoreStreams.toImmutableMap;
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toSet;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.FINAL;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.common.Visibility;
import com.google.auto.value.extension.AutoValueExtension;
import com.google.auto.value.extension.AutoValueExtension.Context;
-import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableMap;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
@@ -46,19 +37,11 @@ import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
-import java.lang.annotation.Inherited;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import javax.lang.model.SourceVersion;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.QualifiedNameable;
-import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
-import javax.lang.model.util.Types;
/**
* A factory for {@link TypeSpec}s used in {@link AutoValueExtension} implementations.
@@ -68,15 +51,11 @@ import javax.lang.model.util.Types;
* location to consolidate the code.
*/
final class ExtensionClassTypeSpecBuilder {
- private static final String AUTO_VALUE_PACKAGE_NAME = "com.google.auto.value.";
- private static final String AUTO_VALUE_NAME = AUTO_VALUE_PACKAGE_NAME + "AutoValue";
- private static final String COPY_ANNOTATIONS_NAME = AUTO_VALUE_NAME + ".CopyAnnotations";
private final Context context;
private final String className;
private final String classToExtend;
private final boolean isFinal;
- private final Types types;
private final Elements elements;
private final SourceVersion sourceVersion;
@@ -86,7 +65,6 @@ final class ExtensionClassTypeSpecBuilder {
this.className = className;
this.classToExtend = classToExtend;
this.isFinal = isFinal;
- this.types = context.processingEnvironment().getTypeUtils();
this.elements = context.processingEnvironment().getElementUtils();
this.sourceVersion = context.processingEnvironment().getSourceVersion();
}
@@ -101,7 +79,10 @@ final class ExtensionClassTypeSpecBuilder {
TypeSpec.Builder builder =
classBuilder(className)
.superclass(superType())
- .addAnnotations(copiedClassAnnotations(context.autoValueClass()))
+ .addAnnotations(
+ context.classAnnotationsToCopy(context.autoValueClass()).stream()
+ .map(AnnotationSpec::get)
+ .collect(toImmutableList()))
.addTypeVariables(annotatedTypeVariableNames())
.addModifiers(isFinal ? FINAL : ABSTRACT)
.addMethod(constructor());
@@ -139,152 +120,32 @@ final class ExtensionClassTypeSpecBuilder {
private MethodSpec constructor() {
MethodSpec.Builder constructor = constructorBuilder();
+ // TODO(b/35944623): Replace this with a standard way of avoiding keywords.
+ Set<String> propertyNames = context.properties().keySet();
+ ImmutableMap<String, String> parameterNames =
+ propertyNames.stream()
+ .collect(toImmutableMap(name -> name, name -> generateIdentifier(name, propertyNames)));
context
.propertyTypes()
- .forEach((name, type) -> constructor.addParameter(annotatedType(type), name + "$"));
+ .forEach(
+ (name, type) ->
+ constructor.addParameter(annotatedType(type), parameterNames.get(name)));
String superParams =
- context.properties().keySet().stream().map(n -> n + "$").collect(joining(", "));
+ context.properties().keySet().stream().map(parameterNames::get).collect(joining(", "));
constructor.addStatement("super($L)", superParams);
return constructor.build();
}
- /**
- * True if the given class name is in the com.google.auto.value package or a subpackage. False if
- * the class name contains {@code Test}, since many AutoValue tests under com.google.auto.value
- * define their own annotations.
- */
- // TODO(b/122509249): Move code copied from com.google.auto.value.processor to auto-common.
- private boolean isInAutoValuePackage(String className) {
- return className.startsWith(AUTO_VALUE_PACKAGE_NAME) && !className.contains("Test");
- }
-
- /**
- * Returns the fully-qualified name of an annotation-mirror, e.g.
- * "com.google.auto.value.AutoValue".
- */
- // TODO(b/122509249): Move code copied from com.google.auto.value.processor to auto-common.
- private static String getAnnotationFqName(AnnotationMirror annotation) {
- return ((QualifiedNameable) annotation.getAnnotationType().asElement())
- .getQualifiedName()
- .toString();
- }
-
- // TODO(b/122509249): Move code copied from com.google.auto.value.processor to auto-common.
- private boolean annotationVisibleFrom(AnnotationMirror annotation, Element from) {
- Element annotationElement = annotation.getAnnotationType().asElement();
- Visibility visibility = Visibility.effectiveVisibilityOfElement(annotationElement);
- switch (visibility) {
- case PUBLIC:
- return true;
- case PROTECTED:
- // If the annotation is protected, it must be inside another class, call it C. If our
- // @AutoValue class is Foo then, for the annotation to be visible, either Foo must be in
- // the same package as C or Foo must be a subclass of C. If the annotation is visible from
- // Foo then it is also visible from our generated subclass AutoValue_Foo.
- // The protected case only applies to method annotations. An annotation on the
- // AutoValue_Foo class itself can't be protected, even if AutoValue_Foo ultimately
- // inherits from the class that defines the annotation. The JLS says "Access is permitted
- // only within the body of a subclass":
- // https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.1
- // AutoValue_Foo is a top-level class, so an annotation on it cannot be in the body of a
- // subclass of anything.
- return getPackage(annotationElement).equals(getPackage(from))
- || types.isSubtype(from.asType(), annotationElement.getEnclosingElement().asType());
- case DEFAULT:
- return getPackage(annotationElement).equals(getPackage(from));
- default:
- return false;
+ private static String generateIdentifier(String name, Set<String> existingNames) {
+ if (!SourceVersion.isKeyword(name)) {
+ return name;
}
- }
-
- /** Implements the semantics of {@code AutoValue.CopyAnnotations}; see its javadoc. */
- // TODO(b/122509249): Move code copied from com.google.auto.value.processor to auto-common.
- private ImmutableList<AnnotationMirror> annotationsToCopy(
- Element autoValueType, Element typeOrMethod, Set<String> excludedAnnotations) {
- ImmutableList.Builder<AnnotationMirror> result = ImmutableList.builder();
- for (AnnotationMirror annotation : typeOrMethod.getAnnotationMirrors()) {
- String annotationFqName = getAnnotationFqName(annotation);
- // To be included, the annotation should not be in com.google.auto.value,
- // and it should not be in the excludedAnnotations set.
- if (!isInAutoValuePackage(annotationFqName)
- && !excludedAnnotations.contains(annotationFqName)
- && annotationVisibleFrom(annotation, autoValueType)) {
- result.add(annotation);
+ for (int i = 0; ; i++) {
+ String newName = name + i;
+ if (!existingNames.contains(newName)) {
+ return newName;
}
}
-
- return result.build();
- }
-
- /** Implements the semantics of {@code AutoValue.CopyAnnotations}; see its javadoc. */
- // TODO(b/122509249): Move code copied from com.google.auto.value.processor to auto-common.
- private ImmutableList<AnnotationSpec> copyAnnotations(
- Element autoValueType, Element typeOrMethod, Set<String> excludedAnnotations) {
- ImmutableList<AnnotationMirror> annotationsToCopy =
- annotationsToCopy(autoValueType, typeOrMethod, excludedAnnotations);
- return annotationsToCopy.stream().map(AnnotationSpec::get).collect(toImmutableList());
- }
-
- // TODO(b/122509249): Move code copied from com.google.auto.value.processor to auto-common.
- private static boolean hasAnnotationMirror(Element element, String annotationName) {
- return getAnnotationMirror(element, annotationName).isPresent();
- }
-
- /**
- * Returns the contents of the {@code AutoValue.CopyAnnotations.exclude} element, as a set of
- * {@code TypeMirror} where each type is an annotation type.
- */
- // TODO(b/122509249): Move code copied from com.google.auto.value.processor to auto-common.
- private ImmutableSet<TypeMirror> getExcludedAnnotationTypes(Element element) {
- Optional<AnnotationMirror> maybeAnnotation =
- getAnnotationMirror(element, COPY_ANNOTATIONS_NAME);
- if (!maybeAnnotation.isPresent()) {
- return ImmutableSet.of();
- }
-
- @SuppressWarnings("unchecked")
- List<AnnotationValue> excludedClasses =
- (List<AnnotationValue>) getAnnotationValue(maybeAnnotation.get(), "exclude").getValue();
- return excludedClasses.stream()
- .map(
- annotationValue ->
- MoreTypes.equivalence().wrap((TypeMirror) annotationValue.getValue()))
- // TODO(b/122509249): Move TypeMirrorSet to common package instead of doing this.
- .distinct()
- .map(Wrapper::get)
- .collect(toImmutableSet());
- }
-
- /**
- * Returns the contents of the {@code AutoValue.CopyAnnotations.exclude} element, as a set of
- * strings that are fully-qualified class names.
- */
- // TODO(b/122509249): Move code copied from com.google.auto.value.processor to auto-common.
- private Set<String> getExcludedAnnotationClassNames(Element element) {
- return getExcludedAnnotationTypes(element).stream()
- .map(MoreTypes::asTypeElement)
- .map(typeElement -> typeElement.getQualifiedName().toString())
- .collect(toSet());
- }
-
- // TODO(b/122509249): Move code copied from com.google.auto.value.processor to auto-common.
- private static Set<String> getAnnotationsMarkedWithInherited(Element element) {
- return element.getAnnotationMirrors().stream()
- .filter(a -> isAnnotationPresent(a.getAnnotationType().asElement(), Inherited.class))
- .map(ExtensionClassTypeSpecBuilder::getAnnotationFqName)
- .collect(toSet());
- }
-
- private ImmutableList<AnnotationSpec> copiedClassAnnotations(TypeElement type) {
- // Only copy annotations from a class if it has @AutoValue.CopyAnnotations.
- if (hasAnnotationMirror(type, COPY_ANNOTATIONS_NAME)) {
- Set<String> excludedAnnotations =
- union(getExcludedAnnotationClassNames(type), getAnnotationsMarkedWithInherited(type));
-
- return copyAnnotations(type, type, excludedAnnotations);
- } else {
- return ImmutableList.of();
- }
}
/** Translate a {@link TypeMirror} into a {@link TypeName}, including type annotations. */