[KeepAnno] Revert all CLs following the enabling of the proto encoding
The proto library uses internal reflection that needs to be kept or
avoided when used in r8lib.
This CL contains reverts of:
Revert "[KeepAnno] Finish remaining proto encoding"
This reverts commit 3030ac61d1760cd1b07a8bc57fffd90827d4fe1e.
Revert "[KeepAnno] Remove annotation based extraction"
This reverts commit 9beb7e2ca303e7ac176a39f1b1da19bad8c95bd2.
Revert "[KeepAnno] Extract rules in the test builder instead of the reader"
This reverts commit c5f041d430892b4e0657c9048932e57262d08773.
Revert "[KeepAnno] Use native interpretation in R8"
This reverts commit 57a02ee85383a73cb9fa077eae6336dcd6bea5bc.
Revert "[KeepAnno] Retain the system property to enable keep annotations"
This reverts commit 531039f35b8a9e658589452f532c0f4e894d0f51.
Revert "[KeepAnno] Filter out keep-anno rules from compat behavior"
This reverts commit 47a6cba85eb4ecaba3d496bb5c524601826bcd1c.
Revert "Don't override keep-annotation system property if set"
This reverts commit bb3db8e917e1a98df8ee960008e232a106a85ec5.
Reapply "[KeepAnno] Use native interpretation in R8"
This reverts commit 79b516d4dbfc59e50916d0769d497ec2bc1e4d72.
Bug: b/343389186
Change-Id: I07b1f89bb899daaa7dd0f60d7d9944884e70df03
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java
index c37ef50..ad230d1 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java
@@ -13,6 +13,8 @@
import com.android.tools.r8.keepanno.ast.AnnotationConstants.Binding;
import com.android.tools.r8.keepanno.ast.AnnotationConstants.Condition;
import com.android.tools.r8.keepanno.ast.AnnotationConstants.Edge;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.ExtractedAnnotation;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.ExtractedAnnotations;
import com.android.tools.r8.keepanno.ast.AnnotationConstants.FieldAccess;
import com.android.tools.r8.keepanno.ast.AnnotationConstants.ForApi;
import com.android.tools.r8.keepanno.ast.AnnotationConstants.Item;
@@ -35,6 +37,7 @@
import com.android.tools.r8.keepanno.ast.KeepConstraints;
import com.android.tools.r8.keepanno.ast.KeepDeclaration;
import com.android.tools.r8.keepanno.ast.KeepEdge;
+import com.android.tools.r8.keepanno.ast.KeepEdgeException;
import com.android.tools.r8.keepanno.ast.KeepEdgeMetaInfo;
import com.android.tools.r8.keepanno.ast.KeepFieldAccessPattern;
import com.android.tools.r8.keepanno.ast.KeepFieldNamePattern;
@@ -88,7 +91,7 @@
public static int ASM_VERSION = ASM9;
public static boolean isClassKeepAnnotation(String descriptor, boolean visible) {
- return !visible && isEmbeddedAnnotation(descriptor);
+ return !visible && (isExtractedAnnotation(descriptor) || isEmbeddedAnnotation(descriptor));
}
public static boolean isFieldKeepAnnotation(String descriptor, boolean visible) {
@@ -99,6 +102,10 @@
return !visible && isEmbeddedAnnotation(descriptor);
}
+ private static boolean isExtractedAnnotation(String descriptor) {
+ return ExtractedAnnotations.DESCRIPTOR.equals(descriptor);
+ }
+
private static boolean isEmbeddedAnnotation(String descriptor) {
switch (descriptor) {
case AnnotationConstants.Edge.DESCRIPTOR:
@@ -115,14 +122,20 @@
}
public static List<KeepDeclaration> readKeepEdges(byte[] classFileBytes) {
- return internalReadKeepEdges(classFileBytes, true);
+ return internalReadKeepEdges(classFileBytes, true, false);
+ }
+
+ public static List<KeepDeclaration> readExtractedKeepEdges(byte[] classFileBytes) {
+ return internalReadKeepEdges(classFileBytes, false, true);
}
private static List<KeepDeclaration> internalReadKeepEdges(
- byte[] classFileBytes, boolean readEmbedded) {
+ byte[] classFileBytes, boolean readEmbedded, boolean readExtracted) {
ClassReader reader = new ClassReader(classFileBytes);
List<KeepDeclaration> declarations = new ArrayList<>();
- reader.accept(new KeepEdgeClassVisitor(readEmbedded, declarations::add), ClassReader.SKIP_CODE);
+ reader.accept(
+ new KeepEdgeClassVisitor(readEmbedded, readExtracted, declarations::add),
+ ClassReader.SKIP_CODE);
return declarations;
}
@@ -130,6 +143,7 @@
String descriptor,
boolean visible,
boolean readEmbedded,
+ boolean readExtracted,
String className,
AnnotationParsingContext parsingContext,
Consumer<KeepDeclaration> callback) {
@@ -137,6 +151,7 @@
descriptor,
visible,
readEmbedded,
+ readExtracted,
callback,
parsingContext,
className,
@@ -150,6 +165,7 @@
String descriptor,
boolean visible,
boolean readEmbedded,
+ boolean readExtracted,
String className,
String fieldName,
String fieldTypeDescriptor,
@@ -159,6 +175,7 @@
descriptor,
visible,
readEmbedded,
+ readExtracted,
callback::accept,
parsingContext,
className,
@@ -176,6 +193,7 @@
String descriptor,
boolean visible,
boolean readEmbedded,
+ boolean readExtracted,
String className,
String methodName,
String methodDescriptor,
@@ -185,6 +203,7 @@
descriptor,
visible,
readEmbedded,
+ readExtracted,
callback::accept,
parsingContext,
className,
@@ -286,13 +305,16 @@
private static class KeepEdgeClassVisitor extends ClassVisitor {
private final boolean readEmbedded;
+ private final boolean readExtracted;
private final Parent<KeepDeclaration> parent;
private String className;
private ClassParsingContext parsingContext;
- KeepEdgeClassVisitor(boolean readEmbedded, Parent<KeepDeclaration> parent) {
+ KeepEdgeClassVisitor(
+ boolean readEmbedded, boolean readExtracted, Parent<KeepDeclaration> parent) {
super(ASM_VERSION);
this.readEmbedded = readEmbedded;
+ this.readExtracted = readExtracted;
this.parent = parent;
}
@@ -323,6 +345,7 @@
descriptor,
visible,
readEmbedded,
+ readExtracted,
parent::accept,
annotationParsingContext(descriptor),
className,
@@ -333,6 +356,7 @@
String descriptor,
boolean visible,
boolean readEmbedded,
+ boolean readExtracted,
Consumer<KeepDeclaration> parent,
AnnotationParsingContext parsingContext,
String className,
@@ -342,6 +366,9 @@
return null;
}
+ if (readExtracted && isExtractedAnnotation(descriptor)) {
+ return new ExtractedAnnotationsVisitor(parsingContext, parent::accept);
+ }
if (!readEmbedded || !isEmbeddedAnnotation(descriptor)) {
return null;
}
@@ -463,6 +490,7 @@
descriptor,
visible,
true,
+ false,
parent::accept,
annotationParsingContext(descriptor),
className,
@@ -475,6 +503,7 @@
String descriptor,
boolean visible,
boolean readEmbedded,
+ boolean readExtracted,
Consumer<KeepDeclaration> parent,
AnnotationParsingContext parsingContext,
String className,
@@ -598,6 +627,7 @@
descriptor,
visible,
true,
+ false,
parent::accept,
annotationParsingContext(descriptor),
className,
@@ -610,6 +640,7 @@
String descriptor,
boolean visible,
boolean readEmbedded,
+ boolean readExtracted,
Consumer<KeepEdge> parent,
AnnotationParsingContext parsingContext,
String className,
@@ -741,6 +772,156 @@
}
}
+ public static class ExtractedAnnotationsVisitor extends AnnotationVisitorBase {
+
+ private final Parent<KeepDeclaration> parent;
+ private List<KeepDeclaration> declarations = new ArrayList<>();
+
+ public ExtractedAnnotationsVisitor(
+ AnnotationParsingContext parsingContext, Parent<KeepDeclaration> parent) {
+ super(parsingContext);
+ this.parent = parent;
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String name) {
+ if (name.equals(ExtractedAnnotations.value)) {
+ PropertyParsingContext parsingContext = getParsingContext().property(name);
+ return new AnnotationVisitorBase(parsingContext) {
+ @Override
+ public AnnotationVisitor visitAnnotation(String nullName, String descriptor) {
+ assert nullName == null;
+ if (descriptor.equals(ExtractedAnnotation.DESCRIPTOR)) {
+ return new ExtractedAnnotationVisitor(
+ parsingContext.annotation(descriptor), declarations::add);
+ }
+ return super.visitAnnotation(nullName, descriptor);
+ }
+ };
+ }
+ return super.visitArray(name);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (declarations.isEmpty()) {
+ throw new KeepEdgeException("Invalid extracted annotation set, expected non-empty.");
+ }
+ declarations.forEach(parent::accept);
+ super.visitEnd();
+ }
+ }
+
+ private static class ExtractedAnnotationVisitor extends AnnotationVisitorBase {
+
+ private final Parent<KeepDeclaration> parent;
+ private ContextDescriptor context = null;
+ private String version = null;
+ private KeepEdgeVisitor edgeVisitor = null;
+ private boolean isCheckRemoved = false;
+ private boolean isCheckOptimizedOut = false;
+
+ public ExtractedAnnotationVisitor(
+ AnnotationParsingContext parsingContext, Parent<KeepDeclaration> parent) {
+ super(parsingContext);
+ this.parent = parent;
+ }
+
+ private void ensureVersion(ParsingContext parsingContext) {
+ if (version == null) {
+ parsingContext.error("Property 'version' must be defined before any other property");
+ }
+ }
+
+ @Override
+ public void visit(String name, Object value) {
+ if (name.equals(ExtractedAnnotation.version) && value instanceof String) {
+ version = (String) value;
+ return;
+ }
+ ParsingContext parsingContext = getParsingContext().property(name);
+ ensureVersion(parsingContext);
+ if (name.equals(ExtractedAnnotation.context) && value instanceof String) {
+ context = ContextDescriptor.parse((String) value, parsingContext);
+ return;
+ }
+ if (name.equals(ExtractedAnnotation.checkRemoved) && value instanceof Boolean) {
+ isCheckRemoved = true;
+ return;
+ }
+ if (name.equals(ExtractedAnnotation.checkOptimizedOut) && value instanceof Boolean) {
+ isCheckOptimizedOut = true;
+ return;
+ }
+ super.visit(name, value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ if (name.equals(ExtractedAnnotation.edge) && descriptor.equals(Edge.DESCRIPTOR)) {
+ edgeVisitor =
+ new KeepEdgeVisitor(
+ getParsingContext().annotation(descriptor), edge -> {}, builder -> {});
+ return edgeVisitor;
+ }
+ return super.visitAnnotation(name, descriptor);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (version == null) {
+ throw getParsingContext()
+ .error("Invalid extracted annotation, expected a version property.");
+ }
+ if (context == null) {
+ throw getParsingContext()
+ .error("Invalid extracted annotation, expected a context property.");
+ }
+ if (edgeVisitor != null) {
+ if (isCheckRemoved || isCheckOptimizedOut) {
+ throw getParsingContext()
+ .error("Invalid extracted annotation, cannot be both an edge and check.");
+ }
+ parent.accept(
+ edgeVisitor
+ .builder
+ .setMetaInfo(context.applyToMetadata(edgeVisitor.metaInfoBuilder).build())
+ .build());
+ return;
+ }
+ if (isCheckRemoved && isCheckOptimizedOut) {
+ throw getParsingContext()
+ .error(
+ "Invalid extracted annotation, cannot be both a removed and optimized-out check.");
+ }
+ if (!isCheckRemoved && !isCheckOptimizedOut) {
+ throw getParsingContext()
+ .error(
+ "Invalid extracted annotation, must specify either an edge, a removed check, or an"
+ + " optimized-out check.");
+ }
+ KeepEdgeMetaInfo metaInfo = context.applyToMetadata(KeepEdgeMetaInfo.builder()).build();
+ KeepCheckKind kind = isCheckRemoved ? KeepCheckKind.REMOVED : KeepCheckKind.OPTIMIZED_OUT;
+ UserBindingsHelper bindingsHelper = new UserBindingsHelper();
+ KeepBindingReference contextBinding = context.defineBindingReference(bindingsHelper);
+ parent.accept(buildKeepCheckFromItem(metaInfo, kind, contextBinding, bindingsHelper));
+ super.visitEnd();
+ }
+
+ private static KeepCheck buildKeepCheckFromItem(
+ KeepEdgeMetaInfo metaInfo,
+ KeepCheckKind kind,
+ KeepBindingReference itemReference,
+ UserBindingsHelper bindingsHelper) {
+ return KeepCheck.builder()
+ .setMetaInfo(metaInfo)
+ .setKind(kind)
+ .setBindings(bindingsHelper.build())
+ .setItemReference(itemReference)
+ .build();
+ }
+ }
+
private static class KeepEdgeVisitor extends AnnotationVisitorBase {
private final ParsingContext parsingContext;
@@ -1495,20 +1676,9 @@
@Override
public void visitEnd() {
super.visitEnd();
- parent.accept(buildKeepCheckFromItem(metaInfoBuilder.build(), kind, context, bindingsHelper));
- }
-
- private static KeepCheck buildKeepCheckFromItem(
- KeepEdgeMetaInfo metaInfo,
- KeepCheckKind kind,
- KeepBindingReference itemReference,
- UserBindingsHelper bindingsHelper) {
- return KeepCheck.builder()
- .setMetaInfo(metaInfo)
- .setKind(kind)
- .setBindings(bindingsHelper.build())
- .setItemReference(itemReference)
- .build();
+ parent.accept(
+ ExtractedAnnotationVisitor.buildKeepCheckFromItem(
+ metaInfoBuilder.build(), kind, context, bindingsHelper));
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeWriter.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeWriter.java
new file mode 100644
index 0000000..2645b35
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeWriter.java
@@ -0,0 +1,603 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.keepanno.asm;
+
+import com.android.tools.r8.keepanno.ast.AccessVisibility;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.AnnotationPattern;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Binding;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.ClassNamePattern;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Condition;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Constraints;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Edge;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.ExtractedAnnotation;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.ExtractedAnnotations;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.FieldAccess;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.InstanceOfPattern;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Item;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Kind;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.MemberAccess;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.MethodAccess;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.StringPattern;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Target;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.TypePattern;
+import com.android.tools.r8.keepanno.ast.KeepAnnotationPattern;
+import com.android.tools.r8.keepanno.ast.KeepBindingReference;
+import com.android.tools.r8.keepanno.ast.KeepBindings;
+import com.android.tools.r8.keepanno.ast.KeepClassBindingReference;
+import com.android.tools.r8.keepanno.ast.KeepClassItemPattern;
+import com.android.tools.r8.keepanno.ast.KeepConsequences;
+import com.android.tools.r8.keepanno.ast.KeepConstraint;
+import com.android.tools.r8.keepanno.ast.KeepConstraints;
+import com.android.tools.r8.keepanno.ast.KeepDeclaration;
+import com.android.tools.r8.keepanno.ast.KeepEdge;
+import com.android.tools.r8.keepanno.ast.KeepEdgeException;
+import com.android.tools.r8.keepanno.ast.KeepEdgeMetaInfo;
+import com.android.tools.r8.keepanno.ast.KeepFieldAccessPattern;
+import com.android.tools.r8.keepanno.ast.KeepFieldPattern;
+import com.android.tools.r8.keepanno.ast.KeepInstanceOfPattern;
+import com.android.tools.r8.keepanno.ast.KeepItemPattern;
+import com.android.tools.r8.keepanno.ast.KeepMemberAccessPattern;
+import com.android.tools.r8.keepanno.ast.KeepMemberItemPattern;
+import com.android.tools.r8.keepanno.ast.KeepMemberPattern;
+import com.android.tools.r8.keepanno.ast.KeepMethodAccessPattern;
+import com.android.tools.r8.keepanno.ast.KeepMethodParametersPattern;
+import com.android.tools.r8.keepanno.ast.KeepMethodPattern;
+import com.android.tools.r8.keepanno.ast.KeepMethodReturnTypePattern;
+import com.android.tools.r8.keepanno.ast.KeepPackagePattern;
+import com.android.tools.r8.keepanno.ast.KeepPreconditions;
+import com.android.tools.r8.keepanno.ast.KeepQualifiedClassNamePattern;
+import com.android.tools.r8.keepanno.ast.KeepStringPattern;
+import com.android.tools.r8.keepanno.ast.KeepTarget;
+import com.android.tools.r8.keepanno.ast.KeepTypePattern;
+import com.android.tools.r8.keepanno.ast.ModifierPattern;
+import com.android.tools.r8.keepanno.ast.OptionalPattern;
+import com.android.tools.r8.keepanno.utils.Unimplemented;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+public class KeepEdgeWriter implements Opcodes {
+
+ /** Annotation visitor interface to allow usage from tests without type conflicts in r8lib. */
+ public interface AnnotationVisitorInterface {
+ int version();
+
+ void visit(String name, Object value);
+
+ void visitEnum(String name, String descriptor, String value);
+
+ AnnotationVisitorInterface visitAnnotation(String name, String descriptor);
+
+ AnnotationVisitorInterface visitArray(String name);
+
+ void visitEnd();
+ }
+
+ private static AnnotationVisitor wrap(AnnotationVisitorInterface visitor) {
+ if (visitor == null) {
+ return null;
+ }
+ return new AnnotationVisitor(visitor.version()) {
+
+ @Override
+ public void visit(String name, Object value) {
+ visitor.visit(name, value);
+ }
+
+ @Override
+ public void visitEnum(String name, String descriptor, String value) {
+ visitor.visitEnum(name, descriptor, value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ AnnotationVisitorInterface v = visitor.visitAnnotation(name, descriptor);
+ return v == visitor ? this : wrap(v);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitorInterface v = visitor.visitArray(name);
+ return v == visitor ? this : wrap(v);
+ }
+
+ @Override
+ public void visitEnd() {
+ visitor.visitEnd();
+ }
+ };
+ }
+
+ // Helper to ensure that any call creating a new annotation visitor is statically scoped with its
+ // call to visit end.
+ private static void withNewVisitor(AnnotationVisitor visitor, Consumer<AnnotationVisitor> fn) {
+ fn.accept(visitor);
+ visitor.visitEnd();
+ }
+
+ public static void writeExtractedEdges(
+ List<KeepDeclaration> declarations,
+ BiFunction<String, Boolean, AnnotationVisitorInterface> getVisitor) {
+ if (declarations.isEmpty()) {
+ return;
+ }
+ withNewVisitor(
+ wrap(getVisitor.apply(ExtractedAnnotations.DESCRIPTOR, false)),
+ containerVisitor ->
+ withNewVisitor(
+ containerVisitor.visitArray(ExtractedAnnotations.value),
+ arrayVisitor ->
+ declarations.forEach(
+ decl ->
+ withNewVisitor(
+ arrayVisitor.visitAnnotation(null, ExtractedAnnotation.DESCRIPTOR),
+ extractVisitor -> writeExtractedEdge(extractVisitor, decl)))));
+ }
+
+ private static void writeExtractedEdge(AnnotationVisitor visitor, KeepDeclaration decl) {
+ KeepEdgeMetaInfo metaInfo = decl.getMetaInfo();
+ visitor.visit(ExtractedAnnotation.version, metaInfo.getVersion().toVersionString());
+ visitor.visit(ExtractedAnnotation.context, metaInfo.getContextDescriptorString());
+ decl.match(
+ edge -> {
+ withNewVisitor(
+ visitor.visitAnnotation(ExtractedAnnotation.edge, Edge.DESCRIPTOR),
+ v -> new KeepEdgeWriter().writeEdge(edge, v));
+ },
+ check -> {
+ switch (check.getKind()) {
+ case REMOVED:
+ visitor.visit(ExtractedAnnotation.checkRemoved, true);
+ break;
+ case OPTIMIZED_OUT:
+ visitor.visit(ExtractedAnnotation.checkOptimizedOut, true);
+ break;
+ default:
+ throw new KeepEdgeException("Unexpected keep check kind: " + check.getKind());
+ }
+ });
+ }
+
+ private void writeEdge(KeepEdge edge, AnnotationVisitor visitor) {
+ writeMetaInfo(visitor, edge.getMetaInfo());
+ writeBindings(visitor, edge.getBindings());
+ writePreconditions(visitor, edge.getPreconditions());
+ writeConsequences(visitor, edge.getConsequences());
+ }
+
+ private void writeMetaInfo(AnnotationVisitor visitor, KeepEdgeMetaInfo metaInfo) {
+ // The edge version and context is written in the extraction header.
+ if (metaInfo.hasDescription()) {
+ visitor.visit(Edge.description, metaInfo.getDescriptionString());
+ }
+ }
+
+ private void writeBindings(AnnotationVisitor visitor, KeepBindings bindings) {
+ if (bindings.isEmpty()) {
+ return;
+ }
+ withNewVisitor(
+ visitor.visitArray(Edge.bindings),
+ arrayVisitor -> {
+ bindings.forEach(
+ (symbol, item) -> {
+ withNewVisitor(
+ arrayVisitor.visitAnnotation(null, Binding.DESCRIPTOR),
+ bindingVisitor -> {
+ bindingVisitor.visit(Binding.bindingName, symbol.toString());
+ // The item is written directly into the binding annotation.
+ writeItem(bindingVisitor, item);
+ });
+ });
+ });
+ }
+
+ private void writeStringPattern(
+ KeepStringPattern stringPattern, String propertyName, AnnotationVisitor visitor) {
+ withNewVisitor(
+ visitor.visitAnnotation(propertyName, AnnotationConstants.StringPattern.DESCRIPTOR),
+ v -> {
+ if (stringPattern.isAny()) {
+ // The emtpy pattern matches any string.
+ return;
+ }
+ if (stringPattern.isExact()) {
+ v.visit(StringPattern.exact, stringPattern.asExactString());
+ return;
+ }
+ if (stringPattern.hasPrefix()) {
+ v.visit(StringPattern.startsWith, stringPattern.getPrefixString());
+ }
+ if (stringPattern.hasSuffix()) {
+ v.visit(StringPattern.endsWith, stringPattern.getSuffixString());
+ }
+ });
+ }
+
+ private void writePreconditions(AnnotationVisitor visitor, KeepPreconditions preconditions) {
+ if (preconditions.isAlways()) {
+ return;
+ }
+ String ignoredArrayValueName = null;
+ withNewVisitor(
+ visitor.visitArray(Edge.preconditions),
+ arrayVisitor ->
+ preconditions.forEach(
+ condition ->
+ withNewVisitor(
+ arrayVisitor.visitAnnotation(ignoredArrayValueName, Condition.DESCRIPTOR),
+ conditionVisitor ->
+ writeItemReference(conditionVisitor, condition.getItem()))));
+ }
+
+ private void writeConsequences(AnnotationVisitor visitor, KeepConsequences consequences) {
+ assert !consequences.isEmpty();
+ String ignoredArrayValueName = null;
+ withNewVisitor(
+ visitor.visitArray(Edge.consequences),
+ arrayVisitor ->
+ consequences.forEachTarget(
+ target ->
+ withNewVisitor(
+ arrayVisitor.visitAnnotation(ignoredArrayValueName, Target.DESCRIPTOR),
+ targetVisitor -> writeTarget(target, targetVisitor))));
+ }
+
+ private void writeTarget(KeepTarget target, AnnotationVisitor visitor) {
+ writeConstraints(visitor, target.getConstraints(), target.getItem());
+ writeItemReference(visitor, target.getItem());
+ }
+
+ private void writeConstraints(
+ AnnotationVisitor visitor, KeepConstraints constraints, KeepBindingReference item) {
+ Set<KeepConstraint> typedConstraints;
+ if (item.isClassType()) {
+ typedConstraints = constraints.getClassConstraints();
+ } else {
+ typedConstraints = constraints.getMemberConstraints();
+ }
+
+ List<String> constraintEnumValues = new ArrayList<>();
+ List<KeepAnnotationPattern> annotationConstraints = new ArrayList<>();
+ for (KeepConstraint constraint : typedConstraints) {
+ String value = constraint.getEnumValue();
+ if (value != null) {
+ constraintEnumValues.add(value);
+ continue;
+ }
+ KeepAnnotationPattern annotationPattern = constraint.asAnnotationPattern();
+ if (annotationPattern != null) {
+ annotationConstraints.add(annotationPattern);
+ continue;
+ }
+ throw new Unimplemented("Missing: " + constraint.getClass().toString());
+ }
+ // The default constraints is *not* the empty set, so always write it as defined.
+ constraintEnumValues.sort(String::compareTo);
+ withNewVisitor(
+ visitor.visitArray(Target.constraints),
+ arrayVisitor ->
+ constraintEnumValues.forEach(
+ c -> arrayVisitor.visitEnum(null, Constraints.DESCRIPTOR, c)));
+ if (!annotationConstraints.isEmpty()) {
+ if (annotationConstraints.size() > 1) {
+ annotationConstraints.sort(
+ Comparator.comparing((KeepAnnotationPattern p) -> p.getNamePattern().toString())
+ .thenComparingInt(p -> p.includesClassRetention() ? 1 : 0)
+ .thenComparingInt(p -> p.includesRuntimeRetention() ? 1 : 0));
+ }
+ withNewVisitor(
+ visitor.visitArray(Target.constrainAnnotations),
+ arrayVisitor ->
+ annotationConstraints.forEach(
+ annotation -> {
+ withNewVisitor(
+ arrayVisitor.visitAnnotation(null, AnnotationPattern.DESCRIPTOR),
+ annoVisitor -> {
+ writeClassNamePattern(
+ annotation.getNamePattern(),
+ AnnotationPattern.namePattern,
+ annoVisitor);
+ assert annotation.includesClassRetention()
+ || annotation.includesRuntimeRetention();
+ withNewVisitor(
+ annoVisitor.visitArray(AnnotationPattern.retention),
+ retentionArrayVisitor -> {
+ if (annotation.includesClassRetention()) {
+ retentionArrayVisitor.visitEnum(
+ null,
+ "Ljava/lang/annotation/RetentionPolicy;",
+ RetentionPolicy.CLASS.name());
+ }
+ if (annotation.includesRuntimeRetention()) {
+ retentionArrayVisitor.visitEnum(
+ null,
+ "Ljava/lang/annotation/RetentionPolicy;",
+ RetentionPolicy.RUNTIME.name());
+ }
+ });
+ });
+ }));
+ }
+ }
+
+ private void writeItemReference(
+ AnnotationVisitor visitor, KeepBindingReference bindingReference) {
+ String bindingProperty =
+ bindingReference.isClassType() ? Item.classFromBinding : Item.memberFromBinding;
+ visitor.visit(bindingProperty, bindingReference.getName().toString());
+ }
+
+ private void writeItem(AnnotationVisitor itemVisitor, KeepItemPattern item) {
+ if (item.isClassItemPattern()) {
+ writeClassItem(item.asClassItemPattern(), itemVisitor);
+ } else {
+ writeMemberItem(item.asMemberItemPattern(), itemVisitor);
+ }
+ }
+
+ private void writeClassItem(
+ KeepClassItemPattern classItemPattern, AnnotationVisitor itemVisitor) {
+ writeAnnotatedBy(
+ Item.classAnnotatedByClassNamePattern,
+ classItemPattern.getAnnotatedByPattern(),
+ itemVisitor);
+ writeClassNamePattern(
+ classItemPattern.getClassNamePattern(), Item.classNamePattern, itemVisitor);
+ writeInstanceOfPattern(classItemPattern.getInstanceOfPattern(), itemVisitor);
+ }
+
+ private void writeInstanceOfPattern(
+ KeepInstanceOfPattern instanceOfPattern, AnnotationVisitor visitor) {
+ if (instanceOfPattern.isAny()) {
+ return;
+ }
+ withNewVisitor(
+ visitor.visitAnnotation(Item.instanceOfPattern, InstanceOfPattern.DESCRIPTOR),
+ v -> {
+ v.visit(InstanceOfPattern.inclusive, instanceOfPattern.isInclusive());
+ writeClassNamePattern(
+ instanceOfPattern.getClassNamePattern(), InstanceOfPattern.classNamePattern, v);
+ });
+ }
+
+ private void writeMemberItem(
+ KeepMemberItemPattern memberItemPattern, AnnotationVisitor itemVisitor) {
+ KeepClassBindingReference bindingReference = memberItemPattern.getClassReference();
+ itemVisitor.visit(Item.classFromBinding, bindingReference.getName().toString());
+ writeMember(memberItemPattern.getMemberPattern(), itemVisitor);
+ }
+
+ private void writeMember(KeepMemberPattern memberPattern, AnnotationVisitor targetVisitor) {
+ if (memberPattern.isAllMembers()) {
+ // Due to the empty default being a class, we need to set the kind to members.
+ targetVisitor.visitEnum(Target.kind, Kind.DESCRIPTOR, Kind.ONLY_MEMBERS);
+ } else if (memberPattern.isMethod()) {
+ writeMethod(memberPattern.asMethod(), targetVisitor);
+ } else if (memberPattern.isField()) {
+ writeField(memberPattern.asField(), targetVisitor);
+ } else {
+ writeGeneralMember(memberPattern, targetVisitor);
+ }
+ }
+
+ private void writeGeneralMember(KeepMemberPattern member, AnnotationVisitor targetVisitor) {
+ assert member.isGeneralMember();
+ assert !member.isField();
+ assert !member.isMethod();
+ writeAnnotatedBy(
+ Item.memberAnnotatedByClassNamePattern, member.getAnnotatedByPattern(), targetVisitor);
+ writeGeneralMemberAccessPattern(Item.memberAccess, member.getAccessPattern(), targetVisitor);
+ }
+
+ private void writeField(KeepFieldPattern field, AnnotationVisitor targetVisitor) {
+ writeAnnotatedBy(
+ Item.fieldAnnotatedByClassNamePattern, field.getAnnotatedByPattern(), targetVisitor);
+ writeFieldAccessPattern(Item.fieldAccess, field.getAccessPattern(), targetVisitor);
+ writeStringPattern(
+ field.getNamePattern().asStringPattern(), Item.fieldNamePattern, targetVisitor);
+ if (!field.getTypePattern().isAny()) {
+ writeTypePattern(field.getTypePattern().asType(), Item.fieldTypePattern, targetVisitor);
+ }
+ }
+
+ private void writeMethod(KeepMethodPattern method, AnnotationVisitor targetVisitor) {
+ writeAnnotatedBy(
+ Item.methodAnnotatedByClassNamePattern, method.getAnnotatedByPattern(), targetVisitor);
+ writeMethodAccessPattern(Item.methodAccess, method.getAccessPattern(), targetVisitor);
+ writeStringPattern(
+ method.getNamePattern().asStringPattern(), Item.methodNamePattern, targetVisitor);
+ writeMethodReturnType(method.getReturnTypePattern(), targetVisitor);
+ writeMethodParameters(method.getParametersPattern(), targetVisitor);
+ }
+
+ private void writeMethodParameters(
+ KeepMethodParametersPattern parametersPattern, AnnotationVisitor targetVisitor) {
+ if (parametersPattern.isAny()) {
+ return;
+ }
+ withNewVisitor(
+ targetVisitor.visitArray(Item.methodParameterTypePatterns),
+ v ->
+ parametersPattern
+ .asList()
+ .forEach(parameterPattern -> writeTypePattern(parameterPattern, null, v)));
+ }
+
+ private void writeMethodReturnType(
+ KeepMethodReturnTypePattern returnTypePattern, AnnotationVisitor targetVisitor) {
+ if (returnTypePattern.isAny()) {
+ return;
+ }
+ if (returnTypePattern.isVoid()) {
+ targetVisitor.visit(Item.methodReturnType, "void");
+ return;
+ }
+ assert returnTypePattern.isType();
+ writeTypePattern(returnTypePattern.asType(), Item.methodReturnTypePattern, targetVisitor);
+ }
+
+ private void writeTypePattern(
+ KeepTypePattern typePattern, String propertyName, AnnotationVisitor targetVisitor) {
+ withNewVisitor(
+ targetVisitor.visitAnnotation(propertyName, TypePattern.DESCRIPTOR),
+ v ->
+ typePattern.match(
+ () -> {
+ // The empty type pattern matches any type.
+ },
+ primitive -> {
+ if (primitive.isAny()) {
+ throw new Unimplemented("No support for any-primitive.");
+ }
+ v.visit(TypePattern.name, Type.getType(primitive.getDescriptor()).getClassName());
+ },
+ array -> {
+ v.visit(TypePattern.name, Type.getType(array.getDescriptor()).getClassName());
+ },
+ clazz -> {
+ writeClassNamePattern(clazz, TypePattern.classNamePattern, v);
+ },
+ instanceOf -> {
+ writeInstanceOfPattern(instanceOf, v);
+ }));
+ }
+
+ private void writeClassNamePattern(
+ KeepQualifiedClassNamePattern clazz, String propertyName, AnnotationVisitor visitor) {
+ withNewVisitor(
+ visitor.visitAnnotation(propertyName, ClassNamePattern.DESCRIPTOR),
+ v -> {
+ if (clazz.isAny()) {
+ // The empty pattern matches any class-name
+ return;
+ }
+ KeepPackagePattern packagePattern = clazz.getPackagePattern();
+ if (!packagePattern.isAny()) {
+ assert packagePattern.isExact();
+ v.visit(ClassNamePattern.packageName, packagePattern.getExactPackageAsString());
+ }
+ writeStringPattern(
+ clazz.getNamePattern().asStringPattern(), ClassNamePattern.unqualifiedNamePattern, v);
+ });
+ }
+
+ private void writeAnnotatedBy(
+ String propertyName,
+ OptionalPattern<KeepQualifiedClassNamePattern> annotatedByPattern,
+ AnnotationVisitor targetVisitor) {
+ if (annotatedByPattern.isPresent()) {
+ writeClassNamePattern(annotatedByPattern.get(), propertyName, targetVisitor);
+ }
+ }
+
+ private void writeModifierEnumValue(
+ ModifierPattern pattern, String value, String desc, AnnotationVisitor arrayVisitor) {
+ if (pattern.isAny()) {
+ return;
+ }
+ if (pattern.isOnlyPositive()) {
+ arrayVisitor.visitEnum(null, desc, value);
+ return;
+ }
+ assert pattern.isOnlyNegative();
+ arrayVisitor.visitEnum(null, desc, MemberAccess.NEGATION_PREFIX + value);
+ }
+
+ private void writeGeneralMemberAccessPattern(
+ String propertyName, KeepMemberAccessPattern accessPattern, AnnotationVisitor targetVisitor) {
+ internalWriteAccessPattern(
+ propertyName, accessPattern, targetVisitor, MemberAccess.DESCRIPTOR, v -> {});
+ }
+
+ private void writeFieldAccessPattern(
+ String propertyName, KeepFieldAccessPattern accessPattern, AnnotationVisitor targetVisitor) {
+ String enumDescriptor = FieldAccess.DESCRIPTOR;
+ internalWriteAccessPattern(
+ propertyName,
+ accessPattern,
+ targetVisitor,
+ enumDescriptor,
+ visitor -> {
+ writeModifierEnumValue(
+ accessPattern.getVolatilePattern(), FieldAccess.VOLATILE, enumDescriptor, visitor);
+ writeModifierEnumValue(
+ accessPattern.getTransientPattern(), FieldAccess.TRANSIENT, enumDescriptor, visitor);
+ });
+ }
+
+ private void writeMethodAccessPattern(
+ String propertyName, KeepMethodAccessPattern accessPattern, AnnotationVisitor targetVisitor) {
+ String enumDescriptor = MethodAccess.DESCRIPTOR;
+ internalWriteAccessPattern(
+ propertyName,
+ accessPattern,
+ targetVisitor,
+ enumDescriptor,
+ visitor -> {
+ writeModifierEnumValue(
+ accessPattern.getSynchronizedPattern(),
+ MethodAccess.SYNCHRONIZED,
+ enumDescriptor,
+ visitor);
+ writeModifierEnumValue(
+ accessPattern.getBridgePattern(), MethodAccess.BRIDGE, enumDescriptor, visitor);
+ writeModifierEnumValue(
+ accessPattern.getNativePattern(), MethodAccess.NATIVE, enumDescriptor, visitor);
+ writeModifierEnumValue(
+ accessPattern.getAbstractPattern(), MethodAccess.ABSTRACT, enumDescriptor, visitor);
+ writeModifierEnumValue(
+ accessPattern.getStrictFpPattern(), MethodAccess.STRICT_FP, enumDescriptor, visitor);
+ });
+ }
+
+ private void internalWriteAccessPattern(
+ String propertyName,
+ KeepMemberAccessPattern accessPattern,
+ AnnotationVisitor targetVisitor,
+ String enumDescriptor,
+ Consumer<AnnotationVisitor> typeSpecificSettings) {
+ if (accessPattern.isAny()) {
+ return;
+ }
+ withNewVisitor(
+ targetVisitor.visitArray(propertyName),
+ visitor -> {
+ if (!accessPattern.isAnyVisibility()) {
+ for (AccessVisibility visibility : accessPattern.getAllowedAccessVisibilities()) {
+ switch (visibility) {
+ case PUBLIC:
+ visitor.visitEnum(null, enumDescriptor, MemberAccess.PUBLIC);
+ break;
+ case PROTECTED:
+ visitor.visitEnum(null, enumDescriptor, MemberAccess.PROTECTED);
+ break;
+ case PACKAGE_PRIVATE:
+ visitor.visitEnum(null, enumDescriptor, MemberAccess.PACKAGE_PRIVATE);
+ break;
+ case PRIVATE:
+ visitor.visitEnum(null, enumDescriptor, MemberAccess.PRIVATE);
+ break;
+ }
+ }
+ }
+ writeModifierEnumValue(
+ accessPattern.getStaticPattern(), MemberAccess.STATIC, enumDescriptor, visitor);
+ writeModifierEnumValue(
+ accessPattern.getFinalPattern(), MemberAccess.FINAL, enumDescriptor, visitor);
+ writeModifierEnumValue(
+ accessPattern.getSyntheticPattern(), MemberAccess.SYNTHETIC, enumDescriptor, visitor);
+
+ typeSpecificSettings.accept(visitor);
+ });
+ }
+}
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 19e72a5..690bae6 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,7 +3,6 @@
// 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;
@@ -43,35 +42,4 @@
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/AnnotationConstants.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java
index fa6d13a..77643cd 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java
@@ -15,6 +15,23 @@
* annotations which overlap in name with the actual semantic AST types.
*/
public final class AnnotationConstants {
+ public static final class ExtractedAnnotations {
+ public static final String DESCRIPTOR =
+ "Lcom/android/tools/r8/keepanno/annotations/ExtractedKeepAnnotations;";
+ public static final String value = "value";
+ }
+
+ public static final class ExtractedAnnotation {
+ public static final String DESCRIPTOR =
+ "Lcom/android/tools/r8/keepanno/annotations/ExtractedKeepAnnotation;";
+ public static final String version = "version";
+ public static final String context = "context";
+ public static final String keepAnnotationGroup = "keep-annotation";
+ public static final String edge = "edge";
+ public static final String checkRemoved = "checkRemoved";
+ public static final String checkOptimizedOut = "checkOptimizedOut";
+ }
+
public static final class Edge {
public static final String DESCRIPTOR = "Lcom/android/tools/r8/keepanno/annotations/KeepEdge;";
public static final String description = "description";
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 13d4df3..5c7cf96 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,8 +4,6 @@
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;
@@ -40,21 +38,6 @@
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();
@@ -62,31 +45,6 @@
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 b0045f5..28ff0b1 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,7 +3,6 @@
// 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;
@@ -89,13 +88,6 @@
.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 c7d6d84..c59fe13 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,7 +3,6 @@
// 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;
@@ -37,11 +36,19 @@
setKind(KeepCheckKind.REMOVED);
}
- // 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()));
+ // 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()));
return this;
}
@@ -124,12 +131,7 @@
@Override
public String toString() {
- return toProtoString();
- }
-
- @Override
- public String toProtoString() {
- return buildCheckProto().toString();
+ return "KeepCheck{kind=" + kind + ", item=" + itemReference + "}";
}
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 4ccfad3..8d27307 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,10 +24,9 @@
}
public ClassItemPattern.Builder buildClassProto() {
- ClassItemPattern.Builder builder = ClassItemPattern.newBuilder();
- KeepSpecUtils.buildAnnotatedByProto(annotatedByPattern, builder::setAnnotatedBy);
- instanceOfPattern.buildProto(builder::setInstanceOf);
- return builder.setClassName(classNamePattern.buildProto());
+ // TODO(b/343389186): Add instance-of.
+ // TODO(b/343389186): Add annotated-by.
+ return ClassItemPattern.newBuilder().setClassName(classNamePattern.buildProto());
}
public static class Builder {
@@ -44,14 +43,9 @@
if (protoItem.hasClassName()) {
setClassNamePattern(KeepQualifiedClassNamePattern.fromProto(protoItem.getClassName()));
}
- assert annotatedByPattern.isAbsent();
- if (protoItem.hasAnnotatedBy()) {
- setAnnotatedByPattern(KeepSpecUtils.annotatedByFromProto(protoItem.getAnnotatedBy()));
- }
- assert instanceOfPattern.isAny();
- if (protoItem.hasInstanceOf()) {
- setInstanceOfPattern(KeepInstanceOfPattern.fromProto(protoItem.getInstanceOf()));
- }
+
+ // TODO(b/343389186): Add instance-of.
+ // TODO(b/343389186): Add annotated-by.
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 7e619d9..96c0f4d 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,9 +3,6 @@
// 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.
*
@@ -20,25 +17,12 @@
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 2fdc4c3..1322746 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,8 +3,6 @@
// 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;
@@ -13,30 +11,19 @@
/**
* Set of consequences of a keep edge.
*
- * <p>The consequences are "targets" described by item references along with "keep options" which
+ * <p>The consequences are "targets" described by item patterns 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 f33e14e..2ae5f93 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,67 +5,10 @@
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();
@@ -144,11 +87,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.SHRINKING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_LOOKUP;
- }
}
public static Name name() {
@@ -175,11 +113,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OBFUSCATING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_NAME;
- }
}
public static VisibilityRelax visibilityRelax() {
@@ -206,11 +139,6 @@
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() {
@@ -238,11 +166,6 @@
// 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() {
@@ -269,11 +192,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_NEVER_INLINE;
- }
}
public static ClassInstantiate classInstantiate() {
@@ -305,11 +223,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_CLASS_INSTANTIATE;
- }
}
public static ClassOpenHierarchy classOpenHierarchy() {
@@ -341,11 +254,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_CLASS_OPEN_HIERARCHY;
- }
}
public static MethodInvoke methodInvoke() {
@@ -377,11 +285,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_METHOD_INVOKE;
- }
}
public static MethodReplace methodReplace() {
@@ -413,11 +316,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_METHOD_REPLACE;
- }
}
public static FieldGet fieldGet() {
@@ -449,11 +347,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_FIELD_GET;
- }
}
public static FieldSet fieldSet() {
@@ -485,11 +378,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_FIELD_SET;
- }
}
public static FieldReplace fieldReplace() {
@@ -521,11 +409,6 @@
public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
builder.add(KeepOption.OPTIMIZING);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_FIELD_REPLACE;
- }
}
public static GenericSignature genericSignature() {
@@ -557,11 +440,6 @@
public void addRequiredKeepAttributes(Set<KeepAttribute> attributes) {
attributes.add(KeepAttribute.GENERIC_SIGNATURES);
}
-
- @Override
- public ConstraintElement buildElementProto() {
- return ConstraintElement.CONSTRAINT_GENERIC_SIGNATURE;
- }
}
public static Annotation annotationsAll() {
@@ -618,16 +496,6 @@
}
@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 01c8844..6c55e6c 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,14 +6,11 @@
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;
@@ -44,27 +41,6 @@
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;
@@ -173,15 +149,6 @@
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 {
@@ -198,11 +165,6 @@
KeepConstraint.fieldSet());
@Override
- public boolean isDefault() {
- return true;
- }
-
- @Override
Set<KeepConstraint> getConstraints() {
return constraints;
}
@@ -222,13 +184,6 @@
// 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 {
@@ -263,15 +218,6 @@
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 {
@@ -283,15 +229,6 @@
}
@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;
}
@@ -325,8 +262,4 @@
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 a2cc7de..12d1d31 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,8 +50,6 @@
throw new RuntimeException();
}
- public abstract String toProtoString();
-
public final Declaration.Builder buildDeclarationProto() {
Declaration.Builder builder = Declaration.newBuilder();
return apply(
@@ -59,13 +57,13 @@
check -> builder.setCheck(check.buildCheckProto()));
}
- public static KeepDeclaration fromDeclarationProto(
+ public static KeepDeclaration fromProto(
KeepSpecProtos.Declaration declaration, KeepSpecVersion version) {
if (declaration.hasEdge()) {
- return KeepEdge.fromEdgeProto(declaration.getEdge(), version);
+ return KeepEdge.builder().applyProto(declaration.getEdge(), version).build();
}
if (declaration.hasCheck()) {
- return KeepCheck.fromCheckProto(declaration.getCheck(), version);
+ return KeepCheck.builder().applyProto(declaration.getCheck(), version).build();
}
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 ff8e507..3060010 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,14 +147,9 @@
private Builder() {}
- 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));
+ public Builder applyProto(Edge edge, KeepSpecVersion version) {
+ // TODO(b/343389186): implement this.
+ KeepEdgeMetaInfo.builder().applyProto(edge.getMetaInfo(), version).build();
return this;
}
@@ -262,24 +257,17 @@
@Override
public String toString() {
- return toProtoString();
- }
-
- @Override
- public String toProtoString() {
- return buildEdgeProto().toString();
- }
-
- public static KeepEdge fromEdgeProto(Edge proto, KeepSpecVersion version) {
- return KeepEdge.builder().applyProto(proto, version).build();
+ return "KeepEdge{metainfo="
+ + getMetaInfo()
+ + ", preconditions="
+ + preconditions
+ + ", consequences="
+ + consequences
+ + '}';
}
public Edge.Builder buildEdgeProto() {
- 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;
+ Edge.newBuilder().setMetaInfo(getMetaInfo().buildProto());
+ throw new Unimplemented();
}
}
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 b9bf204..55c15c2 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,9 +5,7 @@
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 {
@@ -43,10 +41,6 @@
this.transientPattern = transientPattern;
}
- public static KeepFieldAccessPattern fromFieldProto(MemberAccessField proto) {
- return builder().applyFieldProto(proto).build();
- }
-
@Override
public String toString() {
if (isAny()) {
@@ -70,17 +64,6 @@
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();
@@ -123,20 +106,5 @@
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 d6ec06d..f863c2e 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,6 +4,7 @@
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 {
@@ -30,31 +31,6 @@
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(
@@ -172,17 +148,7 @@
+ '}';
}
- public static KeepFieldPattern fromFieldMemberProto(MemberPatternField proto) {
- return builder().applyProto(proto).build();
- }
-
public MemberPatternField.Builder buildFieldProto() {
- MemberPatternField.Builder builder =
- MemberPatternField.newBuilder()
- .setName(namePattern.asStringPattern().buildProto())
- .setFieldType(typePattern.asType().buildProto());
- accessPattern.buildFieldProto(builder::setAccess);
- KeepSpecUtils.buildAnnotatedByProto(annotatedByPattern, builder::setAnnotatedBy);
- return builder;
+ throw new Unimplemented();
}
}
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 114ada8..79e2f43 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,9 +3,6 @@
// 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 {
@@ -13,20 +10,6 @@
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();
@@ -34,18 +17,6 @@
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 487ddc8..8b18105 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,11 +5,7 @@
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 {
@@ -87,28 +83,6 @@
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
@@ -211,32 +185,5 @@
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 67bbcd2..5c784bc 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,6 +5,7 @@
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;
@@ -20,22 +21,9 @@
}
public static class Builder {
- private OptionalPattern<KeepQualifiedClassNamePattern> annotatedByPattern =
- OptionalPattern.absent();
+ private OptionalPattern<KeepQualifiedClassNamePattern> annotatedByPattern;
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;
@@ -106,15 +94,8 @@
+ '}';
}
- 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();
+ public MemberPatternGeneral.Builder buildGeneralProto() {
+ throw new Unimplemented();
}
}
@@ -175,7 +156,7 @@
public MemberPattern.Builder buildProto() {
MemberPattern.Builder builder = MemberPattern.newBuilder();
match(
- general -> builder.setGeneralMember(((Some) general).buildGeneralMemberProto()),
+ general -> builder.setGeneralMember(((Some) general).buildGeneralProto()),
field -> builder.setFieldMember(field.buildFieldProto()),
method -> builder.setMethodMember(method.buildMethodProto()));
return builder;
@@ -183,13 +164,15 @@
public static KeepMemberPattern fromMemberProto(MemberPattern memberPattern) {
if (memberPattern.hasGeneralMember()) {
- return Some.fromGeneralMemberProto(memberPattern.getGeneralMember());
+ // return KeepMemberPattern.memberBuilder().applyProto(memberPattern.getGeneralMember());
+ throw new Unimplemented();
}
if (memberPattern.hasFieldMember()) {
- return KeepFieldPattern.fromFieldMemberProto(memberPattern.getFieldMember());
+ // return KeepFieldPattern.builder().applyProto(memberPattern.getFieldMember());
+ throw new Unimplemented();
}
if (memberPattern.hasMethodMember()) {
- return KeepMethodPattern.fromMethodMemberProto(memberPattern.getMethodMember());
+ return KeepMethodPattern.fromMethodProto(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 5b3a1bd..c8f83b2 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,9 +5,7 @@
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 {
@@ -55,24 +53,6 @@
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()) {
@@ -143,33 +123,6 @@
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 11f5cea..504bba8 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,16 +34,17 @@
return this;
}
- public Builder applyProto(MemberPatternMethod proto) {
+ public Builder applyProto(MemberPatternMethod methodMember) {
assert namePattern.isAny();
- if (proto.hasName()) {
+ if (methodMember.hasName()) {
setNamePattern(
- KeepMethodNamePattern.fromStringPattern(KeepStringPattern.fromProto(proto.getName())));
+ KeepMethodNamePattern.fromStringPattern(
+ KeepStringPattern.fromProto(methodMember.getName())));
}
assert returnTypePattern.isAny();
- if (proto.hasReturnType()) {
- MethodReturnTypePattern returnType = proto.getReturnType();
+ if (methodMember.hasReturnType()) {
+ MethodReturnTypePattern returnType = methodMember.getReturnType();
if (returnType.hasVoidType()) {
setReturnTypeVoid();
} else if (returnType.hasSomeType()) {
@@ -54,8 +55,8 @@
}
assert parametersPattern.isAny();
- if (proto.hasParameterTypes()) {
- MethodParameterTypesPattern parameterTypes = proto.getParameterTypes();
+ if (methodMember.hasParameterTypes()) {
+ MethodParameterTypesPattern parameterTypes = methodMember.getParameterTypes();
KeepMethodParametersPattern.Builder parametersBuilder =
KeepMethodParametersPattern.builder();
for (TypePattern typePattern : parameterTypes.getTypesList()) {
@@ -64,15 +65,8 @@
setParametersPattern(parametersBuilder.build());
}
- assert accessPattern.isAny();
- if (proto.hasAccess()) {
- setAccessPattern(KeepMethodAccessPattern.fromMethodProto(proto.getAccess()));
- }
-
- assert annotatedByPattern.isAbsent();
- if (proto.hasAnnotatedBy()) {
- setAnnotatedByPattern(KeepSpecUtils.annotatedByFromProto(proto.getAnnotatedBy()));
- }
+ // TODO(b/343389186): Add annotated-by.
+ // TODO(b/343389186): Add access.
return this;
}
@@ -223,7 +217,7 @@
+ '}';
}
- public static KeepMemberPattern fromMethodMemberProto(MemberPatternMethod methodMember) {
+ public static KeepMemberPattern fromMethodProto(MemberPatternMethod methodMember) {
return builder().applyProto(methodMember).build();
}
@@ -235,8 +229,8 @@
if (!parametersPattern.isAny()) {
builder.setParameterTypes(parametersPattern.buildProto());
}
- accessPattern.buildMethodProto(builder::setAccess);
- KeepSpecUtils.buildAnnotatedByProto(annotatedByPattern, builder::setAnnotatedBy);
+ // TODO(b/343389186): Add annotated-by.
+ // TODO(b/343389186): Add access.
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 3483ff7..16d9ef2 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 = KeepPackagePattern.any();
+ private KeepPackagePattern pattern;
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 2cdf7d9..246b20c 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,18 +3,12 @@
// 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 {
@@ -23,14 +17,6 @@
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 94445bb..4b1fcf7 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,8 +50,7 @@
}
public ClassNamePattern.Builder buildProto() {
- ClassNamePattern.Builder builder = ClassNamePattern.newBuilder();
- return builder
+ return ClassNamePattern.newBuilder()
.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 5a76764..11584aa 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,10 +4,7 @@
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 java.util.function.Consumer;
public final class KeepSpecUtils {
@@ -16,49 +13,4 @@
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 1a8321b..0d7dc03 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,22 +3,10 @@
// 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;
@@ -26,16 +14,6 @@
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 15cfef7..a123e61 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,6 +4,7 @@
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;
@@ -57,6 +58,21 @@
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,
@@ -265,25 +281,6 @@
}
}
- 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(
@@ -294,14 +291,7 @@
array -> builder.setArray(array.buildProto()),
clazz -> builder.setClazz(clazz.buildProto()),
instanceOf -> {
- 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);
- }
+ throw new Unimplemented();
});
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 1afe19e..77ce8ad 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,9 +3,6 @@
// 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 {
@@ -72,12 +69,4 @@
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 fd52a93..451b137 100644
--- a/src/keepanno/proto/keepspec.proto
+++ b/src/keepanno/proto/keepspec.proto
@@ -83,9 +83,7 @@
message Edge {
MetaInfo meta_info = 1;
- Bindings bindings = 2;
- repeated Condition preconditions = 3;
- repeated Target consequences = 4;
+ // TODO(b/343389186): Add content.
}
message Bindings {
@@ -101,55 +99,6 @@
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;
@@ -159,13 +108,8 @@
message ClassItemPattern {
optional ClassNamePattern class_name = 1;
- optional InstanceOfPattern instance_of = 2;
- optional AnnotatedByPattern annotated_by = 3;
-}
-
-message InstanceOfPattern {
- optional bool inclusive = 1;
- optional ClassNamePattern class_name = 2;
+ // TODO(b/343389186): Add instance-of.
+ // TODO(b/343389186): Add annotated-by.
}
message ClassNamePattern {
@@ -207,10 +151,6 @@
optional StringPattern name = 1;
}
-message AnnotatedByPattern {
- optional ClassNamePattern name = 1;
-}
-
message MemberItemPattern {
BindingReference class_reference = 1;
optional MemberPattern member_pattern = 2;
@@ -224,64 +164,20 @@
}
}
-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 {
- optional MemberAccessGeneral access = 1;
- optional AnnotatedByPattern annotated_by = 2;
+ // TODO(b/343389186): Add content.
}
message MemberPatternField {
- optional MemberAccessField access = 1;
- optional AnnotatedByPattern annotated_by = 2;
- optional StringPattern name = 3;
- optional TypePattern field_type = 4;
+ // TODO(b/343389186): Add content.
}
message MemberPatternMethod {
- optional MemberAccessMethod access = 1;
- optional AnnotatedByPattern annotated_by = 2;
- optional StringPattern name = 3;
- optional MethodReturnTypePattern return_type = 4;
- optional MethodParameterTypesPattern parameter_types = 5;
+ 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.
}
message MethodReturnTypePattern {
@@ -306,7 +202,7 @@
TypePatternPrimitive primitive = 1;
TypePatternArray array = 2;
ClassNamePattern clazz = 3;
- InstanceOfPattern instance_of = 4;
+ // TODO(b/343389186): Add instance-of.
}
}
@@ -327,3 +223,4 @@
optional uint32 dimensions = 1;
optional TypePattern base_type = 2;
}
+
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 3bd0ac5..36f1ff3 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -139,6 +139,8 @@
private boolean enableMissingLibraryApiModeling = false;
private boolean enableExperimentalKeepAnnotations =
System.getProperty("com.android.tools.r8.enableKeepAnnotations") != null;
+ private boolean enableExperimentalVersionedKeepEdgeAnnotations =
+ System.getProperty("com.android.tools.r8.enableVersionedKeepEdgeAnnotations") != null;
public boolean enableStartupLayoutOptimization = true;
private SemanticVersion fakeCompilerVersion = null;
private AndroidResourceProvider androidResourceProvider = null;
@@ -520,6 +522,12 @@
return self();
}
+ @Deprecated
+ public Builder setEnableExperimentalExtractedKeepAnnotations(boolean enable) {
+ this.enableExperimentalVersionedKeepEdgeAnnotations = enable;
+ return self();
+ }
+
@Override
protected InternalProgramOutputPathConsumer createProgramOutputConsumer(
Path path,
@@ -837,15 +845,20 @@
}
private void extractKeepAnnotationRules(ProguardConfigurationParser parser) {
- if (!enableExperimentalKeepAnnotations) {
+ if (!enableExperimentalKeepAnnotations && !enableExperimentalVersionedKeepEdgeAnnotations) {
return;
}
+ assert enableExperimentalKeepAnnotations != enableExperimentalVersionedKeepEdgeAnnotations;
try {
for (ProgramResourceProvider provider : getAppBuilder().getProgramResourceProviders()) {
for (ProgramResource resource : provider.getProgramResources()) {
if (resource.getKind() == Kind.CF) {
- List<KeepDeclaration> declarations =
- KeepEdgeReader.readKeepEdges(resource.getBytes());
+ List<KeepDeclaration> declarations;
+ if (!enableExperimentalKeepAnnotations) {
+ declarations = KeepEdgeReader.readExtractedKeepEdges(resource.getBytes());
+ } else {
+ declarations = KeepEdgeReader.readKeepEdges(resource.getBytes());
+ }
if (!declarations.isEmpty()) {
KeepRuleExtractor extractor =
new KeepRuleExtractor(
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index a515a46..57b427e 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -458,7 +458,7 @@
public boolean shouldReadKeepAnnotations() {
// Only compilers configured to read annotations should process them.
// In all other instances (D8, relocater, etc.) they must be pass-through.
- return application.options.testing.enableEmbeddedKeepAnnotations
+ return application.options.testing.isKeepAnnotationsEnabled()
&& classKind == ClassKind.PROGRAM;
}
@@ -470,6 +470,7 @@
desc,
visible,
application.options.testing.enableEmbeddedKeepAnnotations,
+ application.options.testing.enableExtractedKeepAnnotations,
className,
ClassParsingContext.fromName(className).annotation(desc),
application::addKeepDeclaration);
@@ -683,6 +684,7 @@
desc,
visible,
parent.application.options.testing.enableEmbeddedKeepAnnotations,
+ parent.application.options.testing.enableExtractedKeepAnnotations,
className,
name,
fieldTypeDescriptor,
@@ -850,6 +852,7 @@
desc,
visible,
parent.application.options.testing.enableEmbeddedKeepAnnotations,
+ parent.application.options.testing.enableExtractedKeepAnnotations,
className,
name,
methodDescriptor,
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index d4fd18a..abee4a2 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -154,7 +154,6 @@
import com.android.tools.r8.shaking.RootSetUtils.RootSetBuilder;
import com.android.tools.r8.shaking.ScopedDexMethodSet.AddMethodIfMoreVisibleResult;
import com.android.tools.r8.shaking.rules.ApplicableRulesEvaluator;
-import com.android.tools.r8.shaking.rules.KeepAnnotationFakeProguardRule;
import com.android.tools.r8.shaking.rules.KeepAnnotationMatcher;
import com.android.tools.r8.synthesis.SyntheticItems.SynthesizingContextOracle;
import com.android.tools.r8.utils.Action;
@@ -679,6 +678,9 @@
}
private void addEffectivelyLiveOriginalMethod(ProgramMethod method) {
+ if (!options.testing.isKeepAnnotationsEnabled()) {
+ return;
+ }
if (method.getDefinition().hasPendingInlineFrame()) {
traceMethodPosition(method.getDefinition().getPendingInlineFrameAsPosition(), method);
} else if (!method.getDefinition().isD8R8Synthesized()) {
@@ -1054,8 +1056,7 @@
if (forceProguardCompatibility) {
Joiner joiner = KeepMethodInfo.newEmptyJoiner();
for (ProguardKeepRuleBase rule : rules) {
- if (!(rule instanceof KeepAnnotationFakeProguardRule)
- && !rule.getType().equals(ProguardKeepRuleType.KEEP_CLASS_MEMBERS)) {
+ if (!rule.getType().equals(ProguardKeepRuleType.KEEP_CLASS_MEMBERS)) {
joiner.addRule(rule);
}
}
@@ -1676,6 +1677,10 @@
}
void traceMethodPosition(com.android.tools.r8.ir.code.Position position, ProgramMethod context) {
+ if (!options.testing.isKeepAnnotationsEnabled()) {
+ // Currently inlining is only intended for the evaluation of keep annotation edges.
+ return;
+ }
while (position.hasCallerPosition()) {
// Any inner position should not be non-synthetic user methods.
assert !position.isD8R8Synthesized();
@@ -3306,6 +3311,9 @@
}
private void addEffectivelyLiveOriginalField(ProgramField field) {
+ if (!options.testing.isKeepAnnotationsEnabled()) {
+ return;
+ }
if (field.getDefinition().hasOriginalFieldWitness()) {
markEffectivelyLiveOriginalReference(field.getDefinition().getOriginalFieldWitness());
} else {
@@ -3552,6 +3560,7 @@
}
public boolean isOriginalReferenceEffectivelyLive(DexReference reference) {
+ assert options.testing.isKeepAnnotationsEnabled();
// The effectively-live original set contains types, fields and methods witnessed by
// instructions, such as method inlining positions.
return effectivelyLiveOriginalReferences.contains(reference);
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 72f1164..1dfda01 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepSpecificationSource.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepSpecificationSource.java
@@ -45,8 +45,7 @@
throw new ResourceException(getOrigin(), "Unknown keepspec version " + spec.getVersion());
}
for (Declaration declaration : spec.getDeclarationsList()) {
- KeepDeclaration parsedDeclaration =
- KeepDeclaration.fromDeclarationProto(declaration, version);
+ KeepDeclaration parsedDeclaration = KeepDeclaration.fromProto(declaration, version);
if (parsedDeclaration == null) {
throw new ResourceException(getOrigin(), "Unable to parse declaration " + declaration);
} else {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardKeepRuleType.java b/src/main/java/com/android/tools/r8/shaking/ProguardKeepRuleType.java
index 44e836e..2018cbf 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardKeepRuleType.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardKeepRuleType.java
@@ -9,8 +9,7 @@
KEEP,
KEEP_CLASS_MEMBERS,
KEEP_CLASSES_WITH_MEMBERS,
- CONDITIONAL,
- KEEPSPEC;
+ CONDITIONAL;
@Override
public String toString() {
@@ -23,8 +22,6 @@
return "keepclasseswithmembers";
case CONDITIONAL:
return "if";
- case KEEPSPEC:
- return "keepspec";
default:
throw new Unreachable("Unknown ProguardKeepRuleType.");
}
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index e0170ef..3d5324b 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -282,8 +282,6 @@
break;
case CONDITIONAL:
throw new Unreachable("-if rule will be evaluated separately, not here.");
- case KEEPSPEC:
- throw new Unreachable("keepspec rules are evaluated separately, not here.");
}
return;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationFakeProguardRule.java b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationFakeProguardRule.java
index 73b5fee..2e28fcb 100644
--- a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationFakeProguardRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationFakeProguardRule.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.position.Position;
import com.android.tools.r8.shaking.ProguardClassType;
import com.android.tools.r8.shaking.ProguardKeepRuleBase;
-import com.android.tools.r8.shaking.ProguardKeepRuleType;
// TODO(b/323816623): Make an interface to use in the keep-reason tracking.
public class KeepAnnotationFakeProguardRule extends ProguardKeepRuleBase {
@@ -29,7 +28,7 @@
null,
false,
null,
- ProguardKeepRuleType.KEEPSPEC,
+ null,
null);
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 14efa1d..ef49e3a 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -2217,10 +2217,14 @@
public static class TestingOptions {
- public boolean enableEmbeddedKeepAnnotations =
- System.getProperty("com.android.tools.r8.enableKeepAnnotations") != null;
+ public boolean enableExtractedKeepAnnotations = false;
+ public boolean enableEmbeddedKeepAnnotations = false;
public boolean reverseClassSortingForDeterminism = false;
+ public boolean isKeepAnnotationsEnabled() {
+ return enableExtractedKeepAnnotations || enableEmbeddedKeepAnnotations;
+ }
+
public boolean enableNumberUnboxer = false;
public boolean printNumberUnboxed = false;
public boolean roundtripThroughLir = false;
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 8b21c8d..f39df8f 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java
@@ -4,6 +4,7 @@
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;
@@ -17,14 +18,18 @@
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.KeepRuleExtractor;
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;
@@ -33,6 +38,8 @@
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 {
@@ -190,8 +197,23 @@
.enableExperimentalKeepAnnotations()
.setMinApi(parameters());
+ if (isExtractRules()) {
+ // TODO(b/323816623): Replace the internal rule extraction by extraction in this builder.
+ builder.getBuilder().setEnableExperimentalKeepAnnotations(true);
+ builder.getBuilder().setEnableExperimentalExtractedKeepAnnotations(false);
+ return;
+ }
+
// TODO(b/323816623): Replace the testing flag by the API call.
- builder.addOptionsModification(o -> o.testing.enableEmbeddedKeepAnnotations = isDirect());
+ // This enables native interpretation of all keep annotations.
+ builder.addOptionsModification(
+ o -> {
+ o.testing.enableExtractedKeepAnnotations = isNormalizeEdges();
+ o.testing.enableEmbeddedKeepAnnotations = !isNormalizeEdges();
+ });
+ // This disables all reading of annotations in the command reader.
+ builder.getBuilder().setEnableExperimentalKeepAnnotations(false);
+ builder.getBuilder().setEnableExperimentalExtractedKeepAnnotations(false);
}
private boolean isExtractRules() {
@@ -202,10 +224,6 @@
return config == KeepAnnoConfig.R8_NORMALIZED;
}
- private boolean isDirect() {
- return config == KeepAnnoConfig.R8_DIRECT;
- }
-
@Override
public KeepAnnoTestBuilder allowUnusedProguardConfigurationRules() {
if (isExtractRules()) {
@@ -262,29 +280,54 @@
private void extractAndAdd(byte[] classFileData) {
builder.addProgramClassFileData(classFileData);
- if (isExtractRules()) {
- List<KeepDeclaration> declarations = KeepEdgeReader.readKeepEdges(classFileData);
- if (!declarations.isEmpty()) {
- KeepRuleExtractor extractor = new KeepRuleExtractor(builder::addKeepRules);
- declarations.forEach(extractor::extract);
- }
- return;
- }
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) {
- keepSpecBuilder.addDeclarations(declaration.buildDeclarationProto());
+ try {
+ keepSpecBuilder.addDeclarations(declaration.buildDeclarationProto());
+ } catch (Unimplemented e) {
+ legacyExtract.add(declaration);
+ }
}
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";
+ }
+ });
}
- return;
}
- assert isDirect();
}
@Override
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 1293e79..85809df 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepInclusiveInstanceOfTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepInclusiveInstanceOfTest.java
@@ -3,9 +3,6 @@
// 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;
@@ -37,14 +34,11 @@
.addKeepMainRule(TestClass.class)
.setExcludedOuterClass(getClass())
.run(TestClass.class)
- .assertSuccessWithOutput(EXPECTED)
- .applyIf(
- parameters.isShrinker(),
- r -> r.inspect(inspector -> assertThat(inspector.clazz(Unrelated.class), isAbsent())));
+ .assertSuccessWithOutput(EXPECTED);
}
public List<Class<?>> getInputClasses() {
- return ImmutableList.of(TestClass.class, Base.class, Sub.class, A.class, Unrelated.class);
+ return ImmutableList.of(TestClass.class, Base.class, Sub.class, A.class);
}
static class Base {
@@ -59,12 +53,6 @@
}
}
- 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 f85dcd7..8c96fe1 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java
@@ -41,6 +41,19 @@
.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));
diff --git a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
index e6d0cf9..e92c4d8 100644
--- a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
+++ b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
@@ -80,6 +80,8 @@
static final ClassReference USED_BY_NATIVE = annoClass("UsedByNative");
static final ClassReference CHECK_REMOVED = annoClass("CheckRemoved");
static final ClassReference CHECK_OPTIMIZED_OUT = annoClass("CheckOptimizedOut");
+ static final ClassReference EXTRACTED_KEEP_ANNOTATIONS = annoClass("ExtractedKeepAnnotations");
+ static final ClassReference EXTRACTED_KEEP_ANNOTATION = annoClass("ExtractedKeepAnnotation");
static final ClassReference KEEP_EDGE = annoClass("KeepEdge");
static final ClassReference KEEP_BINDING = annoClass("KeepBinding");
static final ClassReference KEEP_TARGET = annoClass("KeepTarget");
@@ -1678,6 +1680,7 @@
withIndent(
() -> {
// Root annotations.
+ generateExtractedKeepAnnotationsConstants();
generateKeepEdgeConstants();
generateKeepForApiConstants();
generateUsesReflectionConstants();
@@ -1716,6 +1719,49 @@
println("public static final String DESCRIPTOR = " + quote(desc) + ";");
}
+ private void generateExtractedKeepAnnotationsConstants() {
+ println("public static final class ExtractedAnnotations {");
+ withIndent(
+ () -> {
+ generateAnnotationConstants(EXTRACTED_KEEP_ANNOTATIONS);
+ new GroupMember("value")
+ .setDocTitle("Extracted normalized keep edges.")
+ .requiredArrayValue(KEEP_EDGE)
+ .generateConstants(this);
+ });
+ println("}");
+ println();
+ println("public static final class ExtractedAnnotation {");
+ withIndent(
+ () -> {
+ generateAnnotationConstants(EXTRACTED_KEEP_ANNOTATION);
+ new GroupMember("version")
+ .setDocTitle("Extraction version used to generate this keep annotation.")
+ .requiredStringValue()
+ .generateConstants(this);
+ new GroupMember("context")
+ .setDocTitle("Extraction context from which this keep annotation is generated.")
+ .requiredStringValue()
+ .generateConstants(this);
+ new Group("keep-annotation")
+ .addMember(
+ new GroupMember("edge")
+ .setDocTitle("Extracted normalized keep edge.")
+ .requiredValue(KEEP_EDGE))
+ .addMember(
+ new GroupMember("checkRemoved")
+ .setDocTitle("Extracted check removed.")
+ .defaultBooleanValue(false))
+ .addMember(
+ new GroupMember("checkOptimizedOut")
+ .setDocTitle("Extracted check optimized out.")
+ .defaultBooleanValue(false))
+ .generateConstants(this);
+ });
+ println("}");
+ println();
+ }
+
List<Group> getKeepEdgeGroups() {
return ImmutableList.of(
createDescriptionGroup(),
diff --git a/src/test/testbase/java/com/android/tools/r8/keepanno/KeepAnnoTestUtils.java b/src/test/testbase/java/com/android/tools/r8/keepanno/KeepAnnoTestUtils.java
index 8fba6b2..93384e8 100644
--- a/src/test/testbase/java/com/android/tools/r8/keepanno/KeepAnnoTestUtils.java
+++ b/src/test/testbase/java/com/android/tools/r8/keepanno/KeepAnnoTestUtils.java
@@ -11,10 +11,12 @@
import com.android.tools.r8.ProguardVersion;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.keepanno.asm.KeepEdgeReader;
+import com.android.tools.r8.keepanno.asm.KeepEdgeWriter.AnnotationVisitorInterface;
import com.android.tools.r8.keepanno.ast.KeepDeclaration;
import com.android.tools.r8.keepanno.keeprules.KeepRuleExtractor;
import com.android.tools.r8.keepanno.keeprules.KeepRuleExtractorOptions;
import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import java.io.IOException;
import java.nio.file.Files;
@@ -24,6 +26,7 @@
import java.util.List;
import java.util.stream.Stream;
import org.junit.rules.TemporaryFolder;
+import org.objectweb.asm.AnnotationVisitor;
public class KeepAnnoTestUtils {
@@ -98,4 +101,47 @@
}
return rules;
}
+
+ public static AnnotationVisitorInterface wrap(AnnotationVisitor visitor) {
+ return visitor == null ? null : new WrappedAnnotationVisitor(visitor);
+ }
+
+ private static class WrappedAnnotationVisitor implements AnnotationVisitorInterface {
+
+ private final AnnotationVisitor visitor;
+
+ private WrappedAnnotationVisitor(AnnotationVisitor visitor) {
+ this.visitor = visitor;
+ }
+
+ @Override
+ public int version() {
+ return InternalOptions.ASM_VERSION;
+ }
+
+ @Override
+ public void visit(String name, Object value) {
+ visitor.visit(name, value);
+ }
+
+ @Override
+ public void visitEnum(String name, String descriptor, String value) {
+ visitor.visitEnum(name, descriptor, value);
+ }
+
+ @Override
+ public AnnotationVisitorInterface visitAnnotation(String name, String descriptor) {
+ return wrap(visitor.visitAnnotation(name, descriptor));
+ }
+
+ @Override
+ public AnnotationVisitorInterface visitArray(String name) {
+ return wrap(visitor.visitArray(name));
+ }
+
+ @Override
+ public void visitEnd() {
+ visitor.visitEnd();
+ }
+ }
}