diff options
author | Googler <noreply@google.com> | 2017-12-21 13:29:12 -0800 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2017-12-21 13:31:22 -0800 |
commit | 86b154ca21c026cb8a265004ddc87840e57dd61f (patch) | |
tree | 90fb87c2552bc0ffcce36beca4ddcc70d7900c8a /src | |
parent | 3ce42ef3074ee6d3ac7d9968381c8c0a51d9d38d (diff) |
@AutoCodec features.
* POLYMORPHIC strategy.
* Support for int and Map.Entry types.
PiperOrigin-RevId: 179851237
Diffstat (limited to 'src')
5 files changed, 221 insertions, 127 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java index 6652972035..b36dd4effb 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java @@ -62,6 +62,13 @@ public @interface AutoCodec { * instance for deserialization. */ PUBLIC_FIELDS, + /** + * For use with abstract classes (enforced at compile time). + * + * <p>Uses reflection to determine the concrete subclass, stores the name of the subclass and + * uses its codec to serialize the data. + */ + POLYMORPHIC, } Strategy strategy() default Strategy.CONSTRUCTOR; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java index 7dddb37a4d..c285cb1fe1 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java @@ -17,21 +17,23 @@ package com.google.devtools.build.lib.skyframe.serialization.autocodec; import com.google.auto.service.AutoService; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; -import com.google.devtools.build.lib.skyframe.serialization.SerializationException; import com.google.devtools.build.lib.skyframe.serialization.strings.StringCodecs; import com.google.protobuf.CodedInputStream; import com.google.protobuf.CodedOutputStream; -import com.squareup.javapoet.ClassName; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.UnaryOperator; import java.util.stream.Collectors; @@ -93,8 +95,11 @@ public class AutoCodecProcessor extends AbstractProcessor { for (Element element : roundEnv.getElementsAnnotatedWith(AutoCodecUtil.ANNOTATION)) { AutoCodec annotation = element.getAnnotation(AutoCodecUtil.ANNOTATION); TypeElement encodedType = (TypeElement) element; - TypeSpec.Builder codecClassBuilder = initializeCodecClassBuilder(encodedType); - codecClassBuilder.addMethod(buildGetEncodedClassMethod(encodedType)); + TypeSpec.Builder codecClassBuilder = AutoCodecUtil.initializeCodecClassBuilder(encodedType); + codecClassBuilder.addMethod( + AutoCodecUtil.initializeGetEncodedClassMethod(encodedType) + .addStatement("return $T.class", TypeName.get(encodedType.asType())) + .build()); switch (annotation.strategy()) { case CONSTRUCTOR: buildClassWithConstructorStrategy(codecClassBuilder, encodedType); @@ -102,6 +107,9 @@ public class AutoCodecProcessor extends AbstractProcessor { case PUBLIC_FIELDS: buildClassWithPublicFieldsStrategy(codecClassBuilder, encodedType); break; + case POLYMORPHIC: + buildClassWithPolymorphicStrategy(codecClassBuilder, encodedType); + break; default: throw new IllegalArgumentException("Unknown strategy: " + annotation.strategy()); } @@ -122,7 +130,7 @@ public class AutoCodecProcessor extends AbstractProcessor { return true; } - void buildClassWithConstructorStrategy( + private void buildClassWithConstructorStrategy( TypeSpec.Builder codecClassBuilder, TypeElement encodedType) { // In Java, every class has a constructor, so this always succeeds. ExecutableElement constructor = @@ -132,12 +140,13 @@ public class AutoCodecProcessor extends AbstractProcessor { buildSerializeMethod( encodedType, constructorParameters, AutoCodecProcessor::paramNameAsGetter)); MethodSpec.Builder deserializeBuilder = - initializeDeserializeMethodBuilder(encodedType, constructorParameters); + AutoCodecUtil.initializeDeserializeMethodBuilder(encodedType); + buildDeserializeBody(deserializeBuilder, constructorParameters); addReturnNew(deserializeBuilder, encodedType, constructorParameters); codecClassBuilder.addMethod(deserializeBuilder.build()); } - void buildClassWithPublicFieldsStrategy( + private void buildClassWithPublicFieldsStrategy( TypeSpec.Builder codecClassBuilder, TypeElement encodedType) { List<? extends VariableElement> publicFields = ElementFilter.fieldsIn(env.getElementUtils().getAllMembers(encodedType)) @@ -147,29 +156,12 @@ public class AutoCodecProcessor extends AbstractProcessor { codecClassBuilder.addMethod( buildSerializeMethod(encodedType, publicFields, UnaryOperator.identity())); MethodSpec.Builder deserializeBuilder = - initializeDeserializeMethodBuilder(encodedType, publicFields); + AutoCodecUtil.initializeDeserializeMethodBuilder(encodedType); + buildDeserializeBody(deserializeBuilder, publicFields); addInstantiatePopulateFieldsAndReturn(deserializeBuilder, encodedType, publicFields); codecClassBuilder.addMethod(deserializeBuilder.build()); } - private TypeSpec.Builder initializeCodecClassBuilder(TypeElement encodedType) { - return TypeSpec.classBuilder(AutoCodecUtil.getCodecName(encodedType)) - .addSuperinterface( - ParameterizedTypeName.get( - ClassName.get(ObjectCodec.class), TypeName.get(encodedType.asType()))); - } - - private static MethodSpec buildGetEncodedClassMethod(TypeElement encodedType) { - return MethodSpec.methodBuilder("getEncodedClass") - .addModifiers(Modifier.PUBLIC) - .addAnnotation(Override.class) - .returns( - ParameterizedTypeName.get( - ClassName.get(Class.class), TypeName.get(encodedType.asType()))) - .addStatement("return $T.class", TypeName.get(encodedType.asType())) - .build(); - } - /** * Heuristic that converts a constructor parameter to a getter. * @@ -192,14 +184,7 @@ public class AutoCodecProcessor extends AbstractProcessor { List<? extends VariableElement> parameters, UnaryOperator<String> nameToAccessor) { MethodSpec.Builder serializeBuilder = - MethodSpec.methodBuilder("serialize") - .addModifiers(Modifier.PUBLIC) - .returns(void.class) - .addParameter(TypeName.get(encodedType.asType()), "input") - .addParameter(CodedOutputStream.class, "codedOut") - .addAnnotation(Override.class) - .addException(SerializationException.class) - .addException(IOException.class); + AutoCodecUtil.initializeSerializeMethodBuilder(encodedType); for (VariableElement parameter : parameters) { String paramAccessor = "input." + nameToAccessor.apply(parameter.getSimpleName().toString()); TypeKind typeKind = parameter.asType().getKind(); @@ -207,6 +192,9 @@ public class AutoCodecProcessor extends AbstractProcessor { case BOOLEAN: serializeBuilder.addStatement("codedOut.writeBoolNoTag($L)", paramAccessor); break; + case INT: + serializeBuilder.addStatement("codedOut.writeInt32NoTag($L)", paramAccessor); + break; case DECLARED: buildSerializeBody(serializeBuilder, (DeclaredType) parameter.asType(), paramAccessor); break; @@ -218,41 +206,6 @@ public class AutoCodecProcessor extends AbstractProcessor { } /** - * Creates a method builder defining the deserialize method and a body that extracts serialized - * parameters. - * - * <p>Parameter values are extracted into local variables with the same name as the parameter - * suffixed with a trailing underscore. For example, {@code target} becomes {@code target_}. This - * is to avoid name collisions. - */ - private MethodSpec.Builder initializeDeserializeMethodBuilder( - TypeElement encodedType, List<? extends VariableElement> parameters) { - MethodSpec.Builder builder = - MethodSpec.methodBuilder("deserialize") - .addModifiers(Modifier.PUBLIC) - .returns(TypeName.get(encodedType.asType())) - .addParameter(CodedInputStream.class, "codedIn") - .addAnnotation(Override.class) - .addException(SerializationException.class) - .addException(IOException.class); - for (VariableElement parameter : parameters) { - String paramName = parameter.getSimpleName() + "_"; - TypeKind typeKind = parameter.asType().getKind(); - switch (typeKind) { - case BOOLEAN: - builder.addStatement("boolean $L = codedIn.readBool()", paramName); - break; - case DECLARED: - buildDeserializeBody(builder, (DeclaredType) parameter.asType(), paramName); - break; - default: - throw new IllegalArgumentException("Unimplemented or invalid kind: " + typeKind); - } - } - return builder; - } - - /** * Appends code statements to {@code builder} to serialize a pre-declared variable named {@code * accessor}. * @@ -269,6 +222,11 @@ public class AutoCodecProcessor extends AbstractProcessor { } else if (matchesType(type, String.class)) { builder.addStatement( "$T.asciiOptimized().serialize($L, codedOut)", StringCodecs.class, accessor); + } else if (matchesErased(type, Map.Entry.class)) { + DeclaredType keyType = (DeclaredType) type.getTypeArguments().get(0); + buildSerializeBody(builder, keyType, accessor + ".getKey()", depth + 1); + DeclaredType valueType = (DeclaredType) type.getTypeArguments().get(1); + buildSerializeBody(builder, valueType, accessor + ".getValue()", depth + 1); } else if (matchesErased(type, List.class) || matchesErased(type, ImmutableSortedSet.class)) { // Writes the target count to the stream so deserialization knows when to stop. builder.addStatement("codedOut.writeInt32NoTag($L.size())", accessor); @@ -293,34 +251,31 @@ public class AutoCodecProcessor extends AbstractProcessor { } /** - * Invokes the constructor and returns the value. + * Adds a body to the deserialize method that extracts serialized parameters. * - * <p>Used by the {@link AutoCodec.Strategy.CONSTRUCTOR} strategy. - */ - private void addReturnNew( - MethodSpec.Builder builder, TypeElement type, List<? extends VariableElement> parameters) { - builder.addStatement( - "return new $T($L)", - TypeName.get(type.asType()), - parameters.stream().map(p -> p.getSimpleName() + "_").collect(Collectors.joining(", "))); - } - - /** - * Invokes the constructor, populates public fields and returns the value. - * - * <p>Used by the {@link AutoCodec.Strategy.PUBLIC_FIELDS} strategy. + * <p>Parameter values are extracted into local variables with the same name as the parameter + * suffixed with a trailing underscore. For example, {@code target} becomes {@code target_}. This + * is to avoid name collisions with variables used internally by AutoCodec. */ - private static void addInstantiatePopulateFieldsAndReturn( - MethodSpec.Builder builder, TypeElement type, List<? extends VariableElement> fields) { - builder.addStatement( - "$T deserializationResult = new $T()", - TypeName.get(type.asType()), - TypeName.get(type.asType())); - for (VariableElement field : fields) { - String fieldName = field.getSimpleName().toString(); - builder.addStatement("deserializationResult.$L = $L", fieldName, fieldName + "_"); + private void buildDeserializeBody( + MethodSpec.Builder builder, List<? extends VariableElement> parameters) { + for (VariableElement parameter : parameters) { + String paramName = parameter.getSimpleName() + "_"; + TypeKind typeKind = parameter.asType().getKind(); + switch (typeKind) { + case BOOLEAN: + builder.addStatement("boolean $L = codedIn.readBool()", paramName); + break; + case INT: + builder.addStatement("int $L = codedIn.readInt32()", paramName); + break; + case DECLARED: + buildDeserializeBody(builder, (DeclaredType) parameter.asType(), paramName); + break; + default: + throw new IllegalArgumentException("Unimplemented or invalid kind: " + typeKind); + } } - builder.addStatement("return deserializationResult"); } /** @@ -341,6 +296,14 @@ public class AutoCodecProcessor extends AbstractProcessor { } else if (matchesType(type, String.class)) { builder.addStatement( "$L = $T.asciiOptimized().deserialize(codedIn)", name, StringCodecs.class); + } else if (matchesErased(type, Map.Entry.class)) { + DeclaredType keyType = (DeclaredType) type.getTypeArguments().get(0); + String keyName = "key" + depth; + buildDeserializeBody(builder, keyType, keyName, depth + 1); + DeclaredType valueType = (DeclaredType) type.getTypeArguments().get(1); + String valueName = "value" + depth; + buildDeserializeBody(builder, valueType, valueName, depth + 1); + builder.addStatement("$L = $T.immutableEntry($L, $L)", name, Maps.class, keyName, valueName); } else if (matchesErased(type, List.class)) { builder.addStatement("$L = new $T<>()", name, ArrayList.class); String lengthName = "length" + depth; @@ -383,6 +346,106 @@ public class AutoCodecProcessor extends AbstractProcessor { buildDeserializeBody(builder, type, name, /*depth=*/ 0); } + /** + * Invokes the constructor and returns the value. + * + * <p>Used by the {@link AutoCodec.Strategy.CONSTRUCTOR} strategy. + */ + private static void addReturnNew( + MethodSpec.Builder builder, TypeElement type, List<? extends VariableElement> parameters) { + builder.addStatement( + "return new $T($L)", + TypeName.get(type.asType()), + parameters.stream().map(p -> p.getSimpleName() + "_").collect(Collectors.joining(", "))); + } + + /** + * Invokes the constructor, populates public fields and returns the value. + * + * <p>Used by the {@link AutoCodec.Strategy.PUBLIC_FIELDS} strategy. + */ + private static void addInstantiatePopulateFieldsAndReturn( + MethodSpec.Builder builder, TypeElement type, List<? extends VariableElement> fields) { + builder.addStatement( + "$T deserializationResult = new $T()", + TypeName.get(type.asType()), + TypeName.get(type.asType())); + for (VariableElement field : fields) { + String fieldName = field.getSimpleName().toString(); + builder.addStatement("deserializationResult.$L = $L", fieldName, fieldName + "_"); + } + builder.addStatement("return deserializationResult"); + } + + private static void buildClassWithPolymorphicStrategy( + TypeSpec.Builder codecClassBuilder, TypeElement encodedType) { + if (!encodedType.getModifiers().contains(Modifier.ABSTRACT)) { + throw new IllegalArgumentException( + encodedType + " is not abstract, but POLYMORPHIC was selected as the strategy."); + } + codecClassBuilder.addMethod(buildPolymorphicSerializeMethod(encodedType)); + codecClassBuilder.addMethod(buildPolymorphicDeserializeMethod(encodedType)); + } + + private static MethodSpec buildPolymorphicSerializeMethod(TypeElement encodedType) { + MethodSpec.Builder builder = AutoCodecUtil.initializeSerializeMethodBuilder(encodedType); + builder.beginControlFlow("if (input != null)"); + builder.addStatement("Class<?> clazz = input.getClass()"); + builder.beginControlFlow("try"); + builder.addStatement("$T codecField = clazz.getDeclaredField(\"CODEC\")", Field.class); + builder.addStatement("codedOut.writeBoolNoTag(true)"); + builder.addStatement( + "$T.asciiOptimized().serialize(clazz.getName(), codedOut)", StringCodecs.class); + builder.addStatement("Object codec = codecField.get(null)"); + builder.addStatement( + "$T serializeMethod = codec.getClass().getDeclaredMethod(\"serialize\", clazz, $T.class)", + Method.class, + CodedOutputStream.class); + builder.addStatement("serializeMethod.invoke(codec, input, codedOut)"); + builder.nextControlFlow( + "catch ($T|$T|$T|$T e)", + NoSuchFieldException.class, + NoSuchMethodException.class, + IllegalAccessException.class, + InvocationTargetException.class); + builder.addStatement("throw new SerializationException(input.getClass().getName(), e)"); + builder.endControlFlow(); + builder.nextControlFlow("else"); + builder.addStatement("codedOut.writeBoolNoTag(false)"); + builder.endControlFlow(); + return builder.build(); + } + + private static MethodSpec buildPolymorphicDeserializeMethod(TypeElement encodedType) { + MethodSpec.Builder builder = AutoCodecUtil.initializeDeserializeMethodBuilder(encodedType); + builder.addStatement("$T deserialized = null", TypeName.get(encodedType.asType())); + builder.beginControlFlow("if (codedIn.readBool())"); + builder.addStatement( + "String className = $T.asciiOptimized().deserialize(codedIn)", StringCodecs.class); + builder.beginControlFlow("try"); + builder.addStatement("Class<?> clazz = Class.forName(className)", StringCodecs.class); + builder.addStatement("Object codec = clazz.getDeclaredField(\"CODEC\").get(null)"); + builder.addStatement( + "$T deserializeMethod = codec.getClass().getDeclaredMethod(\"deserialize\", $T.class)", + Method.class, + CodedInputStream.class); + builder.addStatement( + "deserialized = ($T)deserializeMethod.invoke(codec, codedIn)", + TypeName.get(encodedType.asType())); + builder.nextControlFlow( + "catch ($T|$T|$T|$T|$T e)", + ClassNotFoundException.class, + NoSuchFieldException.class, + NoSuchMethodException.class, + IllegalAccessException.class, + InvocationTargetException.class); + builder.addStatement("throw new SerializationException(className, e)"); + builder.endControlFlow(); + builder.endControlFlow(); + builder.addStatement("return deserialized"); + return builder.build(); + } + /** True when {@code type} has the same type as {@code clazz}. */ private boolean matchesType(TypeMirror type, Class<?> clazz) { return env.getTypeUtils() diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecUtil.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecUtil.java index a4b39c8ee1..7dbc42952f 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecUtil.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecUtil.java @@ -15,8 +15,19 @@ package com.google.devtools.build.lib.skyframe.serialization.autocodec; import com.google.common.collect.ImmutableList; +import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; +import com.google.devtools.build.lib.skyframe.serialization.SerializationException; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import java.io.IOException; import java.util.stream.Collectors; import javax.lang.model.element.Element; +import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; /** Static utilities for AutoCodec processors. */ @@ -25,12 +36,49 @@ class AutoCodecUtil { public static final String GENERATED_CLASS_NAME_SUFFIX = "AutoCodec"; static final Class<AutoCodec> ANNOTATION = AutoCodec.class; + static TypeSpec.Builder initializeCodecClassBuilder(TypeElement encodedType) { + return TypeSpec.classBuilder(getCodecName(encodedType)) + .addSuperinterface( + ParameterizedTypeName.get( + ClassName.get(ObjectCodec.class), TypeName.get(encodedType.asType()))); + } + + static MethodSpec.Builder initializeGetEncodedClassMethod(TypeElement encodedType) { + return MethodSpec.methodBuilder("getEncodedClass") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns( + ParameterizedTypeName.get( + ClassName.get(Class.class), TypeName.get(encodedType.asType()))); + } + + static MethodSpec.Builder initializeSerializeMethodBuilder(TypeElement encodedType) { + return MethodSpec.methodBuilder("serialize") + .addModifiers(Modifier.PUBLIC) + .returns(void.class) + .addParameter(TypeName.get(encodedType.asType()), "input") + .addParameter(CodedOutputStream.class, "codedOut") + .addAnnotation(Override.class) + .addException(SerializationException.class) + .addException(IOException.class); + } + + static MethodSpec.Builder initializeDeserializeMethodBuilder(TypeElement encodedType) { + return MethodSpec.methodBuilder("deserialize") + .addModifiers(Modifier.PUBLIC) + .returns(TypeName.get(encodedType.asType())) + .addParameter(CodedInputStream.class, "codedIn") + .addAnnotation(Override.class) + .addException(SerializationException.class) + .addException(IOException.class); + } + /** * Name of the generated codec class. * * <p>For {@code Foo.Bar} this is {@code Foo_Bar_AutoCodec}. */ - static String getCodecName(Element element) { + private static String getCodecName(Element element) { ImmutableList.Builder<String> classNamesBuilder = new ImmutableList.Builder<>(); classNamesBuilder.add(GENERATED_CLASS_NAME_SUFFIX); do { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/BUILD b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/BUILD index 9fff28b2dc..4f98384702 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/BUILD +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/BUILD @@ -55,7 +55,10 @@ java_library( srcs = ["AutoCodecUtil.java"], deps = [ ":autocodec-annotation", + "//src/main/java/com/google/devtools/build/lib/skyframe/serialization", "//third_party:guava", + "//third_party/java/javapoet", + "//third_party/protobuf:protobuf_java", ], ) @@ -65,11 +68,9 @@ java_library( srcs = ["FakeAutoCodecProcessor.java"], deps = [ ":autocodec-util", - "//src/main/java/com/google/devtools/build/lib/skyframe/serialization", "//third_party:auto_service", "//third_party:guava", "//third_party/java/javapoet", - "//third_party/protobuf:protobuf_java", ], ) diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/FakeAutoCodecProcessor.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/FakeAutoCodecProcessor.java index bdd8462a3b..7a46fbb12f 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/FakeAutoCodecProcessor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/FakeAutoCodecProcessor.java @@ -16,14 +16,7 @@ package com.google.devtools.build.lib.skyframe.serialization.autocodec; import com.google.auto.service.AutoService; import com.google.common.collect.ImmutableSet; -import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; -import com.google.protobuf.CodedInputStream; -import com.google.protobuf.CodedOutputStream; -import com.squareup.javapoet.ClassName; import com.squareup.javapoet.JavaFile; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterizedTypeName; -import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import java.io.IOException; import java.util.Set; @@ -33,7 +26,6 @@ import javax.annotation.processing.Processor; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; -import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; @@ -68,34 +60,17 @@ public class FakeAutoCodecProcessor extends AbstractProcessor { public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { for (Element element : roundEnv.getElementsAnnotatedWith(AutoCodecUtil.ANNOTATION)) { TypeElement encodedType = (TypeElement) element; - TypeSpec.Builder codecClassBuilder = - TypeSpec.classBuilder(AutoCodecUtil.getCodecName(encodedType)) - .addSuperinterface( - ParameterizedTypeName.get( - ClassName.get(ObjectCodec.class), TypeName.get(encodedType.asType()))); + TypeSpec.Builder codecClassBuilder = AutoCodecUtil.initializeCodecClassBuilder(encodedType); codecClassBuilder.addMethod( - MethodSpec.methodBuilder("getEncodedClass") - .addModifiers(Modifier.PUBLIC) - .addAnnotation(Override.class) - .returns( - ParameterizedTypeName.get( - ClassName.get(Class.class), TypeName.get(encodedType.asType()))) + AutoCodecUtil.initializeGetEncodedClassMethod(encodedType) .addStatement("throw new RuntimeException(\"Shouldn't be called.\")") .build()); codecClassBuilder.addMethod( - MethodSpec.methodBuilder("serialize") - .addModifiers(Modifier.PUBLIC) - .addParameter(TypeName.get(encodedType.asType()), "input") - .addParameter(CodedOutputStream.class, "codedOut") - .addAnnotation(Override.class) + AutoCodecUtil.initializeSerializeMethodBuilder(encodedType) .addStatement("throw new RuntimeException(\"Shouldn't be called.\")") .build()); codecClassBuilder.addMethod( - MethodSpec.methodBuilder("deserialize") - .addModifiers(Modifier.PUBLIC) - .returns(TypeName.get(encodedType.asType())) - .addParameter(CodedInputStream.class, "codedIn") - .addAnnotation(Override.class) + AutoCodecUtil.initializeDeserializeMethodBuilder(encodedType) .addStatement("throw new RuntimeException(\"Shouldn't be called.\")") .build()); String packageName = |