[KeepAnno] Finish remaining proto encoding
Bug: b/343389186
Change-Id: I0bd71f0cc1fd55171698e385ad03a71fd1d79ef4
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/AccessVisibility.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/AccessVisibility.java
index 690bae6..19e72a5 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/AccessVisibility.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/AccessVisibility.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import java.util.HashSet;
@@ -42,4 +43,35 @@
public static Set<AccessVisibility> all() {
return ALL;
}
+
+ public KeepSpecProtos.AccessVisibility buildProto() {
+ switch (this) {
+ case PUBLIC:
+ return KeepSpecProtos.AccessVisibility.ACCESS_PUBLIC;
+ case PROTECTED:
+ return KeepSpecProtos.AccessVisibility.ACCESS_PROTECTED;
+ case PACKAGE_PRIVATE:
+ return KeepSpecProtos.AccessVisibility.ACCESS_PACKAGE_PRIVATE;
+ case PRIVATE:
+ return KeepSpecProtos.AccessVisibility.ACCESS_PRIVATE;
+ default:
+ return KeepSpecProtos.AccessVisibility.ACCESS_UNSPECIFIED;
+ }
+ }
+
+ public static AccessVisibility fromProto(KeepSpecProtos.AccessVisibility proto) {
+ switch (proto.getNumber()) {
+ case KeepSpecProtos.AccessVisibility.ACCESS_PUBLIC_VALUE:
+ return PUBLIC;
+ case KeepSpecProtos.AccessVisibility.ACCESS_PROTECTED_VALUE:
+ return PROTECTED;
+ case KeepSpecProtos.AccessVisibility.ACCESS_PACKAGE_PRIVATE_VALUE:
+ return PACKAGE_PRIVATE;
+ case KeepSpecProtos.AccessVisibility.ACCESS_PRIVATE_VALUE:
+ return PRIVATE;
+ default:
+ assert proto == KeepSpecProtos.AccessVisibility.ACCESS_UNSPECIFIED;
+ return null;
+ }
+ }
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAnnotationPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAnnotationPattern.java
index 5c7cf96..13d4df3 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAnnotationPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAnnotationPattern.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.AnnotationPattern;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.AnnotationRetention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
@@ -38,6 +40,21 @@
return new Builder();
}
+ public static KeepAnnotationPattern fromProto(AnnotationPattern proto) {
+ return builder().applyProto(proto).build();
+ }
+
+ public AnnotationPattern.Builder buildProto() {
+ AnnotationPattern.Builder builder = AnnotationPattern.newBuilder();
+ builder.setName(namePattern.buildProto());
+ if (retentionPolicies == RUNTIME_RETENTION_MASK) {
+ builder.setRetention(AnnotationRetention.RETENTION_RUNTIME);
+ } else if (retentionPolicies == CLASS_RETENTION_MASK) {
+ builder.setRetention(AnnotationRetention.RETENTION_CLASS);
+ }
+ return builder;
+ }
+
public static class Builder {
private KeepQualifiedClassNamePattern namePattern = KeepQualifiedClassNamePattern.any();
@@ -45,6 +62,31 @@
private Builder() {}
+ public Builder applyProto(AnnotationPattern proto) {
+ assert namePattern.isAny();
+ if (proto.hasName()) {
+ setNamePattern(KeepQualifiedClassNamePattern.fromProto(proto.getName()));
+ }
+ // The builder is configured to check that retention is set.
+ // Thus, we apply the default case here explicitly.
+ assert retentionPolicies != ANY_RETENTION_MASK;
+ retentionPolicies = ANY_RETENTION_MASK;
+ if (proto.hasRetention()) {
+ switch (proto.getRetention().getNumber()) {
+ case AnnotationRetention.RETENTION_RUNTIME_VALUE:
+ retentionPolicies = RUNTIME_RETENTION_MASK;
+ break;
+ case AnnotationRetention.RETENTION_CLASS_VALUE:
+ retentionPolicies = CLASS_RETENTION_MASK;
+ break;
+ default:
+ // default any applies.
+ assert retentionPolicies == ANY_RETENTION_MASK;
+ }
+ }
+ return this;
+ }
+
public Builder setNamePattern(KeepQualifiedClassNamePattern namePattern) {
this.namePattern = namePattern;
return this;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepBindings.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepBindings.java
index 28ff0b1..b0045f5 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepBindings.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepBindings.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.ast.KeepSpecUtils.BindingResolver;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.Bindings;
import java.util.Collections;
@@ -88,6 +89,13 @@
.collect(Collectors.joining(", "));
}
+ public static BindingResolver fromProto(Bindings proto) {
+ if (proto == null) {
+ throw new KeepEdgeException("Invalid keep spec, must have valid bindings.");
+ }
+ return new BindingResolver(builder().applyProto(proto));
+ }
+
public KeepSpecProtos.Bindings.Builder buildProto() {
KeepSpecProtos.Bindings.Builder builder = KeepSpecProtos.Bindings.newBuilder();
bindings.forEach(
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepCheck.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepCheck.java
index c59fe13..c7d6d84 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepCheck.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepCheck.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.ast.KeepSpecUtils.BindingResolver;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.Check;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.CheckKind;
@@ -36,19 +37,11 @@
setKind(KeepCheckKind.REMOVED);
}
- // Bindings are not optional.
- if (!proto.hasBindings()) {
- throw new KeepEdgeException("Invalid Check, must have valid bindings.");
- }
- KeepBindings.Builder bindingsBuilder = KeepBindings.builder().applyProto(proto.getBindings());
- setBindings(bindingsBuilder.build());
-
- // The check item reference is not optional.
- if (!proto.hasItem() || proto.getItem().getName().isEmpty()) {
- throw new KeepEdgeException("Invalid check, must have a valid item reference.");
- }
- setItemReference(
- bindingsBuilder.getBindingReferenceForUserBinding(proto.getItem().getName()));
+ // Bindings are non-optional (checked in fromProto).
+ BindingResolver resolver = KeepBindings.fromProto(proto.getBindings());
+ setBindings(resolver.getBindings());
+ // Item is non-optional (checked in mapReference).
+ setItemReference(resolver.mapReference(proto.getItem()));
return this;
}
@@ -131,7 +124,12 @@
@Override
public String toString() {
- return "KeepCheck{kind=" + kind + ", item=" + itemReference + "}";
+ return toProtoString();
+ }
+
+ @Override
+ public String toProtoString() {
+ return buildCheckProto().toString();
}
public static KeepCheck fromCheckProto(Check proto, KeepSpecVersion version) {
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepClassItemPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepClassItemPattern.java
index 8d27307..4ccfad3 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepClassItemPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepClassItemPattern.java
@@ -24,9 +24,10 @@
}
public ClassItemPattern.Builder buildClassProto() {
- // TODO(b/343389186): Add instance-of.
- // TODO(b/343389186): Add annotated-by.
- return ClassItemPattern.newBuilder().setClassName(classNamePattern.buildProto());
+ ClassItemPattern.Builder builder = ClassItemPattern.newBuilder();
+ KeepSpecUtils.buildAnnotatedByProto(annotatedByPattern, builder::setAnnotatedBy);
+ instanceOfPattern.buildProto(builder::setInstanceOf);
+ return builder.setClassName(classNamePattern.buildProto());
}
public static class Builder {
@@ -43,9 +44,14 @@
if (protoItem.hasClassName()) {
setClassNamePattern(KeepQualifiedClassNamePattern.fromProto(protoItem.getClassName()));
}
-
- // TODO(b/343389186): Add instance-of.
- // TODO(b/343389186): Add annotated-by.
+ assert annotatedByPattern.isAbsent();
+ if (protoItem.hasAnnotatedBy()) {
+ setAnnotatedByPattern(KeepSpecUtils.annotatedByFromProto(protoItem.getAnnotatedBy()));
+ }
+ assert instanceOfPattern.isAny();
+ if (protoItem.hasInstanceOf()) {
+ setInstanceOfPattern(KeepInstanceOfPattern.fromProto(protoItem.getInstanceOf()));
+ }
return this;
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepCondition.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepCondition.java
index 96c0f4d..7e619d9 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepCondition.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepCondition.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.ast.KeepSpecUtils.BindingResolver;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.Condition;
+
/**
* A keep condition is the content of an item in the set of preconditions.
*
@@ -17,12 +20,25 @@
return new Builder();
}
+ public Condition.Builder buildProto() {
+ return Condition.newBuilder().setItem(item.buildProto());
+ }
+
+ public static KeepCondition fromProto(Condition proto, BindingResolver resolver) {
+ return builder().applyProto(proto, resolver).build();
+ }
+
public static class Builder {
private KeepBindingReference item;
private Builder() {}
+ public Builder applyProto(Condition proto, BindingResolver resolver) {
+ // Item is not optional and the resolver will throw if not present.
+ return setItemReference(resolver.mapReference(proto.getItem()));
+ }
+
public Builder setItemReference(KeepBindingReference item) {
this.item = item;
return this;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConsequences.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConsequences.java
index 1322746..2fdc4c3 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConsequences.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConsequences.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.ast.KeepSpecUtils.BindingResolver;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.Target;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
@@ -11,19 +13,30 @@
/**
* Set of consequences of a keep edge.
*
- * <p>The consequences are "targets" described by item patterns along with "keep options" which
+ * <p>The consequences are "targets" described by item references along with "keep options" which
* detail what aspects of the items must be retained.
*
* <p>The consequences come into effect if the preconditions of an edge are met.
*/
public final class KeepConsequences {
+ public static KeepConsequences fromProto(List<Target> protoList, BindingResolver resolver) {
+ return builder().applyProto(protoList, resolver).build();
+ }
+
public static class Builder {
private List<KeepTarget> targets = new ArrayList<>();
private Builder() {}
+ public Builder applyProto(List<Target> protoList, BindingResolver resolver) {
+ for (Target target : protoList) {
+ addTarget(KeepTarget.fromProto(target, resolver));
+ }
+ return this;
+ }
+
public Builder addTarget(KeepTarget target) {
targets.add(target);
return this;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraint.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraint.java
index 2ae5f93..f33e14e 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraint.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraint.java
@@ -5,10 +5,67 @@
import com.android.tools.r8.keepanno.ast.AnnotationConstants.Constraints;
import com.android.tools.r8.keepanno.ast.KeepOptions.KeepOption;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.Constraint;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.ConstraintElement;
import java.util.Set;
+import java.util.function.Consumer;
public abstract class KeepConstraint {
+ public Constraint.Builder buildProto() {
+ return Constraint.newBuilder().setElement(buildElementProto());
+ }
+
+ public abstract ConstraintElement buildElementProto();
+
+ public static void fromProto(Constraint proto, Consumer<KeepConstraint> callback) {
+ if (proto.hasElement()) {
+ KeepConstraint constraint = getConstraintFromProtoEnum(proto.getElement());
+ if (constraint != null) {
+ callback.accept(constraint);
+ }
+ return;
+ }
+ if (proto.hasAnnotation()) {
+ callback.accept(
+ KeepConstraint.annotation(KeepAnnotationPattern.fromProto(proto.getAnnotation())));
+ }
+ }
+
+ private static KeepConstraint getConstraintFromProtoEnum(ConstraintElement proto) {
+ switch (proto.getNumber()) {
+ case ConstraintElement.CONSTRAINT_LOOKUP_VALUE:
+ return lookup();
+ case ConstraintElement.CONSTRAINT_NAME_VALUE:
+ return name();
+ case ConstraintElement.CONSTRAINT_VISIBILITY_RELAX_VALUE:
+ return visibilityRelax();
+ case ConstraintElement.CONSTRAINT_VISIBILITY_RESTRICT_VALUE:
+ return visibilityRestrict();
+ case ConstraintElement.CONSTRAINT_NEVER_INLINE_VALUE:
+ return neverInline();
+ case ConstraintElement.CONSTRAINT_CLASS_INSTANTIATE_VALUE:
+ return classInstantiate();
+ case ConstraintElement.CONSTRAINT_CLASS_OPEN_HIERARCHY_VALUE:
+ return classOpenHierarchy();
+ case ConstraintElement.CONSTRAINT_METHOD_INVOKE_VALUE:
+ return methodInvoke();
+ case ConstraintElement.CONSTRAINT_METHOD_REPLACE_VALUE:
+ return methodReplace();
+ case ConstraintElement.CONSTRAINT_FIELD_GET_VALUE:
+ return fieldGet();
+ case ConstraintElement.CONSTRAINT_FIELD_SET_VALUE:
+ return fieldSet();
+ case ConstraintElement.CONSTRAINT_FIELD_REPLACE_VALUE:
+ return fieldReplace();
+ case ConstraintElement.CONSTRAINT_GENERIC_SIGNATURE_VALUE:
+ return genericSignature();
+ default:
+ assert proto == ConstraintElement.CONSTRAINT_UNSPECIFIED;
+ return null;
+ }
+ }
+
@Override
public String toString() {
String typeName = getClass().getTypeName();
@@ -87,6 +144,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.SHRINKING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_LOOKUP;
+ }
}
public static Name name() {
@@ -113,6 +175,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OBFUSCATING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_NAME;
+ }
}
public static VisibilityRelax visibilityRelax() {
@@ -139,6 +206,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
// The compiler currently satisfies that access is never restricted.
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_VISIBILITY_RELAX;
+ }
}
public static VisibilityRestrict visibilityRestrict() {
@@ -166,6 +238,11 @@
// We don't have directional rules so this prohibits any modification.
builder.add(KeepOption.ACCESS_MODIFICATION);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_VISIBILITY_RESTRICT;
+ }
}
public static NeverInline neverInline() {
@@ -192,6 +269,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_NEVER_INLINE;
+ }
}
public static ClassInstantiate classInstantiate() {
@@ -223,6 +305,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_CLASS_INSTANTIATE;
+ }
}
public static ClassOpenHierarchy classOpenHierarchy() {
@@ -254,6 +341,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_CLASS_OPEN_HIERARCHY;
+ }
}
public static MethodInvoke methodInvoke() {
@@ -285,6 +377,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_METHOD_INVOKE;
+ }
}
public static MethodReplace methodReplace() {
@@ -316,6 +413,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_METHOD_REPLACE;
+ }
}
public static FieldGet fieldGet() {
@@ -347,6 +449,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_FIELD_GET;
+ }
}
public static FieldSet fieldSet() {
@@ -378,6 +485,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_FIELD_SET;
+ }
}
public static FieldReplace fieldReplace() {
@@ -409,6 +521,11 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_FIELD_REPLACE;
+ }
}
public static GenericSignature genericSignature() {
@@ -440,6 +557,11 @@
public void addRequiredKeepAttributes(Set<KeepAttribute> attributes) {
attributes.add(KeepAttribute.GENERIC_SIGNATURES);
}
+
+ @Override
+ public ConstraintElement buildElementProto() {
+ return ConstraintElement.CONSTRAINT_GENERIC_SIGNATURE;
+ }
}
public static Annotation annotationsAll() {
@@ -496,6 +618,16 @@
}
@Override
+ public ConstraintElement buildElementProto() {
+ throw new KeepEdgeException("Unexpected attempt to build element for annotation constraint");
+ }
+
+ @Override
+ public Constraint.Builder buildProto() {
+ return Constraint.newBuilder().setAnnotation(annotationPattern.buildProto());
+ }
+
+ @Override
public void accept(KeepConstraintVisitor visitor) {
visitor.onAnnotation(this);
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraints.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraints.java
index 6c55e6c..01c8844 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraints.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraints.java
@@ -6,11 +6,14 @@
import com.android.tools.r8.keepanno.ast.KeepConstraint.Annotation;
import com.android.tools.r8.keepanno.ast.KeepOptions.KeepOption;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos;
import com.google.common.collect.ImmutableSet;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -41,6 +44,27 @@
getConstraints().forEach(c -> c.accept(visitor));
}
+ public abstract void buildProto(
+ Consumer<KeepSpecProtos.Constraints> setConstraints,
+ Consumer<KeepSpecProtos.Constraint> addConstraintAddition);
+
+ public void fromProto(
+ KeepSpecProtos.Constraints proto,
+ List<KeepSpecProtos.Constraint> protoAdditions,
+ Consumer<KeepConstraints> setConstraints) {
+ if (proto == null && protoAdditions.isEmpty()) {
+ return;
+ }
+ Builder builder = builder();
+ if (proto == null) {
+ builder.copyFrom(defaultConstraints());
+ } else {
+ proto.getConstraintsList().forEach(c -> KeepConstraint.fromProto(c, builder::add));
+ }
+ protoAdditions.forEach(c -> KeepConstraint.fromProto(c, builder::add));
+ setConstraints.accept(builder.build());
+ }
+
public static class Builder {
private boolean defaultAdditions = false;
@@ -149,6 +173,15 @@
public KeepOptions convertToKeepOptions(KeepOptions defaultOptions) {
return KeepOptions.keepAll();
}
+
+ @Override
+ public void buildProto(
+ Consumer<KeepSpecProtos.Constraints> setConstraints,
+ Consumer<KeepSpecProtos.Constraint> addConstraintAddition) {
+ KeepSpecProtos.Constraints.Builder builder = KeepSpecProtos.Constraints.newBuilder();
+ constraints.forEach(c -> builder.addConstraints(c.buildProto()));
+ setConstraints.accept(builder.build());
+ }
}
private static class Defaults extends KeepConstraints {
@@ -165,6 +198,11 @@
KeepConstraint.fieldSet());
@Override
+ public boolean isDefault() {
+ return true;
+ }
+
+ @Override
Set<KeepConstraint> getConstraints() {
return constraints;
}
@@ -184,6 +222,13 @@
// The default set of keep rules for any kind of target requires no additional attributes.
return Collections.emptySet();
}
+
+ @Override
+ public void buildProto(
+ Consumer<KeepSpecProtos.Constraints> setConstraints,
+ Consumer<KeepSpecProtos.Constraint> addConstraintAddition) {
+ // Nothing to add as these are the defaults.
+ }
}
private static class Additions extends KeepConstraints {
@@ -218,6 +263,15 @@
public Set<KeepAttribute> getRequiredKeepAttributes() {
return additions.getRequiredKeepAttributes();
}
+
+ @Override
+ public void buildProto(
+ Consumer<KeepSpecProtos.Constraints> setConstraints,
+ Consumer<KeepSpecProtos.Constraint> addConstraintAddition) {
+ // Map all nested constraints into additions.
+ additions.buildProto(
+ cs -> cs.getConstraintsList().forEach(addConstraintAddition), addConstraintAddition);
+ }
}
private static class Constraints extends KeepConstraints {
@@ -229,6 +283,15 @@
}
@Override
+ public void buildProto(
+ Consumer<KeepSpecProtos.Constraints> setConstraints,
+ Consumer<KeepSpecProtos.Constraint> addConstraintAddition) {
+ KeepSpecProtos.Constraints.Builder builder = KeepSpecProtos.Constraints.newBuilder();
+ constraints.forEach(c -> builder.addConstraints(c.buildProto()));
+ setConstraints.accept(builder.build());
+ }
+
+ @Override
public Set<KeepConstraint> getConstraints() {
return constraints;
}
@@ -262,4 +325,8 @@
public abstract KeepOptions convertToKeepOptions(KeepOptions defaultOptions);
public abstract Set<KeepAttribute> getRequiredKeepAttributes();
+
+ public boolean isDefault() {
+ return false;
+ }
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepDeclaration.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepDeclaration.java
index 12d1d31..a2cc7de 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepDeclaration.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepDeclaration.java
@@ -50,6 +50,8 @@
throw new RuntimeException();
}
+ public abstract String toProtoString();
+
public final Declaration.Builder buildDeclarationProto() {
Declaration.Builder builder = Declaration.newBuilder();
return apply(
@@ -57,13 +59,13 @@
check -> builder.setCheck(check.buildCheckProto()));
}
- public static KeepDeclaration fromProto(
+ public static KeepDeclaration fromDeclarationProto(
KeepSpecProtos.Declaration declaration, KeepSpecVersion version) {
if (declaration.hasEdge()) {
- return KeepEdge.builder().applyProto(declaration.getEdge(), version).build();
+ return KeepEdge.fromEdgeProto(declaration.getEdge(), version);
}
if (declaration.hasCheck()) {
- return KeepCheck.builder().applyProto(declaration.getCheck(), version).build();
+ return KeepCheck.fromCheckProto(declaration.getCheck(), version);
}
return null;
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepEdge.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepEdge.java
index 3060010..ff8e507 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepEdge.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepEdge.java
@@ -3,8 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.ast.KeepSpecUtils.BindingResolver;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.Edge;
-import com.android.tools.r8.keepanno.utils.Unimplemented;
/**
* An edge in the keep graph.
@@ -147,9 +147,14 @@
private Builder() {}
- public Builder applyProto(Edge edge, KeepSpecVersion version) {
- // TODO(b/343389186): implement this.
- KeepEdgeMetaInfo.builder().applyProto(edge.getMetaInfo(), version).build();
+ public Builder applyProto(Edge proto, KeepSpecVersion version) {
+ // Proto MetaInfo is optional but the `fromProto` deals with the null case.
+ setMetaInfo(KeepEdgeMetaInfo.fromProto(proto.getMetaInfo(), version));
+ // Bindings are non-optional (checked in fromProto).
+ BindingResolver resolver = KeepBindings.fromProto(proto.getBindings());
+ setBindings(resolver.getBindings());
+ setPreconditions(KeepPreconditions.fromProto(proto.getPreconditionsList(), resolver));
+ setConsequences(KeepConsequences.fromProto(proto.getConsequencesList(), resolver));
return this;
}
@@ -257,17 +262,24 @@
@Override
public String toString() {
- return "KeepEdge{metainfo="
- + getMetaInfo()
- + ", preconditions="
- + preconditions
- + ", consequences="
- + consequences
- + '}';
+ return toProtoString();
+ }
+
+ @Override
+ public String toProtoString() {
+ return buildEdgeProto().toString();
+ }
+
+ public static KeepEdge fromEdgeProto(Edge proto, KeepSpecVersion version) {
+ return KeepEdge.builder().applyProto(proto, version).build();
}
public Edge.Builder buildEdgeProto() {
- Edge.newBuilder().setMetaInfo(getMetaInfo().buildProto());
- throw new Unimplemented();
+ Edge.Builder builder = Edge.newBuilder();
+ builder.setMetaInfo(getMetaInfo().buildProto());
+ builder.setBindings(bindings.buildProto());
+ preconditions.forEach(condition -> builder.addPreconditions(condition.buildProto()));
+ consequences.forEachTarget(target -> builder.addConsequences(target.buildProto()));
+ return builder;
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepFieldAccessPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepFieldAccessPattern.java
index 55c15c2..b9bf204 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepFieldAccessPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepFieldAccessPattern.java
@@ -5,7 +5,9 @@
import com.android.tools.r8.keepanno.keeprules.RulePrinter;
import com.android.tools.r8.keepanno.keeprules.RulePrintingUtils;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.MemberAccessField;
import java.util.Set;
+import java.util.function.Consumer;
public class KeepFieldAccessPattern extends KeepMemberAccessPattern {
@@ -41,6 +43,10 @@
this.transientPattern = transientPattern;
}
+ public static KeepFieldAccessPattern fromFieldProto(MemberAccessField proto) {
+ return builder().applyFieldProto(proto).build();
+ }
+
@Override
public String toString() {
if (isAny()) {
@@ -64,6 +70,17 @@
return transientPattern;
}
+ public void buildFieldProto(Consumer<MemberAccessField.Builder> callback) {
+ if (isAny()) {
+ return;
+ }
+ MemberAccessField.Builder builder = MemberAccessField.newBuilder();
+ buildGeneralProto(builder::setGeneralAccess);
+ volatilePattern.buildProto(builder::setVolatilePattern);
+ transientPattern.buildProto(builder::setTransientPattern);
+ callback.accept(builder);
+ }
+
public static class Builder extends BuilderBase<KeepFieldAccessPattern, Builder> {
private ModifierPattern volatilePattern = ModifierPattern.any();
@@ -106,5 +123,20 @@
public ModifierPattern getTransientPattern() {
return transientPattern;
}
+
+ public Builder applyFieldProto(MemberAccessField proto) {
+ if (proto.hasGeneralAccess()) {
+ applyGeneralProto(proto.getGeneralAccess());
+ }
+ assert volatilePattern.isAny();
+ if (proto.hasVolatilePattern()) {
+ setVolatile(proto.getVolatilePattern().getValue());
+ }
+ assert transientPattern.isAny();
+ if (proto.hasTransientPattern()) {
+ setTransient(proto.getTransientPattern().getValue());
+ }
+ return this;
+ }
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepFieldPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepFieldPattern.java
index f863c2e..d6ec06d 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepFieldPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepFieldPattern.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.keepanno.ast;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.MemberPatternField;
-import com.android.tools.r8.keepanno.utils.Unimplemented;
import java.util.Objects;
public final class KeepFieldPattern extends KeepMemberPattern {
@@ -31,6 +30,31 @@
return this;
}
+ public Builder applyProto(MemberPatternField proto) {
+ assert namePattern.isAny();
+ if (proto.hasName()) {
+ setNamePattern(
+ KeepFieldNamePattern.fromStringPattern(KeepStringPattern.fromProto(proto.getName())));
+ }
+
+ assert typePattern.isAny();
+ if (proto.hasFieldType()) {
+ setTypePattern(
+ KeepFieldTypePattern.fromType(KeepTypePattern.fromProto(proto.getFieldType())));
+ }
+
+ assert accessPattern.isAny();
+ if (proto.hasAccess()) {
+ setAccessPattern(KeepFieldAccessPattern.fromFieldProto(proto.getAccess()));
+ }
+
+ assert annotatedByPattern.isAbsent();
+ if (proto.hasAnnotatedBy()) {
+ setAnnotatedByPattern(KeepSpecUtils.annotatedByFromProto(proto.getAnnotatedBy()));
+ }
+ return self();
+ }
+
public Builder copyFromMemberPattern(KeepMemberPattern memberPattern) {
assert memberPattern.isGeneralMember();
return setAccessPattern(
@@ -148,7 +172,17 @@
+ '}';
}
+ public static KeepFieldPattern fromFieldMemberProto(MemberPatternField proto) {
+ return builder().applyProto(proto).build();
+ }
+
public MemberPatternField.Builder buildFieldProto() {
- throw new Unimplemented();
+ MemberPatternField.Builder builder =
+ MemberPatternField.newBuilder()
+ .setName(namePattern.asStringPattern().buildProto())
+ .setFieldType(typePattern.asType().buildProto());
+ accessPattern.buildFieldProto(builder::setAccess);
+ KeepSpecUtils.buildAnnotatedByProto(annotatedByPattern, builder::setAnnotatedBy);
+ return builder;
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepInstanceOfPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepInstanceOfPattern.java
index 79e2f43..114ada8 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepInstanceOfPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepInstanceOfPattern.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.InstanceOfPattern;
+import java.util.function.Consumer;
+
/** Pattern for matching the instance-of properties of a class. */
public abstract class KeepInstanceOfPattern {
@@ -10,6 +13,20 @@
return Some.getAnyInstance();
}
+ public static KeepInstanceOfPattern fromProto(InstanceOfPattern proto) {
+ return builder().applyProto(proto).build();
+ }
+
+ public void buildProto(Consumer<InstanceOfPattern.Builder> setter) {
+ if (isAny()) {
+ return;
+ }
+ setter.accept(
+ InstanceOfPattern.newBuilder()
+ .setInclusive(isInclusive())
+ .setClassName(getClassNamePattern().buildProto()));
+ }
+
public static class Builder {
private KeepQualifiedClassNamePattern namePattern = KeepQualifiedClassNamePattern.any();
@@ -17,6 +34,18 @@
private Builder() {}
+ public Builder applyProto(InstanceOfPattern proto) {
+ assert namePattern.isAny();
+ if (proto.hasClassName()) {
+ classPattern(KeepQualifiedClassNamePattern.fromProto(proto.getClassName()));
+ }
+ assert isInclusive;
+ if (proto.hasInclusive()) {
+ setInclusive(proto.getInclusive());
+ }
+ return this;
+ }
+
public Builder classPattern(KeepQualifiedClassNamePattern namePattern) {
this.namePattern = namePattern;
return this;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMemberAccessPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMemberAccessPattern.java
index 8b18105..487ddc8 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMemberAccessPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMemberAccessPattern.java
@@ -5,7 +5,11 @@
import com.android.tools.r8.keepanno.keeprules.RulePrinter;
import com.android.tools.r8.keepanno.keeprules.RulePrintingUtils;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.AccessVisibilitySet;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.MemberAccessGeneral;
import java.util.Set;
+import java.util.function.Consumer;
public class KeepMemberAccessPattern {
@@ -83,6 +87,28 @@
return syntheticPattern;
}
+ public static KeepMemberAccessPattern fromGeneralProto(MemberAccessGeneral proto) {
+ return memberBuilder().applyGeneralProto(proto).build();
+ }
+
+ public void buildGeneralProto(Consumer<MemberAccessGeneral.Builder> callback) {
+ if (isAny()) {
+ return;
+ }
+ MemberAccessGeneral.Builder builder = MemberAccessGeneral.newBuilder();
+ if (!isAnyVisibility()) {
+ AccessVisibilitySet.Builder visibilityBuilder = AccessVisibilitySet.newBuilder();
+ for (AccessVisibility visibility : allowedVisibilities) {
+ visibilityBuilder.addAccessVisibility(visibility.buildProto());
+ }
+ builder.setAccessVisibility(visibilityBuilder.build());
+ }
+ staticPattern.buildProto(builder::setStaticPattern);
+ finalPattern.buildProto(builder::setFinalPattern);
+ syntheticPattern.buildProto(builder::setSyntheticPattern);
+ callback.accept(builder);
+ }
+
public static class Builder extends BuilderBase<KeepMemberAccessPattern, Builder> {
@Override
@@ -185,5 +211,32 @@
syntheticPattern = ModifierPattern.fromAllowValue(allow);
return self();
}
+
+ public B applyGeneralProto(MemberAccessGeneral proto) {
+ assert getAllowedVisibilities() == AccessVisibility.all();
+ if (proto.hasAccessVisibility()) {
+ AccessVisibilitySet protoSet = proto.getAccessVisibility();
+ for (KeepSpecProtos.AccessVisibility protoVisibility : protoSet.getAccessVisibilityList()) {
+ // Map "unspecified" value to no effect, e.g. any visibility.
+ AccessVisibility visibility = AccessVisibility.fromProto(protoVisibility);
+ if (visibility != null) {
+ setAccessVisibility(visibility, true);
+ }
+ }
+ }
+ assert staticPattern.isAny();
+ if (proto.hasStaticPattern()) {
+ setStatic(proto.getStaticPattern().getValue());
+ }
+ assert finalPattern.isAny();
+ if (proto.hasFinalPattern()) {
+ setFinal(proto.getFinalPattern().getValue());
+ }
+ assert syntheticPattern.isAny();
+ if (proto.hasSyntheticPattern()) {
+ setSynthetic(proto.getSyntheticPattern().getValue());
+ }
+ return self();
+ }
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMemberPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMemberPattern.java
index 5c784bc..67bbcd2 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMemberPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMemberPattern.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.MemberPattern;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.MemberPatternGeneral;
-import com.android.tools.r8.keepanno.utils.Unimplemented;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -21,9 +20,22 @@
}
public static class Builder {
- private OptionalPattern<KeepQualifiedClassNamePattern> annotatedByPattern;
+ private OptionalPattern<KeepQualifiedClassNamePattern> annotatedByPattern =
+ OptionalPattern.absent();
private KeepMemberAccessPattern accessPattern = KeepMemberAccessPattern.anyMemberAccess();
+ public Builder applyProto(MemberPatternGeneral proto) {
+ assert annotatedByPattern.isAbsent();
+ if (proto.hasAnnotatedBy()) {
+ setAnnotatedByPattern(KeepSpecUtils.annotatedByFromProto(proto.getAnnotatedBy()));
+ }
+ assert accessPattern.isAny();
+ if (proto.hasAccess()) {
+ setAccessPattern(KeepMemberAccessPattern.fromGeneralProto(proto.getAccess()));
+ }
+ return this;
+ }
+
public Builder setAnnotatedByPattern(
OptionalPattern<KeepQualifiedClassNamePattern> annotatedByPattern) {
this.annotatedByPattern = annotatedByPattern;
@@ -94,8 +106,15 @@
+ '}';
}
- public MemberPatternGeneral.Builder buildGeneralProto() {
- throw new Unimplemented();
+ public MemberPatternGeneral.Builder buildGeneralMemberProto() {
+ MemberPatternGeneral.Builder builder = MemberPatternGeneral.newBuilder();
+ accessPattern.buildGeneralProto(builder::setAccess);
+ KeepSpecUtils.buildAnnotatedByProto(annotatedByPattern, builder::setAnnotatedBy);
+ return builder;
+ }
+
+ public static KeepMemberPattern fromGeneralMemberProto(MemberPatternGeneral proto) {
+ return memberBuilder().applyProto(proto).build();
}
}
@@ -156,7 +175,7 @@
public MemberPattern.Builder buildProto() {
MemberPattern.Builder builder = MemberPattern.newBuilder();
match(
- general -> builder.setGeneralMember(((Some) general).buildGeneralProto()),
+ general -> builder.setGeneralMember(((Some) general).buildGeneralMemberProto()),
field -> builder.setFieldMember(field.buildFieldProto()),
method -> builder.setMethodMember(method.buildMethodProto()));
return builder;
@@ -164,15 +183,13 @@
public static KeepMemberPattern fromMemberProto(MemberPattern memberPattern) {
if (memberPattern.hasGeneralMember()) {
- // return KeepMemberPattern.memberBuilder().applyProto(memberPattern.getGeneralMember());
- throw new Unimplemented();
+ return Some.fromGeneralMemberProto(memberPattern.getGeneralMember());
}
if (memberPattern.hasFieldMember()) {
- // return KeepFieldPattern.builder().applyProto(memberPattern.getFieldMember());
- throw new Unimplemented();
+ return KeepFieldPattern.fromFieldMemberProto(memberPattern.getFieldMember());
}
if (memberPattern.hasMethodMember()) {
- return KeepMethodPattern.fromMethodProto(memberPattern.getMethodMember());
+ return KeepMethodPattern.fromMethodMemberProto(memberPattern.getMethodMember());
}
return KeepMemberPattern.allMembers();
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMethodAccessPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMethodAccessPattern.java
index c8f83b2..5b3a1bd 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMethodAccessPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMethodAccessPattern.java
@@ -5,7 +5,9 @@
import com.android.tools.r8.keepanno.keeprules.RulePrinter;
import com.android.tools.r8.keepanno.keeprules.RulePrintingUtils;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.MemberAccessMethod;
import java.util.Set;
+import java.util.function.Consumer;
public class KeepMethodAccessPattern extends KeepMemberAccessPattern {
@@ -53,6 +55,24 @@
this.strictFpPattern = strictFpPattern;
}
+ public static KeepMethodAccessPattern fromMethodProto(MemberAccessMethod proto) {
+ return builder().applyMethodProto(proto).build();
+ }
+
+ public void buildMethodProto(Consumer<MemberAccessMethod.Builder> callback) {
+ if (isAny()) {
+ return;
+ }
+ MemberAccessMethod.Builder builder = MemberAccessMethod.newBuilder();
+ buildGeneralProto(builder::setGeneralAccess);
+ synchronizedPattern.buildProto(builder::setSynchronizedPattern);
+ bridgePattern.buildProto(builder::setBridgePattern);
+ nativePattern.buildProto(builder::setNativePattern);
+ abstractPattern.buildProto(builder::setAbstractPattern);
+ strictFpPattern.buildProto(builder::setStrictFpPattern);
+ callback.accept(builder);
+ }
+
@Override
public String toString() {
if (isAny()) {
@@ -123,6 +143,33 @@
return pattern.isAny() ? anyMethodAccess() : pattern;
}
+ public Builder applyMethodProto(MemberAccessMethod proto) {
+ if (proto.hasGeneralAccess()) {
+ applyGeneralProto(proto.getGeneralAccess());
+ }
+ assert synchronizedPattern.isAny();
+ if (proto.hasSynchronizedPattern()) {
+ setSynchronized(proto.getSynchronizedPattern().getValue());
+ }
+ assert bridgePattern.isAny();
+ if (proto.hasBridgePattern()) {
+ setBridge(proto.getBridgePattern().getValue());
+ }
+ assert nativePattern.isAny();
+ if (proto.hasNativePattern()) {
+ setNative(proto.getNativePattern().getValue());
+ }
+ assert abstractPattern.isAny();
+ if (proto.hasAbstractPattern()) {
+ setAbstract(proto.getAbstractPattern().getValue());
+ }
+ assert strictFpPattern.isAny();
+ if (proto.hasStrictFpPattern()) {
+ setStrictFp(proto.getStrictFpPattern().getValue());
+ }
+ return this;
+ }
+
public Builder setSynchronized(boolean allow) {
synchronizedPattern = ModifierPattern.fromAllowValue(allow);
return this;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMethodPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMethodPattern.java
index 504bba8..11f5cea 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMethodPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepMethodPattern.java
@@ -34,17 +34,16 @@
return this;
}
- public Builder applyProto(MemberPatternMethod methodMember) {
+ public Builder applyProto(MemberPatternMethod proto) {
assert namePattern.isAny();
- if (methodMember.hasName()) {
+ if (proto.hasName()) {
setNamePattern(
- KeepMethodNamePattern.fromStringPattern(
- KeepStringPattern.fromProto(methodMember.getName())));
+ KeepMethodNamePattern.fromStringPattern(KeepStringPattern.fromProto(proto.getName())));
}
assert returnTypePattern.isAny();
- if (methodMember.hasReturnType()) {
- MethodReturnTypePattern returnType = methodMember.getReturnType();
+ if (proto.hasReturnType()) {
+ MethodReturnTypePattern returnType = proto.getReturnType();
if (returnType.hasVoidType()) {
setReturnTypeVoid();
} else if (returnType.hasSomeType()) {
@@ -55,8 +54,8 @@
}
assert parametersPattern.isAny();
- if (methodMember.hasParameterTypes()) {
- MethodParameterTypesPattern parameterTypes = methodMember.getParameterTypes();
+ if (proto.hasParameterTypes()) {
+ MethodParameterTypesPattern parameterTypes = proto.getParameterTypes();
KeepMethodParametersPattern.Builder parametersBuilder =
KeepMethodParametersPattern.builder();
for (TypePattern typePattern : parameterTypes.getTypesList()) {
@@ -65,8 +64,15 @@
setParametersPattern(parametersBuilder.build());
}
- // TODO(b/343389186): Add annotated-by.
- // TODO(b/343389186): Add access.
+ assert accessPattern.isAny();
+ if (proto.hasAccess()) {
+ setAccessPattern(KeepMethodAccessPattern.fromMethodProto(proto.getAccess()));
+ }
+
+ assert annotatedByPattern.isAbsent();
+ if (proto.hasAnnotatedBy()) {
+ setAnnotatedByPattern(KeepSpecUtils.annotatedByFromProto(proto.getAnnotatedBy()));
+ }
return this;
}
@@ -217,7 +223,7 @@
+ '}';
}
- public static KeepMemberPattern fromMethodProto(MemberPatternMethod methodMember) {
+ public static KeepMemberPattern fromMethodMemberProto(MemberPatternMethod methodMember) {
return builder().applyProto(methodMember).build();
}
@@ -229,8 +235,8 @@
if (!parametersPattern.isAny()) {
builder.setParameterTypes(parametersPattern.buildProto());
}
- // TODO(b/343389186): Add annotated-by.
- // TODO(b/343389186): Add access.
+ accessPattern.buildMethodProto(builder::setAccess);
+ KeepSpecUtils.buildAnnotatedByProto(annotatedByPattern, builder::setAnnotatedBy);
return builder;
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepPackagePattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepPackagePattern.java
index 16d9ef2..3483ff7 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepPackagePattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepPackagePattern.java
@@ -45,7 +45,7 @@
public static class Builder {
- private KeepPackagePattern pattern;
+ private KeepPackagePattern pattern = KeepPackagePattern.any();
public Builder applyProto(PackagePattern pkg) {
if (pkg.hasExactPackageHack()) {
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepPreconditions.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepPreconditions.java
index 246b20c..2cdf7d9 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepPreconditions.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepPreconditions.java
@@ -3,12 +3,18 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.ast.KeepSpecUtils.BindingResolver;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.Condition;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public abstract class KeepPreconditions {
+ public static KeepPreconditions fromProto(List<Condition> protoList, BindingResolver resolver) {
+ return builder().applyProto(protoList, resolver).build();
+ }
+
public abstract void forEach(Consumer<KeepCondition> fn);
public static class Builder {
@@ -17,6 +23,14 @@
private Builder() {}
+ public Builder applyProto(List<Condition> protoList, BindingResolver resolver) {
+ for (Condition condition : protoList) {
+ addCondition(KeepCondition.fromProto(condition, resolver));
+ }
+ assert !protoList.isEmpty() || build().isAlways();
+ return this;
+ }
+
public Builder addCondition(KeepCondition condition) {
preconditions.add(condition);
return this;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepQualifiedClassNamePattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepQualifiedClassNamePattern.java
index 4b1fcf7..94445bb 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepQualifiedClassNamePattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepQualifiedClassNamePattern.java
@@ -50,7 +50,8 @@
}
public ClassNamePattern.Builder buildProto() {
- return ClassNamePattern.newBuilder()
+ ClassNamePattern.Builder builder = ClassNamePattern.newBuilder();
+ return builder
.setPackage(packagePattern.buildProto())
.setUnqualifiedName(namePattern.buildProto());
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepSpecUtils.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepSpecUtils.java
index b5f934b..5a76764 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepSpecUtils.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepSpecUtils.java
@@ -4,8 +4,9 @@
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.AnnotatedByPattern;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.TypeDesc;
-import com.google.protobuf.MessageOrBuilder;
import java.util.function.Consumer;
public final class KeepSpecUtils {
@@ -15,4 +16,49 @@
public static TypeDesc desc(String descriptor) {
return TypeDesc.newBuilder().setDesc(descriptor).build();
}
+
+ // Helper to resolve binding reference strings into symbols when parsing protos.
+ public static class BindingResolver {
+
+ // Builder is retained to resolve and does not escape this resolver.
+ private final KeepBindings.Builder builder;
+
+ // Bindings is the "build once" structure of the actual bindings.
+ private final KeepBindings bindings;
+
+ public BindingResolver(KeepBindings.Builder builder) {
+ this.builder = builder;
+ this.bindings = builder.build();
+ }
+
+ public KeepBindings getBindings() {
+ return bindings;
+ }
+
+ public KeepBindingReference mapReference(KeepSpecProtos.BindingReference reference) {
+ if (reference == null || reference.getName().isEmpty()) {
+ throw new KeepEdgeException("Invalid binding reference");
+ }
+ return builder.getBindingReferenceForUserBinding(reference.getName());
+ }
+ }
+
+ // Helpers to read/write the annotated-by pattern which does not have its own AST node.
+ public static void buildAnnotatedByProto(
+ OptionalPattern<KeepQualifiedClassNamePattern> pattern,
+ Consumer<AnnotatedByPattern.Builder> callback) {
+ // If the annotated-by pattern is absent then no restrictions are present, and we don't set it.
+ if (pattern.isPresent()) {
+ callback.accept(AnnotatedByPattern.newBuilder().setName(pattern.get().buildProto()));
+ }
+ }
+
+ public static OptionalPattern<KeepQualifiedClassNamePattern> annotatedByFromProto(
+ AnnotatedByPattern proto) {
+ if (!proto.hasName()) {
+ // No name implies any annotation (in contrast to no restrictions).
+ return OptionalPattern.of(KeepQualifiedClassNamePattern.any());
+ }
+ return OptionalPattern.of(KeepQualifiedClassNamePattern.fromProto(proto.getName()));
+ }
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepTarget.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepTarget.java
index 0d7dc03..1a8321b 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepTarget.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepTarget.java
@@ -3,10 +3,22 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.ast.KeepSpecUtils.BindingResolver;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos.Target;
import java.util.Objects;
public class KeepTarget {
+ public Target.Builder buildProto() {
+ Target.Builder builder = Target.newBuilder();
+ constraints.buildProto(builder::setConstraints, builder::addConstraintAdditions);
+ return builder.setItem(item.buildProto());
+ }
+
+ public static KeepTarget fromProto(Target proto, BindingResolver resolver) {
+ return builder().applyProto(proto, resolver).build();
+ }
+
public static class Builder {
private KeepBindingReference item;
@@ -14,6 +26,16 @@
private Builder() {}
+ public Builder applyProto(Target proto, BindingResolver resolver) {
+ setItemReference(resolver.mapReference(proto.getItem()));
+ assert constraints.isDefault();
+ constraints.fromProto(
+ proto.hasConstraints() ? proto.getConstraints() : null,
+ proto.getConstraintAdditionsList(),
+ this::setConstraints);
+ return this;
+ }
+
public Builder setItemReference(KeepBindingReference itemReference) {
this.item = itemReference;
return this;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepTypePattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepTypePattern.java
index a123e61..15cfef7 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepTypePattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepTypePattern.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.keepanno.ast;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.TypePattern;
-import com.android.tools.r8.keepanno.utils.Unimplemented;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.Objects;
@@ -58,21 +57,6 @@
throw new KeepEdgeException("Invalid type descriptor: " + typeDescriptor);
}
- public static KeepTypePattern fromProto(TypePattern typeProto) {
- if (typeProto.hasPrimitive()) {
- return KeepTypePattern.fromPrimitive(
- KeepPrimitiveTypePattern.fromProto(typeProto.getPrimitive()));
- }
- if (typeProto.hasArray()) {
- return KeepTypePattern.fromArray(KeepArrayTypePattern.fromProto(typeProto.getArray()));
- }
- if (typeProto.hasClazz()) {
- return KeepTypePattern.fromClass(
- KeepQualifiedClassNamePattern.fromProto(typeProto.getClazz()));
- }
- return KeepTypePattern.any();
- }
-
public abstract <T> T apply(
Supplier<T> onAny,
Function<KeepPrimitiveTypePattern, T> onPrimitive,
@@ -281,6 +265,25 @@
}
}
+ public static KeepTypePattern fromProto(TypePattern typeProto) {
+ if (typeProto.hasPrimitive()) {
+ return KeepTypePattern.fromPrimitive(
+ KeepPrimitiveTypePattern.fromProto(typeProto.getPrimitive()));
+ }
+ if (typeProto.hasArray()) {
+ return KeepTypePattern.fromArray(KeepArrayTypePattern.fromProto(typeProto.getArray()));
+ }
+ if (typeProto.hasClazz()) {
+ return KeepTypePattern.fromClass(
+ KeepQualifiedClassNamePattern.fromProto(typeProto.getClazz()));
+ }
+ if (typeProto.hasInstanceOf()) {
+ return KeepTypePattern.fromInstanceOf(
+ KeepInstanceOfPattern.fromProto(typeProto.getInstanceOf()));
+ }
+ return KeepTypePattern.any();
+ }
+
public TypePattern.Builder buildProto() {
TypePattern.Builder builder = TypePattern.newBuilder();
match(
@@ -291,7 +294,14 @@
array -> builder.setArray(array.buildProto()),
clazz -> builder.setClazz(clazz.buildProto()),
instanceOf -> {
- throw new Unimplemented();
+ if (instanceOf.isAny()) {
+ // Note that an "any" instance-of pattern should match any class-type
+ // TODO(b/350647134): This should become evident when introducing a class-pattern.
+ // When doing so, consider also if/how to match a general reference type.
+ builder.setClazz(KeepQualifiedClassNamePattern.any().buildProto());
+ } else {
+ instanceOf.buildProto(builder::setInstanceOf);
+ }
});
return builder;
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/ModifierPattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/ModifierPattern.java
index 77ce8ad..1afe19e 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/ModifierPattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/ModifierPattern.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.ast;
+import com.android.tools.r8.keepanno.proto.KeepSpecProtos;
+import java.util.function.Consumer;
+
/** Three-point valued matcher on an access modifier. */
public class ModifierPattern {
@@ -69,4 +72,12 @@
public int hashCode() {
return System.identityHashCode(this);
}
+
+ public void buildProto(Consumer<KeepSpecProtos.ModifierPattern.Builder> callback) {
+ if (isOnlyPositive()) {
+ callback.accept(KeepSpecProtos.ModifierPattern.newBuilder().setValue(true));
+ } else if (isOnlyNegative()) {
+ callback.accept(KeepSpecProtos.ModifierPattern.newBuilder().setValue(false));
+ }
+ }
}
diff --git a/src/keepanno/proto/keepspec.proto b/src/keepanno/proto/keepspec.proto
index 451b137..fd52a93 100644
--- a/src/keepanno/proto/keepspec.proto
+++ b/src/keepanno/proto/keepspec.proto
@@ -83,7 +83,9 @@
message Edge {
MetaInfo meta_info = 1;
- // TODO(b/343389186): Add content.
+ Bindings bindings = 2;
+ repeated Condition preconditions = 3;
+ repeated Target consequences = 4;
}
message Bindings {
@@ -99,6 +101,55 @@
string name = 1;
}
+message Condition {
+ BindingReference item = 1;
+}
+
+message Target {
+ BindingReference item = 1;
+ optional Constraints constraints = 2;
+ repeated Constraint constraint_additions = 3;
+}
+
+message Constraints {
+ repeated Constraint constraints = 1;
+}
+
+enum ConstraintElement {
+ CONSTRAINT_UNSPECIFIED = 0;
+ CONSTRAINT_LOOKUP = 1;
+ CONSTRAINT_NAME = 2;
+ CONSTRAINT_VISIBILITY_RELAX = 3;
+ CONSTRAINT_VISIBILITY_RESTRICT = 4;
+ CONSTRAINT_NEVER_INLINE = 5;
+ CONSTRAINT_CLASS_INSTANTIATE = 6;
+ CONSTRAINT_CLASS_OPEN_HIERARCHY = 7;
+ CONSTRAINT_METHOD_INVOKE = 8;
+ CONSTRAINT_METHOD_REPLACE = 9;
+ CONSTRAINT_FIELD_GET = 10;
+ CONSTRAINT_FIELD_SET = 11;
+ CONSTRAINT_FIELD_REPLACE = 12;
+ CONSTRAINT_GENERIC_SIGNATURE = 13;
+}
+
+message AnnotationPattern {
+ optional AnnotationRetention retention = 1;
+ optional ClassNamePattern name = 2;
+}
+
+enum AnnotationRetention {
+ RETENTION_UNSPECIFIED = 0;
+ RETENTION_RUNTIME = 1;
+ RETENTION_CLASS = 2;
+}
+
+message Constraint {
+ oneof constraint_oneof {
+ ConstraintElement element = 1;
+ AnnotationPattern annotation = 2;
+ }
+}
+
message ItemPattern {
oneof item_oneof {
ClassItemPattern class_item = 1;
@@ -108,8 +159,13 @@
message ClassItemPattern {
optional ClassNamePattern class_name = 1;
- // TODO(b/343389186): Add instance-of.
- // TODO(b/343389186): Add annotated-by.
+ optional InstanceOfPattern instance_of = 2;
+ optional AnnotatedByPattern annotated_by = 3;
+}
+
+message InstanceOfPattern {
+ optional bool inclusive = 1;
+ optional ClassNamePattern class_name = 2;
}
message ClassNamePattern {
@@ -151,6 +207,10 @@
optional StringPattern name = 1;
}
+message AnnotatedByPattern {
+ optional ClassNamePattern name = 1;
+}
+
message MemberItemPattern {
BindingReference class_reference = 1;
optional MemberPattern member_pattern = 2;
@@ -164,20 +224,64 @@
}
}
+enum AccessVisibility {
+ ACCESS_UNSPECIFIED = 0;
+ ACCESS_PUBLIC = 1;
+ ACCESS_PROTECTED = 2;
+ ACCESS_PACKAGE_PRIVATE = 3;
+ ACCESS_PRIVATE = 4;
+}
+
+message AccessVisibilitySet {
+ repeated AccessVisibility access_visibility = 1;
+}
+
+// Placeholder for an optional boolean modifier.
+// The optional value is encoded by it not being present at the reference point.
+message ModifierPattern {
+ bool value = 1;
+}
+
+message MemberAccessGeneral {
+ optional AccessVisibilitySet access_visibility = 1;
+ optional ModifierPattern static_pattern = 2;
+ optional ModifierPattern final_pattern = 3;
+ optional ModifierPattern synthetic_pattern = 4;
+}
+
+message MemberAccessField {
+ optional MemberAccessGeneral general_access = 1;
+ optional ModifierPattern volatile_pattern = 2;
+ optional ModifierPattern transient_pattern = 3;
+}
+
+message MemberAccessMethod {
+ optional MemberAccessGeneral general_access = 1;
+ optional ModifierPattern synchronized_pattern = 2;
+ optional ModifierPattern bridge_pattern = 3;
+ optional ModifierPattern native_pattern = 4;
+ optional ModifierPattern abstract_pattern = 5;
+ optional ModifierPattern strict_fp_pattern = 6;
+}
+
message MemberPatternGeneral {
- // TODO(b/343389186): Add content.
+ optional MemberAccessGeneral access = 1;
+ optional AnnotatedByPattern annotated_by = 2;
}
message MemberPatternField {
- // TODO(b/343389186): Add content.
+ optional MemberAccessField access = 1;
+ optional AnnotatedByPattern annotated_by = 2;
+ optional StringPattern name = 3;
+ optional TypePattern field_type = 4;
}
message MemberPatternMethod {
- optional StringPattern name = 1;
- optional MethodReturnTypePattern return_type = 2;
- optional MethodParameterTypesPattern parameter_types = 3;
- // TODO(b/343389186): Add annotated-by.
- // TODO(b/343389186): Add access.
+ optional MemberAccessMethod access = 1;
+ optional AnnotatedByPattern annotated_by = 2;
+ optional StringPattern name = 3;
+ optional MethodReturnTypePattern return_type = 4;
+ optional MethodParameterTypesPattern parameter_types = 5;
}
message MethodReturnTypePattern {
@@ -202,7 +306,7 @@
TypePatternPrimitive primitive = 1;
TypePatternArray array = 2;
ClassNamePattern clazz = 3;
- // TODO(b/343389186): Add instance-of.
+ InstanceOfPattern instance_of = 4;
}
}
@@ -223,4 +327,3 @@
optional uint32 dimensions = 1;
optional TypePattern base_type = 2;
}
-
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepSpecificationSource.java b/src/main/java/com/android/tools/r8/shaking/KeepSpecificationSource.java
index 1dfda01..72f1164 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepSpecificationSource.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepSpecificationSource.java
@@ -45,7 +45,8 @@
throw new ResourceException(getOrigin(), "Unknown keepspec version " + spec.getVersion());
}
for (Declaration declaration : spec.getDeclarationsList()) {
- KeepDeclaration parsedDeclaration = KeepDeclaration.fromProto(declaration, version);
+ KeepDeclaration parsedDeclaration =
+ KeepDeclaration.fromDeclarationProto(declaration, version);
if (parsedDeclaration == null) {
throw new ResourceException(getOrigin(), "Unable to parse declaration " + declaration);
} else {
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java b/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java
index f39df8f..2c328d0 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.keepanno;
-import static com.android.tools.r8.utils.CfUtils.extractClassDescriptor;
import com.android.tools.r8.ExternalR8TestBuilder;
import com.android.tools.r8.ProguardTestBuilder;
@@ -18,18 +17,13 @@
import com.android.tools.r8.TestShrinkerBuilder;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.keepanno.KeepAnnoParameters.KeepAnnoConfig;
import com.android.tools.r8.keepanno.asm.KeepEdgeReader;
-import com.android.tools.r8.keepanno.asm.KeepEdgeWriter;
import com.android.tools.r8.keepanno.ast.KeepDeclaration;
import com.android.tools.r8.keepanno.ast.KeepSpecVersion;
import com.android.tools.r8.keepanno.keeprules.KeepRuleExtractorOptions;
import com.android.tools.r8.keepanno.proto.KeepSpecProtos.KeepSpec;
-import com.android.tools.r8.keepanno.utils.Unimplemented;
import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.DescriptorUtils;
-import com.android.tools.r8.utils.InternalOptions;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -38,8 +32,6 @@
import java.util.List;
import java.util.function.Consumer;
import org.junit.rules.TemporaryFolder;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Opcodes;
public abstract class KeepAnnoTestBuilder {
@@ -283,49 +275,14 @@
if (isNormalizeEdges()) {
List<KeepDeclaration> declarations = KeepEdgeReader.readKeepEdges(classFileData);
if (!declarations.isEmpty()) {
- List<KeepDeclaration> legacyExtract = new ArrayList<>();
KeepSpec.Builder keepSpecBuilder = KeepSpec.newBuilder();
keepSpecBuilder.setVersion(KeepSpecVersion.getCurrent().buildProto());
for (KeepDeclaration declaration : declarations) {
- try {
- keepSpecBuilder.addDeclarations(declaration.buildDeclarationProto());
- } catch (Unimplemented e) {
- legacyExtract.add(declaration);
- }
+ keepSpecBuilder.addDeclarations(declaration.buildDeclarationProto());
}
builder
.getBuilder()
.addKeepSpecificationData(keepSpecBuilder.build().toByteArray(), Origin.unknown());
- if (legacyExtract.isEmpty()) {
- // TODO(b/343389186): Finish the proto encoding and remove the below extraction.
- return;
- }
- String binaryName =
- DescriptorUtils.getBinaryNameFromDescriptor(extractClassDescriptor(classFileData));
- String synthesizingTarget = binaryName + "$$ExtractedKeepEdges";
- ClassWriter classWriter = new ClassWriter(InternalOptions.ASM_VERSION);
- classWriter.visit(
- Opcodes.V1_8,
- ClassAccessFlags.createPublicFinalSynthetic().getAsCfAccessFlags(),
- synthesizingTarget,
- null,
- "java/lang/Object",
- null);
- KeepEdgeWriter.writeExtractedEdges(
- legacyExtract,
- (descriptor, visible) ->
- KeepAnnoTestUtils.wrap(classWriter.visitAnnotation(descriptor, visible)));
- classWriter.visitEnd();
- builder
- .getBuilder()
- .addClassProgramData(
- classWriter.toByteArray(),
- new Origin(Origin.root()) {
- @Override
- public String part() {
- return "edge-extraction";
- }
- });
}
}
}
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepInclusiveInstanceOfTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepInclusiveInstanceOfTest.java
index 85809df..1293e79 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepInclusiveInstanceOfTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepInclusiveInstanceOfTest.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
import com.android.tools.r8.keepanno.annotations.KeepTarget;
import com.android.tools.r8.keepanno.annotations.UsesReflection;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -34,11 +37,14 @@
.addKeepMainRule(TestClass.class)
.setExcludedOuterClass(getClass())
.run(TestClass.class)
- .assertSuccessWithOutput(EXPECTED);
+ .assertSuccessWithOutput(EXPECTED)
+ .applyIf(
+ parameters.isShrinker(),
+ r -> r.inspect(inspector -> assertThat(inspector.clazz(Unrelated.class), isAbsent())));
}
public List<Class<?>> getInputClasses() {
- return ImmutableList.of(TestClass.class, Base.class, Sub.class, A.class);
+ return ImmutableList.of(TestClass.class, Base.class, Sub.class, A.class, Unrelated.class);
}
static class Base {
@@ -53,6 +59,12 @@
}
}
+ static class Unrelated {
+ static void hiddenMethod() {
+ System.out.println("on Unrelated");
+ }
+ }
+
static class A {
@UsesReflection({
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java
index 8c96fe1..f85dcd7 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java
@@ -41,19 +41,6 @@
.addProgramClasses(getInputClasses())
.addKeepMainRule(TestClass.class)
.setExcludedOuterClass(getClass())
- .inspectOutputConfig(
- rules -> {
- if (parameters.isNativeR8()) {
- // TODO(b/323816623): Once a final distribution format is defined for normalized
- // edges, that format should likely be the bases of the annotation printing too.
- assertThat(rules, containsString("context=" + descriptor(A.class) + "foo()V"));
- assertThat(
- rules, containsString("description=\"Keep the\\nstring-valued fields\""));
- } else {
- assertThat(rules, containsString("context: " + descriptor(A.class) + "foo()V"));
- assertThat(rules, containsString("description: Keep the\\nstring-valued fields"));
- }
- })
.run(TestClass.class)
.assertSuccessWithOutput(EXPECTED)
.applyIf(parameters.isShrinker(), r -> r.inspect(this::checkOutput));