aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar shahan <shahan@google.com>2018-01-05 16:19:34 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-01-05 16:21:43 -0800
commit04e7fd80cf8df79b316d1c858ac33e9db07901b9 (patch)
tree60a3451a781093b1c9acaa8b05856bf22c8ddfcd
parent11389d548b45d0467138eefb7eee806c1290b336 (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
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java27
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/Marshallers.java22
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);