diff options
author | Éamonn McManus <emcmanus@google.com> | 2023-04-04 13:37:16 -0700 |
---|---|---|
committer | Google Java Core Libraries <java-libraries-firehose+copybara@google.com> | 2023-04-04 13:38:13 -0700 |
commit | 4f8dbea8a7ab3b6718b45be5fda6f67e84bf0003 (patch) | |
tree | b79c9bf181abfd661e585c98caf8541a6dd915b9 /value/src/main/java/com | |
parent | 1f52972bf5ab9638e8cea7e6cd93d214bc0f7a4a (diff) | |
download | auto-4f8dbea8a7ab3b6718b45be5fda6f67e84bf0003.tar.gz |
Improve generate constructor parameter names in the `@Memoized` extension.
Previously we just added `$` to each name, in case one of them might be a Java keyword. This turns out to cause an issue with Error Prone's `/* foo= */` checked parameter-name comments, because people end up having to write `/* foo$= */` for the check to pass. With the approach here, you'll only have to write a funny parameter name if your property name is a keyword.
RELNOTES=The constructor parameter names in the class generated by `@Memoized` no longer add a `$`.
PiperOrigin-RevId: 521852747
Diffstat (limited to 'value/src/main/java/com')
2 files changed, 50 insertions, 4 deletions
diff --git a/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java b/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java index 65a8c95c..b611ae1e 100644 --- a/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java +++ b/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java @@ -17,6 +17,7 @@ package com.google.auto.value.extension.memoized.processor; import static com.google.auto.common.GeneratedAnnotationSpecs.generatedAnnotationSpec; import static com.google.auto.common.MoreStreams.toImmutableList; +import static com.google.auto.common.MoreStreams.toImmutableMap; import static com.google.auto.common.MoreStreams.toImmutableSet; import static com.google.auto.value.extension.memoized.processor.ClassNames.MEMOIZED_NAME; import static com.google.auto.value.extension.memoized.processor.MemoizedValidator.getAnnotationMirror; @@ -44,6 +45,7 @@ import com.google.auto.common.MoreElements; import com.google.auto.service.AutoService; import com.google.auto.value.extension.AutoValueExtension; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.errorprone.annotations.FormatMethod; import com.squareup.javapoet.AnnotationSpec; @@ -58,6 +60,7 @@ import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.TypeVariableName; import java.util.List; import java.util.Optional; +import java.util.Set; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.SourceVersion; @@ -193,15 +196,36 @@ public final class MemoizeExtension extends AutoValueExtension { 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(); } + private static String generateIdentifier(String name, Set<String> existingNames) { + if (!SourceVersion.isKeyword(name)) { + return name; + } + for (int i = 0;; i++) { + String newName = name + i; + if (!existingNames.contains(newName)) { + return newName; + } + } + } + + private boolean isHashCodeMemoized() { return memoizedMethods(context).stream() 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 e7578911..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 @@ -18,6 +18,7 @@ package com.google.auto.value.extension.toprettystring.processor; import static com.google.auto.common.GeneratedAnnotationSpecs.generatedAnnotationSpec; import static com.google.auto.common.MoreStreams.toImmutableList; +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; @@ -28,6 +29,7 @@ import static javax.lang.model.element.Modifier.FINAL; import com.google.auto.value.extension.AutoValueExtension; import com.google.auto.value.extension.AutoValueExtension.Context; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.MethodSpec; @@ -36,6 +38,7 @@ import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.TypeVariableName; import java.util.List; +import java.util.Set; import javax.lang.model.SourceVersion; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; @@ -117,15 +120,34 @@ 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(); } + private static String generateIdentifier(String name, Set<String> existingNames) { + if (!SourceVersion.isKeyword(name)) { + return name; + } + for (int i = 0; ; i++) { + String newName = name + i; + if (!existingNames.contains(newName)) { + return newName; + } + } + } + /** Translate a {@link TypeMirror} into a {@link TypeName}, including type annotations. */ private static TypeName annotatedType(TypeMirror type) { List<AnnotationSpec> annotations = |