[KeepAnno] Add parsing context structure for error reporting
Bug: b/248408342
Change-Id: If845574089b98b9cfa0201f9dd0692af523cdc0a
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/ClassNamePattern.java b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/ClassNamePattern.java
index 1d40ae5..a175b3d 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/ClassNamePattern.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/ClassNamePattern.java
@@ -25,7 +25,7 @@
/**
* Exact simple name of the class or interface.
*
- * <p>For example, the simple name {@code com.example.MyClass} is {@code MyClass}.
+ * <p>For example, the simple name of {@code com.example.MyClass} is {@code MyClass}.
*
* <p>The default matches any simple name.
*/
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/AnnotationVisitorBase.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/AnnotationVisitorBase.java
index e15d4e7..777e99b 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/AnnotationVisitorBase.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/AnnotationVisitorBase.java
@@ -4,20 +4,17 @@
package com.android.tools.r8.keepanno.asm;
-import com.android.tools.r8.keepanno.ast.KeepEdgeException;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Type;
public abstract class AnnotationVisitorBase extends AnnotationVisitor {
- AnnotationVisitorBase() {
+ private final ParsingContext parsingContext;
+
+ AnnotationVisitorBase(ParsingContext parsingContext) {
super(KeepEdgeReader.ASM_VERSION);
- }
-
- public abstract String getAnnotationName();
-
- private String errorMessagePrefix() {
- return "@" + getAnnotationName() + ": ";
+ this.parsingContext = parsingContext;
}
private String getTypeName(String descriptor) {
@@ -26,34 +23,31 @@
@Override
public void visit(String name, Object value) {
- throw new KeepEdgeException(
- "Unexpected value in " + errorMessagePrefix() + name + " = " + value);
+ throw parsingContext.error("Unexpected value for property " + name + " with value " + value);
}
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
- throw new KeepEdgeException(
- "Unexpected annotation in "
- + errorMessagePrefix()
+ throw parsingContext.error(
+ "Unexpected annotation for property "
+ name
- + " for annotation: "
+ + " of annotation type "
+ getTypeName(descriptor));
}
@Override
public void visitEnum(String name, String descriptor, String value) {
- throw new KeepEdgeException(
- "Unexpected enum in "
- + errorMessagePrefix()
+ throw parsingContext.error(
+ "Unexpected enum for property "
+ name
- + " for enum: "
+ + " of enum type "
+ getTypeName(descriptor)
- + " with value: "
+ + " with value "
+ value);
}
@Override
public AnnotationVisitor visitArray(String name) {
- throw new KeepEdgeException("Unexpected array in " + errorMessagePrefix() + name);
+ throw parsingContext.error("Unexpected array for property " + name);
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassNameParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassNameParser.java
index c1e5655..d6c41ac 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassNameParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassNameParser.java
@@ -11,6 +11,8 @@
import com.android.tools.r8.keepanno.ast.KeepPackagePattern;
import com.android.tools.r8.keepanno.ast.KeepQualifiedClassNamePattern;
import com.android.tools.r8.keepanno.ast.KeepUnqualfiedClassNamePattern;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
+import com.android.tools.r8.keepanno.ast.ParsingContext.AnnotationParsingContext;
import com.google.common.collect.ImmutableList;
import java.util.function.Consumer;
import org.objectweb.asm.AnnotationVisitor;
@@ -18,6 +20,10 @@
public class ClassNameParser
extends PropertyParserBase<KeepQualifiedClassNamePattern, ClassNameProperty, ClassNameParser> {
+ public ClassNameParser(ParsingContext parsingContext) {
+ super(parsingContext);
+ }
+
public enum ClassNameProperty {
PATTERN
}
@@ -36,13 +42,16 @@
switch (property) {
case PATTERN:
{
+ AnnotationParsingContext parsingContext =
+ new AnnotationParsingContext(getParsingContext(), descriptor);
PackageNameParser packageParser =
- new PackageNameParser()
+ new PackageNameParser(parsingContext)
.setProperty(PackageNameProperty.NAME, ClassNamePattern.packageName);
ClassSimpleNameParser nameParser =
- new ClassSimpleNameParser()
+ new ClassSimpleNameParser(parsingContext)
.setProperty(ClassSimpleNameProperty.NAME, ClassNamePattern.simpleName);
return new ParserVisitor(
+ parsingContext,
descriptor,
ImmutableList.of(packageParser, nameParser),
() ->
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassSimpleNameParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassSimpleNameParser.java
index 17296bc..d349898 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassSimpleNameParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassSimpleNameParser.java
@@ -6,12 +6,17 @@
import com.android.tools.r8.keepanno.asm.ClassSimpleNameParser.ClassSimpleNameProperty;
import com.android.tools.r8.keepanno.ast.KeepUnqualfiedClassNamePattern;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
import java.util.function.Consumer;
public class ClassSimpleNameParser
extends PropertyParserBase<
KeepUnqualfiedClassNamePattern, ClassSimpleNameProperty, ClassSimpleNameParser> {
+ public ClassSimpleNameParser(ParsingContext parsingContext) {
+ super(parsingContext);
+ }
+
public enum ClassSimpleNameProperty {
NAME
}
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 4513464..00729cb 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
@@ -20,7 +20,7 @@
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.AnnotationConstants.UsedByReflection;
-import com.android.tools.r8.keepanno.ast.AnnotationConstants.UsesReflection;
+import com.android.tools.r8.keepanno.ast.KeepAnnotationParserException;
import com.android.tools.r8.keepanno.ast.KeepBindingReference;
import com.android.tools.r8.keepanno.ast.KeepBindings;
import com.android.tools.r8.keepanno.ast.KeepBindings.KeepBindingSymbol;
@@ -32,7 +32,6 @@
import com.android.tools.r8.keepanno.ast.KeepConsequences;
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;
@@ -42,6 +41,7 @@
import com.android.tools.r8.keepanno.ast.KeepItemPattern;
import com.android.tools.r8.keepanno.ast.KeepItemReference;
import com.android.tools.r8.keepanno.ast.KeepMemberAccessPattern;
+import com.android.tools.r8.keepanno.ast.KeepMemberAccessPattern.BuilderBase;
import com.android.tools.r8.keepanno.ast.KeepMemberItemPattern;
import com.android.tools.r8.keepanno.ast.KeepMemberPattern;
import com.android.tools.r8.keepanno.ast.KeepMethodAccessPattern;
@@ -57,6 +57,11 @@
import com.android.tools.r8.keepanno.ast.KeepTarget;
import com.android.tools.r8.keepanno.ast.KeepTypePattern;
import com.android.tools.r8.keepanno.ast.KeepUnqualfiedClassNamePattern;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
+import com.android.tools.r8.keepanno.ast.ParsingContext.AnnotationParsingContext;
+import com.android.tools.r8.keepanno.ast.ParsingContext.ClassParsingContext;
+import com.android.tools.r8.keepanno.ast.ParsingContext.FieldParsingContext;
+import com.android.tools.r8.keepanno.ast.ParsingContext.MethodParsingContext;
import com.android.tools.r8.keepanno.utils.Unimplemented;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -193,6 +198,7 @@
private static class KeepEdgeClassVisitor extends ClassVisitor {
private final Parent<KeepDeclaration> parent;
private String className;
+ private ClassParsingContext parsingContext;
KeepEdgeClassVisitor(Parent<KeepDeclaration> parent) {
super(ASM_VERSION);
@@ -212,7 +218,12 @@
String superName,
String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
- this.className = binaryNameToTypeName(name);
+ className = binaryNameToTypeName(name);
+ parsingContext = new ClassParsingContext(className);
+ }
+
+ private AnnotationParsingContext annotationParsingContext(String descriptor) {
+ return new AnnotationParsingContext(parsingContext, descriptor);
}
@Override
@@ -222,48 +233,66 @@
return null;
}
if (descriptor.equals(Edge.DESCRIPTOR)) {
- return new KeepEdgeVisitor(parent::accept, this::setContext);
+ return new KeepEdgeVisitor(
+ annotationParsingContext(descriptor), parent::accept, this::setContext);
}
if (descriptor.equals(AnnotationConstants.UsesReflection.DESCRIPTOR)) {
KeepClassItemPattern classItem =
KeepClassItemPattern.builder()
.setClassNamePattern(KeepQualifiedClassNamePattern.exact(className))
.build();
- return new UsesReflectionVisitor(parent::accept, this::setContext, classItem);
+ return new UsesReflectionVisitor(
+ annotationParsingContext(descriptor), parent::accept, this::setContext, classItem);
}
if (descriptor.equals(AnnotationConstants.ForApi.DESCRIPTOR)) {
- return new ForApiClassVisitor(parent::accept, this::setContext, className);
+ return new ForApiClassVisitor(
+ annotationParsingContext(descriptor), parent::accept, this::setContext, className);
}
if (descriptor.equals(AnnotationConstants.UsedByReflection.DESCRIPTOR)
|| descriptor.equals(AnnotationConstants.UsedByNative.DESCRIPTOR)) {
return new UsedByReflectionClassVisitor(
- descriptor, parent::accept, this::setContext, className);
+ annotationParsingContext(descriptor),
+ descriptor,
+ parent::accept,
+ this::setContext,
+ className);
}
if (descriptor.equals(AnnotationConstants.CheckRemoved.DESCRIPTOR)) {
return new CheckRemovedClassVisitor(
- descriptor, parent::accept, this::setContext, className, KeepCheckKind.REMOVED);
+ annotationParsingContext(descriptor),
+ descriptor,
+ parent::accept,
+ this::setContext,
+ className,
+ KeepCheckKind.REMOVED);
}
if (descriptor.equals(AnnotationConstants.CheckOptimizedOut.DESCRIPTOR)) {
return new CheckRemovedClassVisitor(
- descriptor, parent::accept, this::setContext, className, KeepCheckKind.OPTIMIZED_OUT);
+ annotationParsingContext(descriptor),
+ descriptor,
+ parent::accept,
+ this::setContext,
+ className,
+ KeepCheckKind.OPTIMIZED_OUT);
}
return null;
}
private void setContext(KeepEdgeMetaInfo.Builder builder) {
- builder.setContextFromClassDescriptor(KeepEdgeReaderUtils.javaTypeToDescriptor(className));
+ builder.setContextFromClassDescriptor(
+ KeepEdgeReaderUtils.getDescriptorFromJavaType(className));
}
@Override
public MethodVisitor visitMethod(
int access, String name, String descriptor, String signature, String[] exceptions) {
- return new KeepEdgeMethodVisitor(parent::accept, className, name, descriptor);
+ return new KeepEdgeMethodVisitor(parsingContext, parent::accept, className, name, descriptor);
}
@Override
public FieldVisitor visitField(
int access, String name, String descriptor, String signature, Object value) {
- return new KeepEdgeFieldVisitor(parent::accept, className, name, descriptor);
+ return new KeepEdgeFieldVisitor(parsingContext, parent::accept, className, name, descriptor);
}
}
@@ -272,8 +301,10 @@
private final String className;
private final String methodName;
private final String methodDescriptor;
+ private final MethodParsingContext parsingContext;
KeepEdgeMethodVisitor(
+ ClassParsingContext classParsingContext,
Parent<KeepDeclaration> parent,
String className,
String methodName,
@@ -283,6 +314,8 @@
this.className = className;
this.methodName = methodName;
this.methodDescriptor = methodDescriptor;
+ this.parsingContext =
+ new MethodParsingContext(classParsingContext, methodName, methodDescriptor);
}
private KeepMemberItemPattern createMethodItemContext() {
@@ -308,6 +341,10 @@
.build();
}
+ private AnnotationParsingContext annotationParsingContext(String descriptor) {
+ return new AnnotationParsingContext(parsingContext, descriptor);
+ }
+
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
// Skip any visible annotations as @KeepEdge is not runtime visible.
@@ -315,22 +352,35 @@
return null;
}
if (descriptor.equals(Edge.DESCRIPTOR)) {
- return new KeepEdgeVisitor(parent::accept, this::setContext);
+ return new KeepEdgeVisitor(
+ annotationParsingContext(descriptor), parent::accept, this::setContext);
}
if (descriptor.equals(AnnotationConstants.UsesReflection.DESCRIPTOR)) {
return new UsesReflectionVisitor(
- parent::accept, this::setContext, createMethodItemContext());
+ annotationParsingContext(descriptor),
+ parent::accept,
+ this::setContext,
+ createMethodItemContext());
}
if (descriptor.equals(AnnotationConstants.ForApi.DESCRIPTOR)) {
- return new ForApiMemberVisitor(parent::accept, this::setContext, createMethodItemContext());
+ return new ForApiMemberVisitor(
+ annotationParsingContext(descriptor),
+ parent::accept,
+ this::setContext,
+ createMethodItemContext());
}
if (descriptor.equals(AnnotationConstants.UsedByReflection.DESCRIPTOR)
|| descriptor.equals(AnnotationConstants.UsedByNative.DESCRIPTOR)) {
return new UsedByReflectionMemberVisitor(
- descriptor, parent::accept, this::setContext, createMethodItemContext());
+ annotationParsingContext(descriptor),
+ descriptor,
+ parent::accept,
+ this::setContext,
+ createMethodItemContext());
}
if (descriptor.equals(AnnotationConstants.CheckRemoved.DESCRIPTOR)) {
return new CheckRemovedMemberVisitor(
+ annotationParsingContext(descriptor),
descriptor,
parent::accept,
this::setContext,
@@ -339,6 +389,7 @@
}
if (descriptor.equals(AnnotationConstants.CheckOptimizedOut.DESCRIPTOR)) {
return new CheckRemovedMemberVisitor(
+ annotationParsingContext(descriptor),
descriptor,
parent::accept,
this::setContext,
@@ -350,7 +401,7 @@
private void setContext(KeepEdgeMetaInfo.Builder builder) {
builder.setContextFromMethodDescriptor(
- KeepEdgeReaderUtils.javaTypeToDescriptor(className), methodName, methodDescriptor);
+ KeepEdgeReaderUtils.getDescriptorFromJavaType(className), methodName, methodDescriptor);
}
}
@@ -359,14 +410,25 @@
private final String className;
private final String fieldName;
private final String fieldDescriptor;
+ private final FieldParsingContext parsingContext;
KeepEdgeFieldVisitor(
- Parent<KeepEdge> parent, String className, String fieldName, String fieldDescriptor) {
+ ClassParsingContext classParsingContext,
+ Parent<KeepEdge> parent,
+ String className,
+ String fieldName,
+ String fieldDescriptor) {
super(ASM_VERSION);
this.parent = parent;
this.className = className;
this.fieldName = fieldName;
this.fieldDescriptor = fieldDescriptor;
+ this.parsingContext =
+ new FieldParsingContext(classParsingContext, fieldName, fieldDescriptor);
+ }
+
+ private AnnotationParsingContext annotationParsingContext(String descriptor) {
+ return new AnnotationParsingContext(parsingContext, descriptor);
}
private KeepMemberItemPattern createMemberItemContext() {
@@ -384,7 +446,7 @@
private void setContext(KeepEdgeMetaInfo.Builder builder) {
builder.setContextFromFieldDescriptor(
- KeepEdgeReaderUtils.javaTypeToDescriptor(className), fieldName, fieldDescriptor);
+ KeepEdgeReaderUtils.getDescriptorFromJavaType(className), fieldName, fieldDescriptor);
}
@Override
@@ -394,18 +456,30 @@
return null;
}
if (descriptor.equals(Edge.DESCRIPTOR)) {
- return new KeepEdgeVisitor(parent, this::setContext);
+ return new KeepEdgeVisitor(annotationParsingContext(descriptor), parent, this::setContext);
}
if (descriptor.equals(AnnotationConstants.UsesReflection.DESCRIPTOR)) {
- return new UsesReflectionVisitor(parent, this::setContext, createMemberItemContext());
+ return new UsesReflectionVisitor(
+ annotationParsingContext(descriptor),
+ parent,
+ this::setContext,
+ createMemberItemContext());
}
if (descriptor.equals(AnnotationConstants.ForApi.DESCRIPTOR)) {
- return new ForApiMemberVisitor(parent, this::setContext, createMemberItemContext());
+ return new ForApiMemberVisitor(
+ annotationParsingContext(descriptor),
+ parent,
+ this::setContext,
+ createMemberItemContext());
}
if (descriptor.equals(AnnotationConstants.UsedByReflection.DESCRIPTOR)
|| descriptor.equals(AnnotationConstants.UsedByNative.DESCRIPTOR)) {
return new UsedByReflectionMemberVisitor(
- descriptor, parent, this::setContext, createMemberItemContext());
+ annotationParsingContext(descriptor),
+ descriptor,
+ parent,
+ this::setContext,
+ createMemberItemContext());
}
return null;
}
@@ -444,22 +518,24 @@
}
private static class KeepEdgeVisitor extends AnnotationVisitorBase {
+
+ private final AnnotationParsingContext parsingContext;
private final Parent<KeepEdge> parent;
private final KeepEdge.Builder builder = KeepEdge.builder();
private final KeepEdgeMetaInfo.Builder metaInfoBuilder = KeepEdgeMetaInfo.builder();
private final UserBindingsHelper bindingsHelper = new UserBindingsHelper();
- KeepEdgeVisitor(Parent<KeepEdge> parent, Consumer<KeepEdgeMetaInfo.Builder> addContext) {
+ KeepEdgeVisitor(
+ AnnotationParsingContext parsingContext,
+ Parent<KeepEdge> parent,
+ Consumer<KeepEdgeMetaInfo.Builder> addContext) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.parent = parent;
addContext.accept(metaInfoBuilder);
}
@Override
- public String getAnnotationName() {
- return "KeepEdge";
- }
-
- @Override
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
@@ -471,15 +547,15 @@
@Override
public AnnotationVisitor visitArray(String name) {
if (name.equals(Edge.bindings)) {
- return new KeepBindingsVisitor(getAnnotationName(), bindingsHelper);
+ return new KeepBindingsVisitor(parsingContext, bindingsHelper);
}
if (name.equals(Edge.preconditions)) {
return new KeepPreconditionsVisitor(
- getAnnotationName(), builder::setPreconditions, bindingsHelper);
+ parsingContext, builder::setPreconditions, bindingsHelper);
}
if (name.equals(Edge.consequences)) {
return new KeepConsequencesVisitor(
- getAnnotationName(), builder::setConsequences, bindingsHelper);
+ parsingContext, builder::setConsequences, bindingsHelper);
}
return super.visitArray(name);
}
@@ -499,6 +575,8 @@
* properties are encountered.
*/
private static class ForApiClassVisitor extends KeepItemVisitorBase {
+
+ private final AnnotationParsingContext parsingContext;
private final String className;
private final Parent<KeepEdge> parent;
private final KeepEdge.Builder builder = KeepEdge.builder();
@@ -507,7 +585,12 @@
private final UserBindingsHelper bindingsHelper = new UserBindingsHelper();
ForApiClassVisitor(
- Parent<KeepEdge> parent, Consumer<KeepEdgeMetaInfo.Builder> addContext, String className) {
+ AnnotationParsingContext parsingContext,
+ Parent<KeepEdge> parent,
+ Consumer<KeepEdgeMetaInfo.Builder> addContext,
+ String className) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.className = className;
this.parent = parent;
addContext.accept(metaInfoBuilder);
@@ -523,11 +606,6 @@
}
@Override
- public String getAnnotationName() {
- return ForApi.SIMPLE_NAME;
- }
-
- @Override
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
@@ -540,7 +618,7 @@
public AnnotationVisitor visitArray(String name) {
if (name.equals(ForApi.additionalTargets)) {
return new KeepConsequencesVisitor(
- getAnnotationName(),
+ parsingContext,
additionalConsequences -> {
additionalConsequences.forEachTarget(consequences::addTarget);
},
@@ -561,7 +639,7 @@
Collection<KeepItemReference> items = getItemsWithoutBinding();
for (KeepItemReference item : items) {
if (item.isBindingReference()) {
- throw new KeepEdgeException("@KeepForApi cannot reference bindings");
+ throw parsingContext.error("cannot reference bindings");
}
KeepClassItemPattern classItemPattern = item.asClassItemPattern();
if (classItemPattern == null) {
@@ -571,13 +649,13 @@
String descriptor = KeepEdgeReaderUtils.getDescriptorFromClassTypeName(className);
String itemDescriptor = classItemPattern.getClassNamePattern().getExactDescriptor();
if (!descriptor.equals(itemDescriptor)) {
- throw new KeepEdgeException("@KeepForApi must reference its class context " + className);
+ throw parsingContext.error("must reference its class context " + className);
}
if (classItemPattern.isMemberItemPattern() && items.size() == 1) {
- throw new KeepEdgeException("@KeepForApi kind must include its class");
+ throw parsingContext.error("kind must include its class");
}
if (!classItemPattern.getInstanceOfPattern().isAny()) {
- throw new KeepEdgeException("@KeepForApi cannot define an 'extends' pattern.");
+ throw parsingContext.error("cannot define an 'extends' pattern.");
}
consequences.addTarget(KeepTarget.builder().setItemReference(item).build());
}
@@ -596,6 +674,8 @@
* <p>When used on a member context the annotation does not allow member related patterns.
*/
private static class ForApiMemberVisitor extends AnnotationVisitorBase {
+
+ private final AnnotationParsingContext parsingContext;
private final Parent<KeepEdge> parent;
private final KeepEdge.Builder builder = KeepEdge.builder();
private final KeepEdgeMetaInfo.Builder metaInfoBuilder = KeepEdgeMetaInfo.builder();
@@ -603,9 +683,12 @@
private final KeepConsequences.Builder consequences = KeepConsequences.builder();
ForApiMemberVisitor(
+ AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
KeepMemberItemPattern context) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.parent = parent;
addContext.accept(metaInfoBuilder);
// Create a binding for the context such that the class and member are shared.
@@ -625,11 +708,6 @@
}
@Override
- public String getAnnotationName() {
- return ForApi.SIMPLE_NAME;
- }
-
- @Override
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
@@ -642,7 +720,7 @@
public AnnotationVisitor visitArray(String name) {
if (name.equals(ForApi.additionalTargets)) {
return new KeepConsequencesVisitor(
- getAnnotationName(),
+ parsingContext,
additionalConsequences -> {
additionalConsequences.forEachTarget(consequences::addTarget);
},
@@ -670,6 +748,8 @@
* properties are encountered.
*/
private static class UsedByReflectionClassVisitor extends KeepItemVisitorBase {
+
+ private final AnnotationParsingContext parsingContext;
private final String annotationDescriptor;
private final String className;
private final Parent<KeepEdge> parent;
@@ -680,17 +760,20 @@
private final OptionsDeclaration optionsDeclaration;
UsedByReflectionClassVisitor(
+ AnnotationParsingContext parsingContext,
String annotationDescriptor,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
String className) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.annotationDescriptor = annotationDescriptor;
this.className = className;
this.parent = parent;
addContext.accept(metaInfoBuilder);
// The class context/holder is the annotated class.
visit(Item.className, className);
- optionsDeclaration = new OptionsDeclaration(getAnnotationName());
+ optionsDeclaration = new OptionsDeclaration(parsingContext);
}
@Override
@@ -699,12 +782,6 @@
}
@Override
- public String getAnnotationName() {
- int sep = annotationDescriptor.lastIndexOf('/');
- return annotationDescriptor.substring(sep + 1, annotationDescriptor.length() - 1);
- }
-
- @Override
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
@@ -717,11 +794,11 @@
public AnnotationVisitor visitArray(String name) {
if (name.equals(Edge.preconditions)) {
return new KeepPreconditionsVisitor(
- getAnnotationName(), builder::setPreconditions, bindingsHelper);
+ parsingContext, builder::setPreconditions, bindingsHelper);
}
if (name.equals(UsedByReflection.additionalTargets)) {
return new KeepConsequencesVisitor(
- getAnnotationName(),
+ parsingContext,
additionalConsequences -> {
additionalConsequences.forEachTarget(consequences::addTarget);
},
@@ -745,7 +822,7 @@
for (KeepItemReference item : items) {
if (item.isBindingReference()) {
// TODO(b/248408342): The edge can have preconditions so it should support bindings!
- throw new KeepEdgeException("@" + getAnnotationName() + " cannot reference bindings");
+ throw parsingContext.error("cannot reference bindings");
}
KeepItemPattern itemPattern = item.asItemPattern();
KeepClassItemPattern holderPattern =
@@ -755,15 +832,13 @@
String descriptor = KeepEdgeReaderUtils.getDescriptorFromClassTypeName(className);
String itemDescriptor = holderPattern.getClassNamePattern().getExactDescriptor();
if (!descriptor.equals(itemDescriptor)) {
- throw new KeepEdgeException(
- "@" + getAnnotationName() + " must reference its class context " + className);
+ throw parsingContext.error("must reference its class context " + className);
}
if (itemPattern.isMemberItemPattern() && items.size() == 1) {
- throw new KeepEdgeException("@" + getAnnotationName() + " kind must include its class");
+ throw parsingContext.error("kind must include its class");
}
if (!holderPattern.getInstanceOfPattern().isAny()) {
- throw new KeepEdgeException(
- "@" + getAnnotationName() + " cannot define an 'extends' pattern.");
+ throw parsingContext.error("cannot define an 'extends' pattern.");
}
consequences.addTarget(
KeepTarget.builder()
@@ -786,6 +861,8 @@
* <p>When used on a member context the annotation does not allow member related patterns.
*/
private static class UsedByReflectionMemberVisitor extends AnnotationVisitorBase {
+
+ private final AnnotationParsingContext parsingContext;
private final String annotationDescriptor;
private final Parent<KeepEdge> parent;
private final KeepItemPattern context;
@@ -797,21 +874,18 @@
private final OptionsDeclaration optionsDeclaration;
UsedByReflectionMemberVisitor(
+ AnnotationParsingContext parsingContext,
String annotationDescriptor,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
KeepItemPattern context) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.annotationDescriptor = annotationDescriptor;
this.parent = parent;
this.context = context;
addContext.accept(metaInfoBuilder);
- optionsDeclaration = new OptionsDeclaration(getAnnotationName());
- }
-
- @Override
- public String getAnnotationName() {
- int sep = annotationDescriptor.lastIndexOf('/');
- return annotationDescriptor.substring(sep + 1, annotationDescriptor.length() - 1);
+ optionsDeclaration = new OptionsDeclaration(parsingContext);
}
@Override
@@ -840,11 +914,11 @@
public AnnotationVisitor visitArray(String name) {
if (name.equals(Edge.preconditions)) {
return new KeepPreconditionsVisitor(
- getAnnotationName(), builder::setPreconditions, bindingsHelper);
+ parsingContext, builder::setPreconditions, bindingsHelper);
}
if (name.equals(UsedByReflection.additionalTargets)) {
return new KeepConsequencesVisitor(
- getAnnotationName(),
+ parsingContext,
additionalConsequences -> {
additionalConsequences.forEachTarget(consequences::addTarget);
},
@@ -860,7 +934,7 @@
@Override
public void visitEnd() {
if (kind.isOnlyClass()) {
- throw new KeepEdgeException("@" + getAnnotationName() + " kind must include its member");
+ throw parsingContext.error("kind must include its member");
}
assert context.isMemberItemPattern();
KeepMemberItemPattern memberContext = context.asMemberItemPattern();
@@ -884,18 +958,20 @@
private void validateConsistentKind(KeepMemberPattern memberPattern) {
if (memberPattern.isGeneralMember()) {
- throw new KeepEdgeException("Unexpected general pattern for context.");
+ throw parsingContext.error("Unexpected general pattern for context.");
}
if (memberPattern.isMethod() && !kind.includesMethod()) {
- throw new KeepEdgeException("Kind " + kind + " cannot be use when annotating a method");
+ throw parsingContext.error("Kind " + kind + " cannot be use when annotating a method");
}
if (memberPattern.isField() && !kind.includesField()) {
- throw new KeepEdgeException("Kind " + kind + " cannot be use when annotating a field");
+ throw parsingContext.error("Kind " + kind + " cannot be use when annotating a field");
}
}
}
private static class UsesReflectionVisitor extends AnnotationVisitorBase {
+
+ private final AnnotationParsingContext parsingContext;
private final Parent<KeepEdge> parent;
private final KeepEdge.Builder builder = KeepEdge.builder();
private final KeepPreconditions.Builder preconditions = KeepPreconditions.builder();
@@ -903,20 +979,18 @@
private final UserBindingsHelper bindingsHelper = new UserBindingsHelper();
UsesReflectionVisitor(
+ AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
KeepItemPattern context) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.parent = parent;
preconditions.addCondition(KeepCondition.builder().setItemPattern(context).build());
addContext.accept(metaInfoBuilder);
}
@Override
- public String getAnnotationName() {
- return UsesReflection.SIMPLE_NAME;
- }
-
- @Override
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
@@ -929,11 +1003,11 @@
public AnnotationVisitor visitArray(String name) {
if (name.equals(AnnotationConstants.UsesReflection.value)) {
return new KeepConsequencesVisitor(
- getAnnotationName(), builder::setConsequences, bindingsHelper);
+ parsingContext, builder::setConsequences, bindingsHelper);
}
if (name.equals(AnnotationConstants.UsesReflection.additionalPreconditions)) {
return new KeepPreconditionsVisitor(
- getAnnotationName(),
+ parsingContext,
additionalPreconditions -> {
additionalPreconditions.forEach(preconditions::addCondition);
},
@@ -954,52 +1028,44 @@
}
private static class KeepBindingsVisitor extends AnnotationVisitorBase {
- private final String annotationName;
+ private final AnnotationParsingContext parsingContext;
private final UserBindingsHelper helper;
- public KeepBindingsVisitor(String annotationName, UserBindingsHelper helper) {
- this.annotationName = annotationName;
+ public KeepBindingsVisitor(AnnotationParsingContext parsingContext, UserBindingsHelper helper) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.helper = helper;
}
@Override
- public String getAnnotationName() {
- return annotationName;
- }
-
- @Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
if (descriptor.equals(AnnotationConstants.Binding.DESCRIPTOR)) {
- return new KeepBindingVisitor(helper);
+ return new KeepBindingVisitor(parsingContext, helper);
}
return super.visitAnnotation(name, descriptor);
}
}
private static class KeepPreconditionsVisitor extends AnnotationVisitorBase {
- private final String annotationName;
+ private final AnnotationParsingContext parsingContext;
private final Parent<KeepPreconditions> parent;
private final KeepPreconditions.Builder builder = KeepPreconditions.builder();
private final UserBindingsHelper bindingsHelper;
public KeepPreconditionsVisitor(
- String annotationName,
+ AnnotationParsingContext parsingContext,
Parent<KeepPreconditions> parent,
UserBindingsHelper bindingsHelper) {
- this.annotationName = annotationName;
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.parent = parent;
this.bindingsHelper = bindingsHelper;
}
@Override
- public String getAnnotationName() {
- return annotationName;
- }
-
- @Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
if (descriptor.equals(Condition.DESCRIPTOR)) {
- return new KeepConditionVisitor(builder::addCondition, bindingsHelper);
+ return new KeepConditionVisitor(parsingContext, builder::addCondition, bindingsHelper);
}
return super.visitAnnotation(name, descriptor);
}
@@ -1011,27 +1077,25 @@
}
private static class KeepConsequencesVisitor extends AnnotationVisitorBase {
- private final String annotationName;
+ private final AnnotationParsingContext parsingContext;
private final Parent<KeepConsequences> parent;
private final KeepConsequences.Builder builder = KeepConsequences.builder();
private final UserBindingsHelper bindingsHelper;
public KeepConsequencesVisitor(
- String annotationName, Parent<KeepConsequences> parent, UserBindingsHelper bindingsHelper) {
- this.annotationName = annotationName;
+ AnnotationParsingContext parsingContext,
+ Parent<KeepConsequences> parent,
+ UserBindingsHelper bindingsHelper) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.parent = parent;
this.bindingsHelper = bindingsHelper;
}
@Override
- public String getAnnotationName() {
- return annotationName;
- }
-
- @Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
if (descriptor.equals(Target.DESCRIPTOR)) {
- return KeepTargetVisitor.create(builder::addTarget, bindingsHelper);
+ return KeepTargetVisitor.create(parsingContext, builder::addTarget, bindingsHelper);
}
return super.visitAnnotation(name, descriptor);
}
@@ -1045,6 +1109,7 @@
/** Parsing of @CheckRemoved and @CheckOptimizedOut on a class context. */
private static class CheckRemovedClassVisitor extends AnnotationVisitorBase {
+ private final AnnotationParsingContext parsingContext;
private final String annotationDescriptor;
private final Parent<KeepCheck> parent;
private final KeepEdgeMetaInfo.Builder metaInfoBuilder = KeepEdgeMetaInfo.builder();
@@ -1052,11 +1117,14 @@
private final KeepCheckKind kind;
public CheckRemovedClassVisitor(
+ AnnotationParsingContext parsingContext,
String annotationDescriptor,
Parent<KeepCheck> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
String className,
KeepCheckKind kind) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.annotationDescriptor = annotationDescriptor;
this.parent = parent;
this.className = className;
@@ -1065,12 +1133,6 @@
}
@Override
- public String getAnnotationName() {
- int sep = annotationDescriptor.lastIndexOf('/');
- return annotationDescriptor.substring(sep + 1, annotationDescriptor.length() - 1);
- }
-
- @Override
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
@@ -1083,15 +1145,10 @@
public void visitEnd() {
CheckRemovedClassVisitor superVisitor = this;
KeepItemVisitorBase itemVisitor =
- new KeepItemVisitorBase() {
+ new KeepItemVisitorBase(parsingContext) {
@Override
public UserBindingsHelper getBindingsHelper() {
- throw new KeepEdgeException("Bindings not supported in @" + getAnnotationName());
- }
-
- @Override
- public String getAnnotationName() {
- return superVisitor.getAnnotationName();
+ throw parsingContext.error("bindings not supported");
}
};
itemVisitor.visit(Item.className, className);
@@ -1115,11 +1172,13 @@
private final KeepCheckKind kind;
CheckRemovedMemberVisitor(
+ AnnotationParsingContext parsingContext,
String annotationDescriptor,
Parent<KeepDeclaration> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
KeepItemPattern context,
KeepCheckKind kind) {
+ super(parsingContext);
this.annotationDescriptor = annotationDescriptor;
this.parent = parent;
this.context = context;
@@ -1128,12 +1187,6 @@
}
@Override
- public String getAnnotationName() {
- int sep = annotationDescriptor.lastIndexOf('/');
- return annotationDescriptor.substring(sep + 1, annotationDescriptor.length() - 1);
- }
-
- @Override
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
@@ -1203,10 +1256,19 @@
}
private abstract static class SingleDeclaration<T> extends Declaration<T> {
+ private final ParsingContext parsingContext;
private String declarationName = null;
private T declarationValue = null;
private AnnotationVisitor declarationVisitor = null;
+ private SingleDeclaration(ParsingContext parsingContext) {
+ this.parsingContext = parsingContext;
+ }
+
+ public ParsingContext getParsingContext() {
+ return parsingContext;
+ }
+
abstract T getDefaultValue();
abstract T parse(String name, Object value);
@@ -1229,7 +1291,8 @@
}
private void error(String name) {
- throw new KeepEdgeException(
+ throw new KeepAnnotationParserException(
+ parsingContext,
"Multiple declarations defining "
+ kind()
+ ": '"
@@ -1290,6 +1353,10 @@
private static class ClassNameDeclaration
extends SingleDeclaration<KeepQualifiedClassNamePattern> {
+ private ClassNameDeclaration(ParsingContext parsingContext) {
+ super(parsingContext);
+ }
+
@Override
String kind() {
return "class-name";
@@ -1315,7 +1382,8 @@
AnnotationVisitor parseAnnotation(
String name, String descriptor, Consumer<KeepQualifiedClassNamePattern> setValue) {
if (name.equals(Item.classNamePattern) && descriptor.equals(ClassNamePattern.DESCRIPTOR)) {
- return new ClassNamePatternVisitor(setValue);
+ return new ClassNamePatternVisitor(
+ new AnnotationParsingContext(getParsingContext(), descriptor), setValue);
}
return super.parseAnnotation(name, descriptor, setValue);
}
@@ -1323,6 +1391,10 @@
private static class InstanceOfDeclaration extends SingleDeclaration<KeepInstanceOfPattern> {
+ private InstanceOfDeclaration(ParsingContext parsingContext) {
+ super(parsingContext);
+ }
+
@Override
String kind() {
return "instance-of";
@@ -1375,16 +1447,21 @@
private static class ClassDeclaration extends Declaration<KeepClassItemReference> {
+ private final ParsingContext parsingContext;
private final Supplier<UserBindingsHelper> getBindingsHelper;
private KeepClassItemReference boundClassItemReference = null;
- private final ClassNameDeclaration classNameDeclaration = new ClassNameDeclaration();
- private final InstanceOfDeclaration instanceOfDeclaration = new InstanceOfDeclaration();
- private final List<Declaration<?>> declarations =
- ImmutableList.of(classNameDeclaration, instanceOfDeclaration);
+ private final ClassNameDeclaration classNameDeclaration;
+ private final InstanceOfDeclaration instanceOfDeclaration;
+ private final List<Declaration<?>> declarations;
- public ClassDeclaration(Supplier<UserBindingsHelper> getBindingsHelper) {
+ public ClassDeclaration(
+ ParsingContext parsingContext, Supplier<UserBindingsHelper> getBindingsHelper) {
+ this.parsingContext = parsingContext;
this.getBindingsHelper = getBindingsHelper;
+ classNameDeclaration = new ClassNameDeclaration(parsingContext);
+ instanceOfDeclaration = new InstanceOfDeclaration(parsingContext);
+ declarations = ImmutableList.of(classNameDeclaration, instanceOfDeclaration);
}
@Override
@@ -1402,7 +1479,7 @@
private void checkAllowedDefinitions() {
if (isBindingReferenceDefined() && classPatternsAreDefined()) {
- throw new KeepEdgeException(
+ throw parsingContext.error(
"Cannot reference a class binding and class patterns for a single class item");
}
}
@@ -1436,7 +1513,7 @@
public void setBindingReference(KeepClassItemReference bindingReference) {
if (isBindingReferenceDefined()) {
- throw new KeepEdgeException(
+ throw parsingContext.error(
"Cannot reference multiple class bindings for a single class item");
}
this.boundClassItemReference = bindingReference;
@@ -1456,13 +1533,12 @@
private static class MethodReturnTypeDeclaration
extends SingleDeclaration<KeepMethodReturnTypePattern> {
- private final Supplier<String> annotationName;
private final TypeParser typeParser;
- private MethodReturnTypeDeclaration(Supplier<String> annotationName) {
- this.annotationName = annotationName;
+ private MethodReturnTypeDeclaration(ParsingContext parsingContext) {
+ super(parsingContext);
typeParser =
- new TypeParser()
+ new TypeParser(parsingContext)
.setKind("return type")
.enableTypePattern(Item.methodReturnTypePattern)
.enableTypeName(Item.methodReturnType)
@@ -1506,18 +1582,19 @@
private static class MethodParametersDeclaration
extends SingleDeclaration<KeepMethodParametersPattern> {
- private final Supplier<String> annotationName;
+ private final ParsingContext parsingContext;
private KeepMethodParametersPattern pattern = null;
- public MethodParametersDeclaration(Supplier<String> annotationName) {
- this.annotationName = annotationName;
+ public MethodParametersDeclaration(ParsingContext parsingContext) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
}
private void setPattern(
KeepMethodParametersPattern pattern, Consumer<KeepMethodParametersPattern> setValue) {
assert setValue != null;
if (this.pattern != null) {
- throw new KeepEdgeException("Cannot declare multiple patterns for the parameter list");
+ throw parsingContext.error("Cannot declare multiple patterns for the parameter list");
}
setValue.accept(pattern);
this.pattern = pattern;
@@ -1542,7 +1619,7 @@
AnnotationVisitor parseArray(String name, Consumer<KeepMethodParametersPattern> setValue) {
if (name.equals(Item.methodParameters)) {
return new StringArrayVisitor(
- annotationName,
+ getParsingContext(),
params -> {
KeepMethodParametersPattern.Builder builder = KeepMethodParametersPattern.builder();
for (String param : params) {
@@ -1553,7 +1630,7 @@
}
if (name.equals(Item.methodParameterTypePatterns)) {
return new TypePatternsArrayVisitor(
- annotationName,
+ getParsingContext(),
params -> {
KeepMethodParametersPattern.Builder builder = KeepMethodParametersPattern.builder();
for (KeepTypePattern param : params) {
@@ -1567,7 +1644,8 @@
}
private static class MethodDeclaration extends Declaration<KeepMethodPattern> {
- private final Supplier<String> annotationName;
+
+ private final ParsingContext parsingContext;
private KeepMethodAccessPattern.Builder accessBuilder = null;
private KeepMethodPattern.Builder builder = null;
private final MethodReturnTypeDeclaration returnTypeDeclaration;
@@ -1575,10 +1653,10 @@
private final List<Declaration<?>> declarations;
- private MethodDeclaration(Supplier<String> annotationName) {
- this.annotationName = annotationName;
- returnTypeDeclaration = new MethodReturnTypeDeclaration(annotationName);
- parametersDeclaration = new MethodParametersDeclaration(annotationName);
+ private MethodDeclaration(ParsingContext parsingContext) {
+ this.parsingContext = parsingContext;
+ returnTypeDeclaration = new MethodReturnTypeDeclaration(parsingContext);
+ parametersDeclaration = new MethodParametersDeclaration(parsingContext);
declarations = ImmutableList.of(returnTypeDeclaration, parametersDeclaration);
}
@@ -1631,7 +1709,7 @@
AnnotationVisitor tryParseArray(String name) {
if (name.equals(Item.methodAccess)) {
accessBuilder = KeepMethodAccessPattern.builder();
- return new MethodAccessVisitor(annotationName, accessBuilder);
+ return new MethodAccessVisitor(parsingContext, accessBuilder);
}
return super.tryParseArray(name);
}
@@ -1639,13 +1717,12 @@
private static class FieldTypeDeclaration extends SingleDeclaration<KeepFieldTypePattern> {
- private final Supplier<String> annotationName;
private final TypeParser typeParser;
- private FieldTypeDeclaration(Supplier<String> annotationName) {
- this.annotationName = annotationName;
+ private FieldTypeDeclaration(ParsingContext parsingContext) {
+ super(parsingContext);
this.typeParser =
- new TypeParser()
+ new TypeParser(parsingContext)
.setKind("field type")
.enableTypePattern(Item.fieldTypePattern)
.enableTypeName(Item.fieldType)
@@ -1680,15 +1757,16 @@
}
private static class FieldDeclaration extends Declaration<KeepFieldPattern> {
- private final Supplier<String> annotationName;
+
+ private final ParsingContext parsingContext;
private final FieldTypeDeclaration typeDeclaration;
private KeepFieldAccessPattern.Builder accessBuilder = null;
private KeepFieldPattern.Builder builder = null;
private final List<Declaration<?>> declarations;
- public FieldDeclaration(Supplier<String> annotationName) {
- this.annotationName = annotationName;
- typeDeclaration = new FieldTypeDeclaration(annotationName);
+ public FieldDeclaration(ParsingContext parsingContext) {
+ this.parsingContext = parsingContext;
+ typeDeclaration = new FieldTypeDeclaration(parsingContext);
declarations = Collections.singletonList(typeDeclaration);
}
@@ -1738,23 +1816,24 @@
AnnotationVisitor tryParseArray(String name) {
if (name.equals(Item.fieldAccess)) {
accessBuilder = KeepFieldAccessPattern.builder();
- return new FieldAccessVisitor(annotationName, accessBuilder);
+ return new FieldAccessVisitor(parsingContext, accessBuilder);
}
return super.tryParseArray(name);
}
}
private static class MemberDeclaration extends Declaration<KeepMemberPattern> {
- private final Supplier<String> annotationName;
+
+ private final ParsingContext parsingContext;
private KeepMemberAccessPattern.Builder accessBuilder = null;
private final MethodDeclaration methodDeclaration;
private final FieldDeclaration fieldDeclaration;
private final List<Declaration<?>> declarations;
- MemberDeclaration(Supplier<String> annotationName) {
- this.annotationName = annotationName;
- methodDeclaration = new MethodDeclaration(annotationName);
- fieldDeclaration = new FieldDeclaration(annotationName);
+ MemberDeclaration(ParsingContext parsingContext) {
+ this.parsingContext = parsingContext;
+ methodDeclaration = new MethodDeclaration(parsingContext);
+ fieldDeclaration = new FieldDeclaration(parsingContext);
declarations = ImmutableList.of(methodDeclaration, fieldDeclaration);
}
@@ -1779,13 +1858,13 @@
KeepFieldPattern field = fieldDeclaration.getValue();
if (accessBuilder != null) {
if (method != null || field != null) {
- throw new KeepEdgeException(
+ throw parsingContext.error(
"Cannot define common member access as well as field or method pattern");
}
return KeepMemberPattern.memberBuilder().setAccessPattern(accessBuilder.build()).build();
}
if (method != null && field != null) {
- throw new KeepEdgeException("Cannot define both a field and a method pattern");
+ throw parsingContext.error("Cannot define both a field and a method pattern");
}
if (method != null) {
return method;
@@ -1800,37 +1879,42 @@
AnnotationVisitor tryParseArray(String name) {
if (name.equals(Item.memberAccess)) {
accessBuilder = KeepMemberAccessPattern.memberBuilder();
- return new MemberAccessVisitor(annotationName, accessBuilder);
+ return new MemberAccessVisitor(parsingContext, accessBuilder);
}
return super.tryParseArray(name);
}
}
private abstract static class KeepItemVisitorBase extends AnnotationVisitorBase {
+ private final ParsingContext parsingContext;
private String memberBindingReference = null;
private ItemKind kind = null;
- private final ClassDeclaration classDeclaration = new ClassDeclaration(this::getBindingsHelper);
+ private final ClassDeclaration classDeclaration;
private final MemberDeclaration memberDeclaration;
+
public abstract UserBindingsHelper getBindingsHelper();
// Constructed item available once visitEnd has been called.
private KeepItemReference itemReference = null;
- KeepItemVisitorBase() {
- memberDeclaration = new MemberDeclaration(this::getAnnotationName);
+ KeepItemVisitorBase(ParsingContext parsingContext) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
+ classDeclaration = new ClassDeclaration(parsingContext, this::getBindingsHelper);
+ memberDeclaration = new MemberDeclaration(parsingContext);
}
public Collection<KeepItemReference> getItemsWithoutBinding() {
if (itemReference == null) {
- throw new KeepEdgeException("Item reference not finalized. Missing call to visitEnd()");
+ throw parsingContext.error("Item reference not finalized. Missing call to visitEnd()");
}
if (itemReference.isBindingReference()) {
return Collections.singletonList(itemReference);
}
// Kind is only null if item is a "binding reference".
if (kind == null) {
- throw new KeepEdgeException("Unexpected state: unknown kind for an item pattern");
+ throw parsingContext.error("Unexpected state: unknown kind for an item pattern");
}
if (kind.includesClassAndMembers()) {
assert !itemReference.isBindingReference();
@@ -1856,14 +1940,14 @@
public Collection<KeepItemReference> getItemsWithBinding() {
if (itemReference == null) {
- throw new KeepEdgeException("Item reference not finalized. Missing call to visitEnd()");
+ throw parsingContext.error("Item reference not finalized. Missing call to visitEnd()");
}
if (itemReference.isBindingReference()) {
return Collections.singletonList(itemReference);
}
// Kind is only null if item is a "binding reference".
if (kind == null) {
- throw new KeepEdgeException("Unexpected state: unknown kind for an item pattern");
+ throw parsingContext.error("Unexpected state: unknown kind for an item pattern");
}
if (kind.includesClassAndMembers()) {
KeepItemPattern itemPattern = itemReference.asItemPattern();
@@ -1900,7 +1984,7 @@
public KeepItemReference getItemReference() {
if (itemReference == null) {
- throw new KeepEdgeException("Item reference not finalized. Missing call to visitEnd()");
+ throw parsingContext.error("Item reference not finalized. Missing call to visitEnd()");
}
return itemReference;
}
@@ -1967,7 +2051,7 @@
if (!classDeclaration.isDefault()
|| !memberDeclaration.getValue().isNone()
|| kind != null) {
- throw new KeepEdgeException(
+ throw parsingContext.error(
"Cannot define an item explicitly and via a member-binding reference");
}
KeepBindingSymbol symbol = getBindingsHelper().resolveUserBinding(memberBindingReference);
@@ -1989,7 +2073,7 @@
}
if (kind.isOnlyClass() && !memberPattern.isNone()) {
- throw new KeepEdgeException("Item pattern for members is incompatible with kind " + kind);
+ throw parsingContext.error("Item pattern for members is incompatible with kind " + kind);
}
// Refine the member pattern to be as precise as the specified kind.
@@ -2006,8 +2090,7 @@
memberPattern = KeepMethodPattern.allMethods();
} else {
assert memberPattern.isField();
- throw new KeepEdgeException(
- "Item pattern for fields is incompatible with kind " + kind);
+ throw parsingContext.error("Item pattern for fields is incompatible with kind " + kind);
}
}
@@ -2024,7 +2107,7 @@
memberPattern = KeepFieldPattern.allFields();
} else {
assert memberPattern.isMethod();
- throw new KeepEdgeException(
+ throw parsingContext.error(
"Item pattern for methods is incompatible with kind " + kind);
}
}
@@ -2050,10 +2133,13 @@
private static class KeepBindingVisitor extends KeepItemVisitorBase {
+ private final AnnotationParsingContext parsingContext;
private final UserBindingsHelper helper;
private String bindingName;
- public KeepBindingVisitor(UserBindingsHelper helper) {
+ public KeepBindingVisitor(AnnotationParsingContext parsingContext, UserBindingsHelper helper) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.helper = helper;
}
@@ -2063,11 +2149,6 @@
}
@Override
- public String getAnnotationName() {
- return Binding.SIMPLE_NAME;
- }
-
- @Override
public void visit(String name, Object value) {
if (name.equals(Binding.bindingName) && value instanceof String) {
bindingName = (String) value;
@@ -2083,7 +2164,7 @@
// The language currently disallows aliasing bindings, thus a binding cannot directly be
// defined by a reference to another binding.
if (item.isBindingReference()) {
- throw new KeepEdgeException(
+ throw parsingContext.error(
"Invalid binding reference to '"
+ item.asBindingReference()
+ "' in binding definition of '"
@@ -2095,21 +2176,15 @@
}
private static class StringArrayVisitor extends AnnotationVisitorBase {
- private final Supplier<String> annotationName;
private final Consumer<List<String>> fn;
private final List<String> strings = new ArrayList<>();
- public StringArrayVisitor(Supplier<String> annotationName, Consumer<List<String>> fn) {
- this.annotationName = annotationName;
+ public StringArrayVisitor(ParsingContext parsingContext, Consumer<List<String>> fn) {
+ super(parsingContext);
this.fn = fn;
}
@Override
- public String getAnnotationName() {
- return annotationName.get();
- }
-
- @Override
public void visit(String name, Object value) {
if (value instanceof String) {
strings.add((String) value);
@@ -2128,6 +2203,10 @@
private static class ClassSimpleNameDeclaration
extends SingleDeclaration<KeepUnqualfiedClassNamePattern> {
+ private ClassSimpleNameDeclaration(ParsingContext parsingContext) {
+ super(parsingContext);
+ }
+
@Override
String kind() {
return "class-simple-name";
@@ -2149,6 +2228,10 @@
private static class PackageDeclaration extends SingleDeclaration<KeepPackagePattern> {
+ private PackageDeclaration(ParsingContext parsingContext) {
+ super(parsingContext);
+ }
+
@Override
String kind() {
return "package";
@@ -2171,10 +2254,15 @@
private static class ClassNamePatternDeclaration
extends Declaration<KeepQualifiedClassNamePattern> {
- private final ClassSimpleNameDeclaration nameDeclaration = new ClassSimpleNameDeclaration();
- private final PackageDeclaration packageDeclaration = new PackageDeclaration();
- private final List<Declaration<?>> declarations =
- ImmutableList.of(nameDeclaration, packageDeclaration);
+ private final ClassSimpleNameDeclaration nameDeclaration;
+ private final PackageDeclaration packageDeclaration;
+ private final List<Declaration<?>> declarations;
+
+ public ClassNamePatternDeclaration(ParsingContext parsingContext) {
+ nameDeclaration = new ClassSimpleNameDeclaration(parsingContext);
+ packageDeclaration = new PackageDeclaration(parsingContext);
+ declarations = ImmutableList.of(nameDeclaration, packageDeclaration);
+ }
@Override
String kind() {
@@ -2200,16 +2288,14 @@
private static class ClassNamePatternVisitor extends AnnotationVisitorBase {
- private final ClassNamePatternDeclaration declaration = new ClassNamePatternDeclaration();
+ private final ClassNamePatternDeclaration declaration;
private final Consumer<KeepQualifiedClassNamePattern> setValue;
- public ClassNamePatternVisitor(Consumer<KeepQualifiedClassNamePattern> setValue) {
+ public ClassNamePatternVisitor(
+ AnnotationParsingContext parsingContext, Consumer<KeepQualifiedClassNamePattern> setValue) {
+ super(parsingContext);
this.setValue = setValue;
- }
-
- @Override
- public String getAnnotationName() {
- return ClassNamePattern.SIMPLE_NAME;
+ declaration = new ClassNamePatternDeclaration(parsingContext);
}
@Override
@@ -2229,24 +2315,19 @@
}
private static class TypePatternVisitor extends AnnotationVisitorBase {
- private final Supplier<String> annotationName;
+ private final ParsingContext parsingContext;
private final Consumer<KeepTypePattern> consumer;
private KeepTypePattern result = null;
- private TypePatternVisitor(
- Supplier<String> annotationName, Consumer<KeepTypePattern> consumer) {
- this.annotationName = annotationName;
+ private TypePatternVisitor(ParsingContext parsingContext, Consumer<KeepTypePattern> consumer) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.consumer = consumer;
}
- @Override
- public String getAnnotationName() {
- return annotationName.get();
- }
-
private void setResult(KeepTypePattern result) {
if (this.result != null) {
- throw new KeepEdgeException("Invalid type annotation defining multiple properties.");
+ throw parsingContext.error("Invalid type annotation defining multiple properties.");
}
this.result = result;
}
@@ -2270,6 +2351,7 @@
if (TypePattern.classNamePattern.equals(name)
&& descriptor.equals(ClassNamePattern.DESCRIPTOR)) {
return new ClassNamePatternVisitor(
+ new AnnotationParsingContext(parsingContext, descriptor),
p -> {
if (p.isExact()) {
setResult(KeepTypePattern.fromDescriptor(p.getExactDescriptor()));
@@ -2289,25 +2371,21 @@
}
private static class TypePatternsArrayVisitor extends AnnotationVisitorBase {
- private final Supplier<String> annotationName;
+ private final ParsingContext parsingContext;
private final Consumer<List<KeepTypePattern>> fn;
private final List<KeepTypePattern> patterns = new ArrayList<>();
public TypePatternsArrayVisitor(
- Supplier<String> annotationName, Consumer<List<KeepTypePattern>> fn) {
- this.annotationName = annotationName;
+ ParsingContext parsingContext, Consumer<List<KeepTypePattern>> fn) {
+ super(parsingContext);
+ this.parsingContext = parsingContext;
this.fn = fn;
}
@Override
- public String getAnnotationName() {
- return annotationName.get();
- }
-
- @Override
public AnnotationVisitor visitAnnotation(String unusedName, String descriptor) {
if (TypePattern.DESCRIPTOR.equals(descriptor)) {
- return new TypePatternVisitor(annotationName, patterns::add);
+ return new TypePatternVisitor(parsingContext, patterns::add);
}
return null;
}
@@ -2321,10 +2399,8 @@
private static class OptionsDeclaration extends SingleDeclaration<KeepOptions> {
- private final String annotationName;
-
- public OptionsDeclaration(String annotationName) {
- this.annotationName = annotationName;
+ public OptionsDeclaration(ParsingContext parsingContext) {
+ super(parsingContext);
}
@Override
@@ -2346,17 +2422,17 @@
AnnotationVisitor parseArray(String name, Consumer<KeepOptions> setValue) {
if (name.equals(AnnotationConstants.Target.constraints)) {
return new KeepConstraintsVisitor(
- annotationName,
+ getParsingContext(),
options -> setValue.accept(KeepOptions.disallowBuilder().addAll(options).build()));
}
if (name.equals(AnnotationConstants.Target.disallow)) {
return new KeepOptionsVisitor(
- annotationName,
+ getParsingContext(),
options -> setValue.accept(KeepOptions.disallowBuilder().addAll(options).build()));
}
if (name.equals(AnnotationConstants.Target.allow)) {
return new KeepOptionsVisitor(
- annotationName,
+ getParsingContext(),
options -> setValue.accept(KeepOptions.allowBuilder().addAll(options).build()));
}
return null;
@@ -2366,18 +2442,25 @@
private static class KeepTargetVisitor extends KeepItemVisitorBase {
private final Parent<KeepTarget> parent;
- private final KeepTarget.Builder builder = KeepTarget.builder();
- private final OptionsDeclaration optionsDeclaration =
- new OptionsDeclaration(getAnnotationName());
private final UserBindingsHelper bindingsHelper;
+ private final OptionsDeclaration optionsDeclaration;
+ private final KeepTarget.Builder builder = KeepTarget.builder();
- static KeepTargetVisitor create(Parent<KeepTarget> parent, UserBindingsHelper bindingsHelper) {
- return new KeepTargetVisitor(parent, bindingsHelper);
+ static KeepTargetVisitor create(
+ ParsingContext parsingContext,
+ Parent<KeepTarget> parent,
+ UserBindingsHelper bindingsHelper) {
+ return new KeepTargetVisitor(parsingContext, parent, bindingsHelper);
}
- private KeepTargetVisitor(Parent<KeepTarget> parent, UserBindingsHelper bindingsHelper) {
+ private KeepTargetVisitor(
+ ParsingContext parsingContext,
+ Parent<KeepTarget> parent,
+ UserBindingsHelper bindingsHelper) {
+ super(parsingContext);
this.parent = parent;
this.bindingsHelper = bindingsHelper;
+ optionsDeclaration = new OptionsDeclaration(parsingContext);
}
@Override
@@ -2386,11 +2469,6 @@
}
@Override
- public String getAnnotationName() {
- return Target.SIMPLE_NAME;
- }
-
- @Override
public AnnotationVisitor visitArray(String name) {
AnnotationVisitor visitor = optionsDeclaration.tryParseArray(name);
if (visitor != null) {
@@ -2414,7 +2492,11 @@
private final Parent<KeepCondition> parent;
private final UserBindingsHelper bindingsHelper;
- public KeepConditionVisitor(Parent<KeepCondition> parent, UserBindingsHelper bindingsHelper) {
+ public KeepConditionVisitor(
+ ParsingContext parsingContext,
+ Parent<KeepCondition> parent,
+ UserBindingsHelper bindingsHelper) {
+ super(parsingContext);
this.parent = parent;
this.bindingsHelper = bindingsHelper;
}
@@ -2425,11 +2507,6 @@
}
@Override
- public String getAnnotationName() {
- return Condition.SIMPLE_NAME;
- }
-
- @Override
public void visitEnd() {
super.visitEnd();
parent.accept(KeepCondition.builder().setItemReference(getItemReference()).build());
@@ -2438,21 +2515,16 @@
private static class KeepConstraintsVisitor extends AnnotationVisitorBase {
- private final String annotationName;
private final Parent<Collection<KeepOption>> parent;
private final Set<KeepOption> options = new HashSet<>();
- public KeepConstraintsVisitor(String annotationName, Parent<Collection<KeepOption>> parent) {
- this.annotationName = annotationName;
+ public KeepConstraintsVisitor(
+ ParsingContext parsingContext, Parent<Collection<KeepOption>> parent) {
+ super(parsingContext);
this.parent = parent;
}
@Override
- public String getAnnotationName() {
- return annotationName;
- }
-
- @Override
public void visitEnum(String ignore, String descriptor, String value) {
if (!descriptor.equals(AnnotationConstants.Constraints.DESCRIPTOR)) {
super.visitEnum(ignore, descriptor, value);
@@ -2506,21 +2578,16 @@
private static class KeepOptionsVisitor extends AnnotationVisitorBase {
- private final String annotationName;
private final Parent<Collection<KeepOption>> parent;
private final Set<KeepOption> options = new HashSet<>();
- public KeepOptionsVisitor(String annotationName, Parent<Collection<KeepOption>> parent) {
- this.annotationName = annotationName;
+ public KeepOptionsVisitor(
+ ParsingContext parsingContext, Parent<Collection<KeepOption>> parent) {
+ super(parsingContext);
this.parent = parent;
}
@Override
- public String getAnnotationName() {
- return annotationName;
- }
-
- @Override
public void visitEnum(String ignore, String descriptor, String value) {
if (!descriptor.equals(AnnotationConstants.Option.DESCRIPTOR)) {
super.visitEnum(ignore, descriptor, value);
@@ -2557,20 +2624,13 @@
}
private static class MemberAccessVisitor extends AnnotationVisitorBase {
- private final Supplier<String> annotationName;
- KeepMemberAccessPattern.BuilderBase<?, ?> builder;
+ private KeepMemberAccessPattern.BuilderBase<?, ?> builder;
- public MemberAccessVisitor(
- Supplier<String> annotationName, KeepMemberAccessPattern.BuilderBase<?, ?> builder) {
- this.annotationName = annotationName;
+ public MemberAccessVisitor(ParsingContext parsingContext, BuilderBase<?, ?> builder) {
+ super(parsingContext);
this.builder = builder;
}
- @Override
- public String getAnnotationName() {
- return annotationName.get();
- }
-
static boolean withNormalizedAccessFlag(String flag, BiPredicate<String, Boolean> fn) {
boolean allow = !flag.startsWith(MemberAccess.NEGATION_PREFIX);
return allow
@@ -2629,13 +2689,12 @@
private static class MethodAccessVisitor extends MemberAccessVisitor {
- @SuppressWarnings("HidingField")
- KeepMethodAccessPattern.Builder builder;
+ private KeepMethodAccessPattern.Builder methodAccessBuilder;
public MethodAccessVisitor(
- Supplier<String> annotationName, KeepMethodAccessPattern.Builder builder) {
- super(annotationName, builder);
- this.builder = builder;
+ ParsingContext parsingContext, KeepMethodAccessPattern.Builder builder) {
+ super(parsingContext, builder);
+ this.methodAccessBuilder = builder;
}
@Override
@@ -2649,19 +2708,19 @@
(flag, allow) -> {
switch (flag) {
case MethodAccess.SYNCHRONIZED:
- builder.setSynchronized(allow);
+ methodAccessBuilder.setSynchronized(allow);
return true;
case MethodAccess.BRIDGE:
- builder.setBridge(allow);
+ methodAccessBuilder.setBridge(allow);
return true;
case MethodAccess.NATIVE:
- builder.setNative(allow);
+ methodAccessBuilder.setNative(allow);
return true;
case MethodAccess.ABSTRACT:
- builder.setAbstract(allow);
+ methodAccessBuilder.setAbstract(allow);
return true;
case MethodAccess.STRICT_FP:
- builder.setStrictFp(allow);
+ methodAccessBuilder.setStrictFp(allow);
return true;
default:
return false;
@@ -2676,13 +2735,12 @@
private static class FieldAccessVisitor extends MemberAccessVisitor {
- @SuppressWarnings("HidingField")
- KeepFieldAccessPattern.Builder builder;
+ private KeepFieldAccessPattern.Builder fieldAccessBuilder;
public FieldAccessVisitor(
- Supplier<String> annotationName, KeepFieldAccessPattern.Builder builder) {
- super(annotationName, builder);
- this.builder = builder;
+ ParsingContext parsingContext, KeepFieldAccessPattern.Builder builder) {
+ super(parsingContext, builder);
+ this.fieldAccessBuilder = builder;
}
@Override
@@ -2696,10 +2754,10 @@
(flag, allow) -> {
switch (flag) {
case FieldAccess.VOLATILE:
- builder.setVolatile(allow);
+ fieldAccessBuilder.setVolatile(allow);
return true;
case FieldAccess.TRANSIENT:
- builder.setTransient(allow);
+ fieldAccessBuilder.setTransient(allow);
return true;
default:
return false;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReaderUtils.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReaderUtils.java
index d88b010..18e5c02 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReaderUtils.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReaderUtils.java
@@ -23,19 +23,55 @@
return "L" + getBinaryNameFromClassTypeName(classTypeName) + ";";
}
+ public static String getJavaTypeFromDescriptor(String descriptor) {
+ if (descriptor.length() == 1) {
+ switch (descriptor.charAt(0)) {
+ case 'Z':
+ return "boolean";
+ case 'B':
+ return "byte";
+ case 'C':
+ return "char";
+ case 'S':
+ return "short";
+ case 'I':
+ return "int";
+ case 'J':
+ return "long";
+ case 'F':
+ return "float";
+ case 'D':
+ return "double";
+ case 'V':
+ return "void";
+ default:
+ throw new IllegalStateException("Unexpected descriptor: " + descriptor);
+ }
+ }
+ if (descriptor.charAt(0) == '[') {
+ return getJavaTypeFromDescriptor(descriptor.substring(1)) + "[]";
+ }
+ if (descriptor.charAt(0) == 'L') {
+ return descriptor.substring(1, descriptor.length() - 1).replace('/', '.');
+ }
+ throw new IllegalStateException("Unexpected descriptor: " + descriptor);
+ }
+
public static KeepTypePattern typePatternFromString(String string) {
if (string.equals("<any>")) {
return KeepTypePattern.any();
}
- return KeepTypePattern.fromDescriptor(javaTypeToDescriptor(string));
+ return KeepTypePattern.fromDescriptor(getDescriptorFromJavaType(string));
}
- public static String javaTypeToDescriptor(String type) {
+ public static String getDescriptorFromJavaType(String type) {
switch (type) {
case "boolean":
return "Z";
case "byte":
return "B";
+ case "char":
+ return "C";
case "short":
return "S";
case "int":
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/PackageNameParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/PackageNameParser.java
index adef04f..dadb8de 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/PackageNameParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/PackageNameParser.java
@@ -6,11 +6,16 @@
import com.android.tools.r8.keepanno.asm.PackageNameParser.PackageNameProperty;
import com.android.tools.r8.keepanno.ast.KeepPackagePattern;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
import java.util.function.Consumer;
public class PackageNameParser
extends PropertyParserBase<KeepPackagePattern, PackageNameProperty, PackageNameParser> {
+ public PackageNameParser(ParsingContext parsingContext) {
+ super(parsingContext);
+ }
+
public enum PackageNameProperty {
NAME
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ParserVisitor.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ParserVisitor.java
index 5c8ea6f..77d6087 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ParserVisitor.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ParserVisitor.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.keepanno.asm;
+import com.android.tools.r8.keepanno.ast.ParsingContext.AnnotationParsingContext;
import java.util.Collections;
import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
@@ -11,32 +12,31 @@
/** Convert parser(s) into an annotation visitor. */
public class ParserVisitor extends AnnotationVisitorBase {
- private final String annotationDescriptor;
private final List<PropertyParser<?, ?, ?>> parsers;
private final Runnable onVisitEnd;
public ParserVisitor(
- String annotationDescriptor, List<PropertyParser<?, ?, ?>> parsers, Runnable onVisitEnd) {
- this.annotationDescriptor = annotationDescriptor;
+ AnnotationParsingContext parsingContext,
+ String annotationDescriptor,
+ List<PropertyParser<?, ?, ?>> parsers,
+ Runnable onVisitEnd) {
+ super(parsingContext);
this.parsers = parsers;
this.onVisitEnd = onVisitEnd;
+ assert annotationDescriptor.equals(parsingContext.getAnnotationDescriptor());
}
public ParserVisitor(
- String annotationDescriptor, PropertyParser<?, ?, ?> declaration, Runnable onVisitEnd) {
- this(annotationDescriptor, Collections.singletonList(declaration), onVisitEnd);
+ AnnotationParsingContext parsingContext,
+ String annotationDescriptor,
+ PropertyParser<?, ?, ?> declaration,
+ Runnable onVisitEnd) {
+ this(parsingContext, annotationDescriptor, Collections.singletonList(declaration), onVisitEnd);
}
private <T> void ignore(T unused) {}
@Override
- public String getAnnotationName() {
- int start = annotationDescriptor.lastIndexOf('/') + 1;
- int end = annotationDescriptor.length() - 1;
- return annotationDescriptor.substring(start, end);
- }
-
- @Override
public void visit(String name, Object value) {
for (PropertyParser<?, ?, ?> parser : parsers) {
if (parser.tryParse(name, value, this::ignore)) {
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/PropertyParserBase.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/PropertyParserBase.java
index 027b6c2..108f086 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/PropertyParserBase.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/PropertyParserBase.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.keepanno.asm;
import com.android.tools.r8.keepanno.ast.KeepEdgeException;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
@@ -13,11 +14,21 @@
/** Special case of a property parser allowing only a single value callback. */
public abstract class PropertyParserBase<T, P, S> implements PropertyParser<T, P, S> {
+ private final ParsingContext parsingContext;
+
private String kind;
private final Map<String, P> mapping = new HashMap<>();
private String resultPropertyName = null;
private T resultValue = null;
+ protected PropertyParserBase(ParsingContext parsingContext) {
+ this.parsingContext = parsingContext;
+ }
+
+ public ParsingContext getParsingContext() {
+ return parsingContext;
+ }
+
boolean tryProperty(P property, String name, Object value, Consumer<T> setValue) {
return false;
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/TypeParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/TypeParser.java
index f9c6739..6b11f70 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/TypeParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/TypeParser.java
@@ -8,6 +8,8 @@
import com.android.tools.r8.keepanno.asm.TypeParser.TypeProperty;
import com.android.tools.r8.keepanno.ast.AnnotationConstants.TypePattern;
import com.android.tools.r8.keepanno.ast.KeepTypePattern;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
+import com.android.tools.r8.keepanno.ast.ParsingContext.AnnotationParsingContext;
import com.android.tools.r8.keepanno.utils.Unimplemented;
import java.util.function.Consumer;
import org.objectweb.asm.AnnotationVisitor;
@@ -15,6 +17,10 @@
public class TypeParser extends PropertyParserBase<KeepTypePattern, TypeProperty, TypeParser> {
+ public TypeParser(ParsingContext parsingContext) {
+ super(parsingContext);
+ }
+
public enum TypeProperty {
SELF_PATTERN,
TYPE_NAME,
@@ -63,32 +69,39 @@
TypeProperty property, String name, String descriptor, Consumer<KeepTypePattern> setValue) {
switch (property) {
case SELF_PATTERN:
- TypeParser typeParser =
- new TypeParser()
- .setKind(kind())
- .enableTypeName(TypePattern.name)
- .enableTypeConstant(TypePattern.constant)
- .enableTypeClassNamePattern(TypePattern.classNamePattern);
- return new ParserVisitor(
- descriptor,
- typeParser,
- () -> setValue.accept(typeParser.getValueOrDefault(KeepTypePattern.any())));
+ {
+ AnnotationParsingContext parsingContext =
+ new AnnotationParsingContext(getParsingContext(), descriptor);
+ TypeParser typeParser =
+ new TypeParser(parsingContext)
+ .setKind(kind())
+ .enableTypeName(TypePattern.name)
+ .enableTypeConstant(TypePattern.constant)
+ .enableTypeClassNamePattern(TypePattern.classNamePattern);
+ return new ParserVisitor(
+ parsingContext,
+ descriptor,
+ typeParser,
+ () -> setValue.accept(typeParser.getValueOrDefault(KeepTypePattern.any())));
+ }
case CLASS_NAME_PATTERN:
- return new ClassNameParser()
- .setKind(kind())
- .tryPropertyAnnotation(
- ClassNameProperty.PATTERN,
- name,
- descriptor,
- classNamePattern -> {
- if (classNamePattern.isExact()) {
- setValue.accept(
- KeepTypePattern.fromDescriptor(classNamePattern.getExactDescriptor()));
- } else {
- // TODO(b/248408342): Extend the AST type patterns.
- throw new Unimplemented("Non-exact class patterns are not implemented yet");
- }
- });
+ {
+ return new ClassNameParser(getParsingContext())
+ .setKind(kind())
+ .tryPropertyAnnotation(
+ ClassNameProperty.PATTERN,
+ name,
+ descriptor,
+ classNamePattern -> {
+ if (classNamePattern.isExact()) {
+ setValue.accept(
+ KeepTypePattern.fromDescriptor(classNamePattern.getExactDescriptor()));
+ } else {
+ // TODO(b/248408342): Extend the AST type patterns.
+ throw new Unimplemented("Non-exact class patterns are not implemented yet");
+ }
+ });
+ }
default:
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 cae779e..13a228b 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
@@ -16,7 +16,6 @@
*/
public final class AnnotationConstants {
public static final class Edge {
- public static final String SIMPLE_NAME = "KeepEdge";
public static final String DESCRIPTOR = "Lcom/android/tools/r8/keepanno/annotations/KeepEdge;";
public static final String description = "description";
public static final String bindings = "bindings";
@@ -25,7 +24,6 @@
}
public static final class ForApi {
- public static final String SIMPLE_NAME = "KeepForApi";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/KeepForApi;";
public static final String description = "description";
@@ -34,7 +32,6 @@
}
public static final class UsesReflection {
- public static final String SIMPLE_NAME = "UsesReflection";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/UsesReflection;";
public static final String description = "description";
@@ -43,7 +40,6 @@
}
public static final class UsedByReflection {
- public static final String SIMPLE_NAME = "UsedByReflection";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/UsedByReflection;";
public static final String description = "description";
@@ -52,20 +48,17 @@
}
public static final class UsedByNative {
- public static final String SIMPLE_NAME = "UsedByNative";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/UsedByNative;";
// Content is the same as UsedByReflection.
}
public static final class CheckRemoved {
- public static final String SIMPLE_NAME = "CheckRemoved";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/CheckRemoved;";
}
public static final class CheckOptimizedOut {
- public static final String SIMPLE_NAME = "CheckOptimizedOut";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/CheckOptimizedOut;";
}
@@ -100,20 +93,17 @@
}
public static final class Binding {
- public static final String SIMPLE_NAME = "KeepBinding";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/KeepBinding;";
public static final String bindingName = "bindingName";
}
public static final class Condition {
- public static final String SIMPLE_NAME = "KeepCondition";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/KeepCondition;";
}
public static final class Target {
- public static final String SIMPLE_NAME = "KeepTarget";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/KeepTarget;";
public static final String kind = "kind";
@@ -123,7 +113,6 @@
}
public static final class Kind {
- public static final String SIMPLE_NAME = "KeepItemKind";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/KeepItemKind;";
public static final String ONLY_CLASS = "ONLY_CLASS";
@@ -136,7 +125,6 @@
}
public static final class Constraints {
- public static final String SIMPLE_NAME = "KeepConstraint";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/KeepConstraint;";
public static final String LOOKUP = "LOOKUP";
@@ -155,7 +143,6 @@
}
public static final class Option {
- public static final String SIMPLE_NAME = "KeepOption";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/KeepOption;";
public static final String SHRINKING = "SHRINKING";
@@ -166,7 +153,6 @@
}
public static final class MemberAccess {
- public static final String SIMPLE_NAME = "MemberAccessFlags";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/MemberAccessFlags;";
public static final String NEGATION_PREFIX = "NON_";
@@ -180,7 +166,6 @@
}
public static final class MethodAccess {
- public static final String SIMPLE_NAME = "MethodAccessFlags";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/MethodAccessFlags;";
public static final String SYNCHRONIZED = "SYNCHRONIZED";
@@ -191,7 +176,6 @@
}
public static final class FieldAccess {
- public static final String SIMPLE_NAME = "FieldAccessFlags";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/FieldAccessFlags;";
public static final String VOLATILE = "VOLATILE";
@@ -199,7 +183,6 @@
}
public static final class TypePattern {
- public static final String SIMPLE_NAME = "TypePattern";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/TypePattern;";
public static final String name = "name";
@@ -208,7 +191,6 @@
}
public static final class ClassNamePattern {
- public static final String SIMPLE_NAME = "ClassNamePattern";
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/ClassNamePattern;";
public static final String simpleName = "simpleName";
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAnnotationParserException.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAnnotationParserException.java
new file mode 100644
index 0000000..d98d410
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAnnotationParserException.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2023, 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.ast;
+
+public class KeepAnnotationParserException extends KeepEdgeException {
+
+ private final ParsingContext context;
+
+ public KeepAnnotationParserException(ParsingContext context, String message) {
+ super(message);
+ this.context = context;
+ }
+
+ @Override
+ public String getMessage() {
+ return super.getMessage() + getContextAsString();
+ }
+
+ private String getContextAsString() {
+ StringBuilder builder = new StringBuilder();
+ ParsingContext current = context;
+ while (current != null) {
+ builder.append("\n in ").append(current.getContextFrameAsString());
+ current = current.getParentContext();
+ }
+ return builder.toString();
+ }
+}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepEdgeMetaInfo.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepEdgeMetaInfo.java
index 75094be..4ec248b 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepEdgeMetaInfo.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepEdgeMetaInfo.java
@@ -115,12 +115,11 @@
}
@Override
- @SuppressWarnings("EqualsGetClass")
public boolean equals(Object o) {
if (this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if (!(o instanceof KeepEdgeClassContext)) {
return false;
}
KeepEdgeClassContext that = (KeepEdgeClassContext) o;
@@ -154,12 +153,11 @@
}
@Override
- @SuppressWarnings("EqualsGetClass")
public boolean equals(Object o) {
if (this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if (!(o instanceof KeepEdgeMethodContext)) {
return false;
}
KeepEdgeMethodContext that = (KeepEdgeMethodContext) o;
@@ -191,12 +189,11 @@
}
@Override
- @SuppressWarnings("EqualsGetClass")
public boolean equals(Object o) {
if (this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if (!(o instanceof KeepEdgeFieldContext)) {
return false;
}
KeepEdgeFieldContext that = (KeepEdgeFieldContext) o;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/ParsingContext.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/ParsingContext.java
new file mode 100644
index 0000000..d7ce9a4
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/ParsingContext.java
@@ -0,0 +1,147 @@
+// Copyright (c) 2023, 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.ast;
+
+import static com.android.tools.r8.keepanno.asm.KeepEdgeReaderUtils.getJavaTypeFromDescriptor;
+
+import org.objectweb.asm.Type;
+
+public abstract class ParsingContext {
+
+ public KeepAnnotationParserException error(String message) {
+ throw new KeepAnnotationParserException(this, message);
+ }
+
+ public abstract String getHolderName();
+
+ public ParsingContext getParentContext() {
+ return null;
+ }
+
+ public abstract String getContextFrameAsString();
+
+ public static class ClassParsingContext extends ParsingContext {
+ private final String className;
+
+ public ClassParsingContext(String className) {
+ this.className = className;
+ }
+
+ @Override
+ public String getHolderName() {
+ return className;
+ }
+
+ @Override
+ public String getContextFrameAsString() {
+ return className;
+ }
+ }
+
+ public abstract static class MemberParsingContext extends ParsingContext {
+ private final ClassParsingContext classContext;
+
+ public MemberParsingContext(ClassParsingContext classContext) {
+ this.classContext = classContext;
+ }
+
+ @Override
+ public String getHolderName() {
+ return classContext.getHolderName();
+ }
+
+ @Override
+ public ParsingContext getParentContext() {
+ return classContext;
+ }
+ }
+
+ public static class MethodParsingContext extends MemberParsingContext {
+
+ private final String methodName;
+ private final String methodDescriptor;
+
+ public MethodParsingContext(
+ ClassParsingContext classContext, String methodName, String methodDescriptor) {
+ super(classContext);
+ this.methodName = methodName;
+ this.methodDescriptor = methodDescriptor;
+ }
+
+ @Override
+ public String getContextFrameAsString() {
+ Type methodType = Type.getMethodType(methodDescriptor);
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("method ")
+ .append(getJavaTypeFromDescriptor(methodType.getReturnType().getDescriptor()))
+ .append(' ')
+ .append(methodName)
+ .append('(');
+ boolean first = true;
+ for (Type argument : methodType.getArgumentTypes()) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(", ");
+ }
+ builder.append(getJavaTypeFromDescriptor(argument.getDescriptor()));
+ }
+ return builder.append(')').toString();
+ }
+ }
+
+ public static class FieldParsingContext extends MemberParsingContext {
+
+ private final String fieldName;
+ private final String fieldDescriptor;
+
+ public FieldParsingContext(
+ ClassParsingContext classContext, String fieldName, String fieldDescriptor) {
+ super(classContext);
+ this.fieldName = fieldName;
+ this.fieldDescriptor = fieldDescriptor;
+ }
+
+ @Override
+ public String getContextFrameAsString() {
+ return "field " + getJavaTypeFromDescriptor(fieldDescriptor) + " " + fieldName;
+ }
+ }
+
+ public static class AnnotationParsingContext extends ParsingContext {
+ private final ParsingContext parentContext;
+ private final String annotationDescriptor;
+
+ public AnnotationParsingContext(ParsingContext parentContext, String annotationDescriptor) {
+ this.parentContext = parentContext;
+ this.annotationDescriptor = annotationDescriptor;
+ }
+
+ public String getAnnotationDescriptor() {
+ return annotationDescriptor;
+ }
+
+ private String getSimpleAnnotationName() {
+ int i = annotationDescriptor.lastIndexOf('/') + 1;
+ return annotationDescriptor.substring(Math.max(i, 1), annotationDescriptor.length() - 1);
+ }
+
+ @Override
+ public String getHolderName() {
+ return parentContext.getHolderName();
+ }
+
+ @Override
+ public ParsingContext getParentContext() {
+ return parentContext;
+ }
+
+ @Override
+ public String getContextFrameAsString() {
+ return "@" + getSimpleAnnotationName();
+ }
+ }
+}
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 bee5471..312e8bb 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
@@ -1220,9 +1220,7 @@
}
private void generateAnnotationConstants(Class<?> clazz) {
- String name = simpleName(clazz);
String desc = TestBase.descriptor(clazz);
- println("public static final String SIMPLE_NAME = " + quote(name) + ";");
println("public static final String DESCRIPTOR = " + quote(desc) + ";");
}