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 3f3319f278ed8a..d40c5aac73bd92 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 static enum Strategy { * com.google.devtools.build.lib.skyframe.serialization.InjectingObjectCodec#deserialize}. * *
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 static enum Strategy { * {@link com.google.devtools.build.lib.skyframe.serialization.ObjectCodec} with the dependency * type parameter matching the returned type. * - *
This is for use with {@code PUBLIC_FIELDS}, and {@code POLYMORPHIC} strategies. It is an - * error to use this with the {@code CONSTRUCTOR} strategy. + *
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 af07ff529e53c5..744323240ff5b9 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 boolean process(Set extends TypeElement> annotations, RoundEnvironment
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 @@ private TypeElement getDependencyType(AutoCodec annotation) {
}
}
- 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 @@ private TypeSpec.Builder buildClassWithConstructorStrategy(TypeElement encodedTy
private static class PartitionedParameters {
/** Non-dependency parameters. */
List 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 7a01498151bc10..d6d7bd04464a63 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.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 @@ public void addDeserializationCode(Context context) {
}
};
+ /** 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 @@ public void addDeserializationCode(Context context) {
mapMarshaller,
multimapMarshaller,
patternMarshaller,
+ hashCodeMarshaller,
protoMarshaller,
codecMarshaller);