aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools
diff options
context:
space:
mode:
authorGravatar cpeyser <cpeyser@google.com>2018-01-10 15:10:15 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-01-10 15:12:19 -0800
commit2919413bf0a826dd30cf6b69bfdb8584e177ee9f (patch)
treeb28512cd655f0339c75d0b8a9e77b1da427dc2ee /src/main/java/com/google/devtools
parent731ac946d882ffe3449f8dc6af3ece78cab59aa3 (diff)
AutoCodec's constructor strategy recognizes fields in a (transitive)
superclass of the class in question. PiperOrigin-RevId: 181524469
Diffstat (limited to 'src/main/java/com/google/devtools')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java47
1 files changed, 36 insertions, 11 deletions
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 58f8c876a0..bbb3d3bca3 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
@@ -236,7 +236,8 @@ public class AutoCodecProcessor extends AbstractProcessor {
MethodSpec.Builder serializeBuilder =
AutoCodecUtil.initializeSerializeMethodBuilder(encodedType, parameters.dependency);
for (VariableElement parameter : parameters.fields) {
- VariableElement field = getFieldByName(encodedType, parameter.getSimpleName().toString());
+ VariableElement field =
+ getFieldByName(encodedType, parameter.getSimpleName().toString()).value;
TypeKind typeKind = field.asType().getKind();
switch (typeKind) {
case BOOLEAN:
@@ -429,23 +430,22 @@ public class AutoCodecProcessor extends AbstractProcessor {
List<? extends VariableElement> parameters) {
MethodSpec.Builder constructor = MethodSpec.constructorBuilder();
for (VariableElement param : parameters) {
- VariableElement field = getFieldByName(encodedType, param.getSimpleName().toString());
- if (!env.getTypeUtils().isSameType(field.asType(), param.asType())) {
+ FieldValueAndClass field = getFieldByName(encodedType, param.getSimpleName().toString());
+ if (!env.getTypeUtils().isSameType(field.value.asType(), param.asType())) {
throw new IllegalArgumentException(
encodedType.getQualifiedName()
+ " field "
- + field.getSimpleName()
+ + field.value.getSimpleName()
+ " has mismatching type.");
}
builder.addField(
TypeName.LONG, param.getSimpleName() + "_offset", Modifier.PRIVATE, Modifier.FINAL);
constructor.beginControlFlow("try");
- // TODO(shahan): also support fields defined in superclasses if needed.
constructor.addStatement(
"this.$L_offset = $T.getInstance().objectFieldOffset($T.class.getDeclaredField(\"$L\"))",
param.getSimpleName(),
UnsafeProvider.class,
- encodedType.asType(),
+ field.declaringClassType,
param.getSimpleName());
constructor.nextControlFlow("catch ($T e)", NoSuchFieldException.class);
constructor.addStatement("throw new $T(e)", IllegalStateException.class);
@@ -454,22 +454,47 @@ public class AutoCodecProcessor extends AbstractProcessor {
builder.addMethod(constructor.build());
}
+ /** The value of a field, as well as the class that directly declares it. */
+ private static class FieldValueAndClass {
+ final VariableElement value;
+ final TypeElement declaringClassType;
+
+ FieldValueAndClass(VariableElement value, TypeElement declaringClassType) {
+ this.value = value;
+ this.declaringClassType = declaringClassType;
+ }
+ }
+
/**
* Returns the VariableElement for the field named {@code name}.
*
* <p>Throws IllegalArgumentException if no such field is found.
*/
- private static VariableElement getFieldByName(TypeElement type, String name) {
- return ElementFilter.fieldsIn(type.getEnclosedElements())
- .stream()
- .filter(f -> f.getSimpleName().contentEquals(name))
- .findAny()
+ private FieldValueAndClass getFieldByName(TypeElement type, String name) {
+ return getFieldByNameRecursive(type, name)
.orElseThrow(
() ->
new IllegalArgumentException(
type.getQualifiedName() + ": no field with name matching " + name));
}
+ private Optional<FieldValueAndClass> getFieldByNameRecursive(TypeElement type, String name) {
+ Optional<VariableElement> field =
+ ElementFilter.fieldsIn(type.getEnclosedElements())
+ .stream()
+ .filter(f -> f.getSimpleName().contentEquals(name))
+ .findAny();
+
+ if (field.isPresent()) {
+ return Optional.of(new FieldValueAndClass(field.get(), type));
+ }
+ if (type.getSuperclass().getKind() != TypeKind.NONE) {
+ return getFieldByNameRecursive(
+ env.getElementUtils().getTypeElement(type.getSuperclass().toString()), name);
+ }
+ return Optional.empty();
+ }
+
private static TypeSpec.Builder buildClassWithPolymorphicStrategy(
TypeElement encodedType, @Nullable TypeElement dependency) {
if (!encodedType.getModifiers().contains(Modifier.ABSTRACT)) {