diff options
author | 2018-01-05 16:19:34 -0800 | |
---|---|---|
committer | 2018-01-05 16:21:43 -0800 | |
commit | 04e7fd80cf8df79b316d1c858ac33e9db07901b9 (patch) | |
tree | 60a3451a781093b1c9acaa8b05856bf22c8ddfcd | |
parent | 11389d548b45d0467138eefb7eee806c1290b336 (diff) |
@AutoCodec: allow CONSTRUCTOR strategy to be used with dependency element.
It's very common for a child to need a dependency that the parent does not.
This eliminates the need for a `@AutoCodec.Dependency D unusedDependency'
constructor parameter.
* Adds a marshaller for HashCode.
PiperOrigin-RevId: 180989432
3 files changed, 38 insertions, 16 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 3f3319f278..d40c5aac73 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 @@ -92,7 +92,7 @@ public @interface AutoCodec { * com.google.devtools.build.lib.skyframe.serialization.InjectingObjectCodec#deserialize}. * * <p>A compiler error will result if more than one constructor parameter has the - * {@code @Dependency} annotation. + * {@code @Dependency} annotation or if the annotation itself has a dependency element. */ @Target(ElementType.PARAMETER) public static @interface Dependency {} @@ -106,8 +106,7 @@ public @interface AutoCodec { * {@link com.google.devtools.build.lib.skyframe.serialization.ObjectCodec} with the dependency * type parameter matching the returned type. * - * <p>This is for use with {@code PUBLIC_FIELDS}, and {@code POLYMORPHIC} strategies. It is an - * error to use this with the {@code CONSTRUCTOR} strategy. + * <p>It is an error to use this in conjunction with {@code @AutoCodec.Dependency}. */ Class<?> dependency() default Void.class; } 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 af07ff529e..744323240f 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 @@ -97,13 +97,7 @@ public class AutoCodecProcessor extends AbstractProcessor { TypeSpec.Builder codecClassBuilder = null; switch (annotation.strategy()) { case CONSTRUCTOR: - if (dependencyType != null) { - throw new IllegalArgumentException( - encodedType.getQualifiedName() - + " uses the CONSTRUCTOR strategy and has a non-Void dependency " - + dependencyType.getQualifiedName()); - } - codecClassBuilder = buildClassWithConstructorStrategy(encodedType); + codecClassBuilder = buildClassWithConstructorStrategy(encodedType, dependencyType); break; case PUBLIC_FIELDS: codecClassBuilder = buildClassWithPublicFieldsStrategy(encodedType, dependencyType); @@ -150,9 +144,20 @@ public class AutoCodecProcessor extends AbstractProcessor { } } - private TypeSpec.Builder buildClassWithConstructorStrategy(TypeElement encodedType) { + private TypeSpec.Builder buildClassWithConstructorStrategy( + TypeElement encodedType, @Nullable TypeElement dependency) { ExecutableElement constructor = selectConstructorForConstructorStrategy(encodedType); PartitionedParameters parameters = isolateDependency(constructor); + if (dependency != null) { + if (parameters.dependency != null) { + throw new IllegalArgumentException( + encodedType.getQualifiedName() + + " has both a @Dependency annotated constructor parameter " + + "and a non-Void dependency element " + + dependency.getQualifiedName()); + } + parameters.dependency = dependency; + } TypeSpec.Builder codecClassBuilder = AutoCodecUtil.initializeCodecClassBuilder(encodedType, parameters.dependency); @@ -174,11 +179,7 @@ public class AutoCodecProcessor extends AbstractProcessor { private static class PartitionedParameters { /** Non-dependency parameters. */ List<VariableElement> fields; - /** - * Parameter having the {@link AutoCodec.Dependency} annotation. - * - * <p>Null if no such parameter exists. - */ + /** Dependency for this codec or null if no such dependency exists. */ @Nullable TypeElement dependency; } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/Marshallers.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/Marshallers.java index 7a01498151..d6d7bd0446 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/Marshallers.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/Marshallers.java @@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Maps; +import com.google.common.hash.HashCode; import com.google.devtools.build.lib.skyframe.serialization.InjectingObjectCodec; import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; import com.google.devtools.build.lib.skyframe.serialization.autocodec.Marshaller.Context; @@ -421,6 +422,26 @@ class Marshallers { } }; + /** Since we cannot add a codec to {@link HashCode}, it needs to be supported natively. */ + private final Marshaller hashCodeMarshaller = + new Marshaller() { + @Override + public boolean matches(DeclaredType type) { + return matchesType(type, HashCode.class); + } + + @Override + public void addSerializationCode(Context context) { + context.builder.addStatement("codedOut.writeByteArrayNoTag($L.asBytes())", context.name); + } + + @Override + public void addDeserializationCode(Context context) { + context.builder.addStatement( + "$L = $T.fromBytes(codedIn.readByteArray())", context.name, HashCode.class); + } + }; + private final Marshaller protoMarshaller = new Marshaller() { @Override @@ -484,6 +505,7 @@ class Marshallers { mapMarshaller, multimapMarshaller, patternMarshaller, + hashCodeMarshaller, protoMarshaller, codecMarshaller); |