[KeepAnno] Encode property groups in the parsing contexts
This eliminates the previous encoding of the information as a "kind".
The generator is extended to emit "group" names for the cases where
multiple options are possible. This ensures consistency in the naming
between error messages and java doc.
Bug: b/248408342
Change-Id: Icfec26462dc2d16edd0ea19a1425381fdb47da5c
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepCondition.java b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepCondition.java
index 74b2add..642e829 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepCondition.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepCondition.java
@@ -254,6 +254,8 @@
* <p>Mutually exclusive with all field and method properties as use restricts the match to both
* types of members.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining member-access.
+ *
* @return The member access-flag constraints that must be met.
*/
MemberAccessFlags[] memberAccess() default {};
@@ -266,6 +268,8 @@
* <p>If none, and other properties define this item as a method, the default matches any
* method-access flags.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining method-access.
+ *
* @return The method access-flag constraints that must be met.
*/
MethodAccessFlags[] methodAccess() default {};
@@ -278,6 +282,8 @@
* <p>If none, and other properties define this item as a method, the default matches any method
* name.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining method-name.
+ *
* @return The exact method name of the method.
*/
String methodName() default "";
@@ -295,6 +301,7 @@
* <ul>
* <li>methodReturnTypeConstant
* <li>methodReturnTypePattern
+ * <li>memberFromBinding
* </ul>
*
* @return The qualified type name of the method return type.
@@ -314,6 +321,7 @@
* <ul>
* <li>methodReturnType
* <li>methodReturnTypePattern
+ * <li>memberFromBinding
* </ul>
*
* @return A class constant denoting the type of the method return type.
@@ -333,6 +341,7 @@
* <ul>
* <li>methodReturnType
* <li>methodReturnTypeConstant
+ * <li>memberFromBinding
* </ul>
*
* @return The pattern of the method return type.
@@ -347,7 +356,12 @@
* <p>If none, and other properties define this item as a method, the default matches any
* parameters.
*
- * <p>Mutually exclusive with the property `methodParameterTypePatterns` also defining parameters.
+ * <p>Mutually exclusive with the following other properties defining parameters:
+ *
+ * <ul>
+ * <li>methodParameterTypePatterns
+ * <li>memberFromBinding
+ * </ul>
*
* @return The list of qualified type names of the method parameters.
*/
@@ -361,7 +375,12 @@
* <p>If none, and other properties define this item as a method, the default matches any
* parameters.
*
- * <p>Mutually exclusive with the property `methodParameters` also defining parameters.
+ * <p>Mutually exclusive with the following other properties defining parameters:
+ *
+ * <ul>
+ * <li>methodParameters
+ * <li>memberFromBinding
+ * </ul>
*
* @return The list of type patterns for the method parameters.
*/
@@ -375,6 +394,8 @@
* <p>If none, and other properties define this item as a field, the default matches any
* field-access flags.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining field-access.
+ *
* @return The field access-flag constraints that must be met.
*/
FieldAccessFlags[] fieldAccess() default {};
@@ -387,6 +408,8 @@
* <p>If none, and other properties define this item as a field, the default matches any field
* name.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining field-name.
+ *
* @return The exact field name of the field.
*/
String fieldName() default "";
@@ -403,6 +426,7 @@
* <ul>
* <li>fieldTypeConstant
* <li>fieldTypePattern
+ * <li>memberFromBinding
* </ul>
*
* @return The qualified type name for the field type.
@@ -421,6 +445,7 @@
* <ul>
* <li>fieldType
* <li>fieldTypePattern
+ * <li>memberFromBinding
* </ul>
*
* @return The class constant for the field type.
@@ -439,6 +464,7 @@
* <ul>
* <li>fieldType
* <li>fieldTypeConstant
+ * <li>memberFromBinding
* </ul>
*
* @return The type pattern for the field type.
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepTarget.java b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepTarget.java
index d60525d..20705dd 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepTarget.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepTarget.java
@@ -351,6 +351,8 @@
* <p>Mutually exclusive with all field and method properties as use restricts the match to both
* types of members.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining member-access.
+ *
* @return The member access-flag constraints that must be met.
*/
MemberAccessFlags[] memberAccess() default {};
@@ -363,6 +365,8 @@
* <p>If none, and other properties define this item as a method, the default matches any
* method-access flags.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining method-access.
+ *
* @return The method access-flag constraints that must be met.
*/
MethodAccessFlags[] methodAccess() default {};
@@ -375,6 +379,8 @@
* <p>If none, and other properties define this item as a method, the default matches any method
* name.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining method-name.
+ *
* @return The exact method name of the method.
*/
String methodName() default "";
@@ -392,6 +398,7 @@
* <ul>
* <li>methodReturnTypeConstant
* <li>methodReturnTypePattern
+ * <li>memberFromBinding
* </ul>
*
* @return The qualified type name of the method return type.
@@ -411,6 +418,7 @@
* <ul>
* <li>methodReturnType
* <li>methodReturnTypePattern
+ * <li>memberFromBinding
* </ul>
*
* @return A class constant denoting the type of the method return type.
@@ -430,6 +438,7 @@
* <ul>
* <li>methodReturnType
* <li>methodReturnTypeConstant
+ * <li>memberFromBinding
* </ul>
*
* @return The pattern of the method return type.
@@ -444,7 +453,12 @@
* <p>If none, and other properties define this item as a method, the default matches any
* parameters.
*
- * <p>Mutually exclusive with the property `methodParameterTypePatterns` also defining parameters.
+ * <p>Mutually exclusive with the following other properties defining parameters:
+ *
+ * <ul>
+ * <li>methodParameterTypePatterns
+ * <li>memberFromBinding
+ * </ul>
*
* @return The list of qualified type names of the method parameters.
*/
@@ -458,7 +472,12 @@
* <p>If none, and other properties define this item as a method, the default matches any
* parameters.
*
- * <p>Mutually exclusive with the property `methodParameters` also defining parameters.
+ * <p>Mutually exclusive with the following other properties defining parameters:
+ *
+ * <ul>
+ * <li>methodParameters
+ * <li>memberFromBinding
+ * </ul>
*
* @return The list of type patterns for the method parameters.
*/
@@ -472,6 +491,8 @@
* <p>If none, and other properties define this item as a field, the default matches any
* field-access flags.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining field-access.
+ *
* @return The field access-flag constraints that must be met.
*/
FieldAccessFlags[] fieldAccess() default {};
@@ -484,6 +505,8 @@
* <p>If none, and other properties define this item as a field, the default matches any field
* name.
*
+ * <p>Mutually exclusive with the property `memberFromBinding` also defining field-name.
+ *
* @return The exact field name of the field.
*/
String fieldName() default "";
@@ -500,6 +523,7 @@
* <ul>
* <li>fieldTypeConstant
* <li>fieldTypePattern
+ * <li>memberFromBinding
* </ul>
*
* @return The qualified type name for the field type.
@@ -518,6 +542,7 @@
* <ul>
* <li>fieldType
* <li>fieldTypePattern
+ * <li>memberFromBinding
* </ul>
*
* @return The class constant for the field type.
@@ -536,6 +561,7 @@
* <ul>
* <li>fieldType
* <li>fieldTypeConstant
+ * <li>memberFromBinding
* </ul>
*
* @return The type pattern for the field type.
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ConvertingPropertyParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ConvertingPropertyParser.java
index ddbfb58..bbc07f3 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ConvertingPropertyParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ConvertingPropertyParser.java
@@ -30,11 +30,6 @@
}
@Override
- public String kind() {
- return parser.kind();
- }
-
- @Override
public void setProperty(String name, P property) {
parser.setProperty(name, property);
}
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 1706b3a..a0461e6 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,6 @@
import com.android.tools.r8.keepanno.ast.AnnotationConstants.Option;
import com.android.tools.r8.keepanno.ast.AnnotationConstants.Target;
import com.android.tools.r8.keepanno.ast.AnnotationConstants.UsedByReflection;
-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;
@@ -59,6 +58,7 @@
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.GroupParsingContext;
import com.android.tools.r8.keepanno.ast.ParsingContext.MethodParsingContext;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -257,7 +257,6 @@
if (descriptor.equals(AnnotationConstants.CheckRemoved.DESCRIPTOR)) {
return new CheckRemovedClassVisitor(
annotationParsingContext(descriptor),
- descriptor,
parent::accept,
this::setContext,
className,
@@ -266,7 +265,6 @@
if (descriptor.equals(AnnotationConstants.CheckOptimizedOut.DESCRIPTOR)) {
return new CheckRemovedClassVisitor(
annotationParsingContext(descriptor),
- descriptor,
parent::accept,
this::setContext,
className,
@@ -378,7 +376,6 @@
if (descriptor.equals(AnnotationConstants.CheckRemoved.DESCRIPTOR)) {
return new CheckRemovedMemberVisitor(
annotationParsingContext(descriptor),
- descriptor,
parent::accept,
this::setContext,
createMethodItemContext(),
@@ -387,7 +384,6 @@
if (descriptor.equals(AnnotationConstants.CheckOptimizedOut.DESCRIPTOR)) {
return new CheckRemovedMemberVisitor(
annotationParsingContext(descriptor),
- descriptor,
parent::accept,
this::setContext,
createMethodItemContext(),
@@ -860,7 +856,6 @@
private static class UsedByReflectionMemberVisitor extends AnnotationVisitorBase {
private final AnnotationParsingContext parsingContext;
- private final String annotationDescriptor;
private final Parent<KeepEdge> parent;
private final KeepItemPattern context;
private final KeepEdge.Builder builder = KeepEdge.builder();
@@ -878,7 +873,6 @@
KeepItemPattern context) {
super(parsingContext);
this.parsingContext = parsingContext;
- this.annotationDescriptor = annotationDescriptor;
this.parent = parent;
this.context = context;
addContext.accept(metaInfoBuilder);
@@ -1107,7 +1101,6 @@
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();
private final String className;
@@ -1115,14 +1108,12 @@
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;
this.kind = kind;
@@ -1140,7 +1131,6 @@
@Override
public void visitEnd() {
- CheckRemovedClassVisitor superVisitor = this;
KeepItemVisitorBase itemVisitor =
new KeepItemVisitorBase(parsingContext) {
@Override
@@ -1162,7 +1152,6 @@
/** Parsing of @CheckRemoved and @CheckOptimizedOut on a class context. */
private static class CheckRemovedMemberVisitor extends AnnotationVisitorBase {
- private final String annotationDescriptor;
private final Parent<KeepDeclaration> parent;
private final KeepItemPattern context;
private final KeepEdgeMetaInfo.Builder metaInfoBuilder = KeepEdgeMetaInfo.builder();
@@ -1170,13 +1159,11 @@
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;
this.kind = kind;
@@ -1205,7 +1192,6 @@
}
abstract static class Declaration<T> {
- abstract String kind();
boolean isDefault() {
for (Declaration<?> declaration : declarations()) {
@@ -1216,8 +1202,6 @@
return true;
}
- abstract T getValue();
-
List<Declaration<?>> declarations() {
return Collections.emptyList();
}
@@ -1281,7 +1265,7 @@
private T declarationValue = null;
private AnnotationVisitor declarationVisitor = null;
- private SingleDeclaration(ParsingContext parsingContext) {
+ private SingleDeclaration(GroupParsingContext parsingContext) {
this.parsingContext = parsingContext;
}
@@ -1311,19 +1295,11 @@
}
private void error(String name) {
- throw new KeepAnnotationParserException(
- parsingContext,
- "Multiple declarations defining "
- + kind()
- + ": '"
- + declarationName
- + "' and '"
- + name
- + "'");
+ throw parsingContext.error(
+ "Multiple properties: '" + declarationName + "' and '" + name + "'");
}
- @Override
- public final T getValue() {
+ final T getValue() {
return declarationValue == null ? getDefaultValue() : declarationValue;
}
@@ -1373,12 +1349,7 @@
private static class InstanceOfDeclaration extends SingleDeclaration<KeepInstanceOfPattern> {
private InstanceOfDeclaration(ParsingContext parsingContext) {
- super(parsingContext);
- }
-
- @Override
- String kind() {
- return "instance-of";
+ super(parsingContext.group(Item.instanceOfGroup));
}
@Override
@@ -1439,9 +1410,9 @@
public ClassDeclaration(
ParsingContext parsingContext, Supplier<UserBindingsHelper> getBindingsHelper) {
- this.parsingContext = parsingContext;
+ this.parsingContext = parsingContext.group(Item.classGroup);
this.getBindingsHelper = getBindingsHelper;
- classNameParser = new ClassNameParser(parsingContext);
+ classNameParser = new ClassNameParser(parsingContext.group(Item.classNameGroup));
classNameParser.setProperty(Item.className, ClassNameProperty.NAME);
classNameParser.setProperty(Item.classConstant, ClassNameProperty.CONSTANT);
classNameParser.setProperty(Item.classNamePattern, ClassNameProperty.PATTERN);
@@ -1477,17 +1448,11 @@
}
@Override
- String kind() {
- return "class";
- }
-
- @Override
boolean isDefault() {
return !isBindingReferenceDefined() && super.isDefault();
}
- @Override
- KeepClassItemReference getValue() {
+ private KeepClassItemReference getValue() {
checkAllowedDefinitions();
if (isBindingReferenceDefined()) {
return boundClassItemReference;
@@ -1536,12 +1501,12 @@
private MethodDeclaration(ParsingContext parsingContext) {
this.parsingContext = parsingContext;
- returnTypeParser = new MethodReturnTypeParser(parsingContext);
+ returnTypeParser = new MethodReturnTypeParser(parsingContext.group(Item.returnTypeGroup));
returnTypeParser.setProperty(Item.methodReturnType, TypeProperty.TYPE_NAME);
returnTypeParser.setProperty(Item.methodReturnTypeConstant, TypeProperty.TYPE_CONSTANT);
returnTypeParser.setProperty(Item.methodReturnTypePattern, TypeProperty.TYPE_PATTERN);
- parametersParser = new MethodParametersParser(parsingContext);
+ parametersParser = new MethodParametersParser(parsingContext.group(Item.parametersGroup));
parametersParser.setProperty(Item.methodParameters, TypeProperty.TYPE_NAME);
parametersParser.setProperty(Item.methodParameterTypePatterns, TypeProperty.TYPE_PATTERN);
@@ -1561,17 +1526,11 @@
}
@Override
- String kind() {
- return "method";
- }
-
- @Override
boolean isDefault() {
return accessBuilder == null && builder == null && super.isDefault();
}
- @Override
- KeepMethodPattern getValue() {
+ private KeepMethodPattern getValue() {
if (accessBuilder != null) {
getBuilder().setAccessPattern(accessBuilder.build());
}
@@ -1613,7 +1572,7 @@
public FieldDeclaration(ParsingContext parsingContext) {
this.parsingContext = parsingContext;
- typeParser = new FieldTypeParser(parsingContext);
+ typeParser = new FieldTypeParser(parsingContext.group(Item.fieldTypeGroup));
typeParser.setProperty(Item.fieldTypePattern, TypeProperty.TYPE_PATTERN);
typeParser.setProperty(Item.fieldType, TypeProperty.TYPE_NAME);
typeParser.setProperty(Item.fieldTypeConstant, TypeProperty.TYPE_CONSTANT);
@@ -1634,17 +1593,11 @@
}
@Override
- String kind() {
- return "field";
- }
-
- @Override
boolean isDefault() {
return accessBuilder == null && builder == null;
}
- @Override
- KeepFieldPattern getValue() {
+ private KeepFieldPattern getValue() {
if (accessBuilder != null) {
getBuilder().setAccessPattern(accessBuilder.build());
}
@@ -1682,7 +1635,7 @@
private final List<Declaration<?>> declarations;
MemberDeclaration(ParsingContext parsingContext) {
- this.parsingContext = parsingContext;
+ this.parsingContext = parsingContext.group(Item.memberGroup);
methodDeclaration = new MethodDeclaration(parsingContext);
fieldDeclaration = new FieldDeclaration(parsingContext);
declarations = ImmutableList.of(methodDeclaration, fieldDeclaration);
@@ -1694,17 +1647,11 @@
}
@Override
- String kind() {
- return "member";
- }
-
- @Override
public boolean isDefault() {
return accessBuilder == null && methodDeclaration.isDefault() && fieldDeclaration.isDefault();
}
- @Override
- public KeepMemberPattern getValue() {
+ private KeepMemberPattern getValue() {
KeepMethodPattern method = methodDeclaration.getValue();
KeepFieldPattern field = fieldDeclaration.getValue();
if (accessBuilder != null) {
@@ -2026,40 +1973,10 @@
}
}
- private static class StringArrayVisitor extends AnnotationVisitorBase {
- private final Consumer<List<String>> fn;
- private final List<String> strings = new ArrayList<>();
-
- public StringArrayVisitor(ParsingContext parsingContext, Consumer<List<String>> fn) {
- super(parsingContext);
- this.fn = fn;
- }
-
- @Override
- public void visit(String name, Object value) {
- if (value instanceof String) {
- strings.add((String) value);
- } else {
- super.visit(name, value);
- }
- }
-
- @Override
- public void visitEnd() {
- super.visitEnd();
- fn.accept(strings);
- }
- }
-
private static class OptionsDeclaration extends SingleDeclaration<KeepOptions> {
public OptionsDeclaration(ParsingContext parsingContext) {
- super(parsingContext);
- }
-
- @Override
- String kind() {
- return "options";
+ super(parsingContext.group(Target.constraintsGroup));
}
@Override
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/PropertyParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/PropertyParser.java
index 4dc7b38..0fd8a75 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/PropertyParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/PropertyParser.java
@@ -9,8 +9,6 @@
public interface PropertyParser<T, P> {
- String kind();
-
void setProperty(String name, P property);
boolean isDeclared();
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 6578a7f..1ab1fea 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
@@ -15,7 +15,6 @@
private final ParsingContext parsingContext;
- private String kind;
private final Map<String, P> mapping = new HashMap<>();
private String resultPropertyName = null;
private T resultValue = null;
@@ -66,13 +65,7 @@
private void error(String name) {
throw parsingContext.error(
- "Multiple properties defining "
- + kind()
- + ": '"
- + resultPropertyName
- + "' and '"
- + name
- + "'");
+ "Multiple properties: '" + resultPropertyName + "' and '" + name + "'");
}
public final boolean isDeclared() {
@@ -90,14 +83,6 @@
return isDeclared() ? resultValue : defaultValue;
}
- public String kind() {
- return kind != null ? kind : "";
- }
-
- public void setKind(String kind) {
- this.kind = kind;
- }
-
/** Add property parsing for the given property-name. */
public void setProperty(String name, P property) {
P old = mapping.put(name, property);
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 e3922c6..c1682c9 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
@@ -51,8 +51,8 @@
{
AnnotationParsingContext parsingContext =
new AnnotationParsingContext(getParsingContext(), descriptor);
- TypeParser typeParser = new TypeParser(parsingContext);
- typeParser.setKind(kind());
+ TypeParser typeParser =
+ new TypeParser(parsingContext.group(TypePattern.typePatternGroup));
typeParser.setProperty(TypePattern.name, TypeProperty.TYPE_NAME);
typeParser.setProperty(TypePattern.constant, TypeProperty.TYPE_CONSTANT);
typeParser.setProperty(TypePattern.classNamePattern, TypeProperty.CLASS_NAME_PATTERN);
@@ -65,7 +65,6 @@
case CLASS_NAME_PATTERN:
{
ClassNameParser parser = new ClassNameParser(getParsingContext());
- parser.setKind(kind());
return parser.tryPropertyAnnotation(
ClassNameProperty.PATTERN,
name,
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 13a228b..65dc77b 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
@@ -65,11 +65,15 @@
/** Item properties common to binding items, conditions and targets. */
public static final class Item {
+ public static final String classGroup = "class";
public static final String classFromBinding = "classFromBinding";
+ public static final String memberGroup = "member";
public static final String memberFromBinding = "memberFromBinding";
+ public static final String classNameGroup = "class-name";
public static final String className = "className";
public static final String classConstant = "classConstant";
public static final String classNamePattern = "classNamePattern";
+ public static final String instanceOfGroup = "instance-of";
public static final String instanceOfClassName = "instanceOfClassName";
public static final String instanceOfClassNameExclusive = "instanceOfClassNameExclusive";
public static final String instanceOfClassConstant = "instanceOfClassConstant";
@@ -80,13 +84,16 @@
public static final String memberAccess = "memberAccess";
public static final String methodAccess = "methodAccess";
public static final String methodName = "methodName";
+ public static final String returnTypeGroup = "return-type";
public static final String methodReturnType = "methodReturnType";
public static final String methodReturnTypeConstant = "methodReturnTypeConstant";
public static final String methodReturnTypePattern = "methodReturnTypePattern";
+ public static final String parametersGroup = "parameters";
public static final String methodParameters = "methodParameters";
public static final String methodParameterTypePatterns = "methodParameterTypePatterns";
public static final String fieldAccess = "fieldAccess";
public static final String fieldName = "fieldName";
+ public static final String fieldTypeGroup = "field-type";
public static final String fieldType = "fieldType";
public static final String fieldTypeConstant = "fieldTypeConstant";
public static final String fieldTypePattern = "fieldTypePattern";
@@ -107,6 +114,7 @@
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/KeepTarget;";
public static final String kind = "kind";
+ public static final String constraintsGroup = "constraints";
public static final String constraints = "constraints";
public static final String allow = "allow";
public static final String disallow = "disallow";
@@ -185,6 +193,7 @@
public static final class TypePattern {
public static final String DESCRIPTOR =
"Lcom/android/tools/r8/keepanno/annotations/TypePattern;";
+ public static final String typePatternGroup = "type-pattern";
public static final String name = "name";
public static final String constant = "constant";
public static final String classNamePattern = "classNamePattern";
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
index 910b95a..7a08a6a 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAnnotationParserException.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAnnotationParserException.java
@@ -27,7 +27,11 @@
StringBuilder builder = new StringBuilder();
ParsingContext current = context;
while (current != null) {
- builder.append("\n in ").append(current.getContextFrameAsString());
+ builder
+ .append("\n at ")
+ .append(current.getContextType())
+ .append(": ")
+ .append(current.getContextFrameAsString());
current = current.getParentContext();
}
return builder.toString();
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
index 9998b6a..d732c65 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/ParsingContext.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/ParsingContext.java
@@ -27,8 +27,14 @@
return null;
}
+ public abstract String getContextType();
+
public abstract String getContextFrameAsString();
+ public GroupParsingContext group(String propertyGroupDescription) {
+ return new GroupParsingContext(this, propertyGroupDescription);
+ }
+
public static class ClassParsingContext extends ParsingContext {
private final String className;
@@ -42,6 +48,11 @@
}
@Override
+ public String getContextType() {
+ return "class";
+ }
+
+ @Override
public String getContextFrameAsString() {
return className;
}
@@ -78,11 +89,15 @@
}
@Override
+ public String getContextType() {
+ return "method";
+ }
+
+ @Override
public String getContextFrameAsString() {
Type methodType = Type.getMethodType(methodDescriptor);
StringBuilder builder = new StringBuilder();
builder
- .append("method ")
.append(getJavaTypeFromDescriptor(methodType.getReturnType().getDescriptor()))
.append(' ')
.append(methodName)
@@ -113,8 +128,13 @@
}
@Override
+ public String getContextType() {
+ return "field";
+ }
+
+ @Override
public String getContextFrameAsString() {
- return "field " + getJavaTypeFromDescriptor(fieldDescriptor) + " " + fieldName;
+ return getJavaTypeFromDescriptor(fieldDescriptor) + " " + fieldName;
}
}
@@ -147,8 +167,53 @@
}
@Override
+ public String getContextType() {
+ return "annotation";
+ }
+
+ @Override
public String getContextFrameAsString() {
return "@" + getSimpleAnnotationName();
}
}
+
+ public static class GroupParsingContext extends ParsingContext {
+ private final ParsingContext parentContext;
+ private final String propertyGroupDescription;
+
+ public GroupParsingContext(ParsingContext parentContext, String propertyGroupDescription) {
+ // We don't want to maintain nested property groups as they are "synthetic" and only the
+ // inner-most group useful for uses in diagnosing an error.
+ if (parentContext instanceof GroupParsingContext) {
+ parentContext = parentContext.getParentContext();
+ }
+ assert !(parentContext instanceof GroupParsingContext);
+ this.parentContext = parentContext;
+ this.propertyGroupDescription = propertyGroupDescription;
+ }
+
+ public String getPropertyGroupDescription() {
+ return propertyGroupDescription;
+ }
+
+ @Override
+ public String getHolderName() {
+ return parentContext.getHolderName();
+ }
+
+ @Override
+ public ParsingContext getParentContext() {
+ return parentContext;
+ }
+
+ @Override
+ public String getContextType() {
+ return "property-group";
+ }
+
+ @Override
+ public String getContextFrameAsString() {
+ return getPropertyGroupDescription();
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepInvalidForApiTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepInvalidForApiTest.java
index 3d70d4c..af2087b 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepInvalidForApiTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepInvalidForApiTest.java
@@ -66,8 +66,9 @@
() -> extractRuleForClass(RefineMemberAccess.class),
allOf(
containsString("Unexpected array"),
- containsString("@KeepForApi"),
- containsString("memberAccess")));
+ containsString("memberAccess"),
+ containsString("at annotation: @KeepForApi"),
+ containsString("at method: void main")));
}
static class RefineMemberAccess {
@@ -84,8 +85,9 @@
() -> extractRuleForClass(RefineMethodName.class),
allOf(
containsString("Unexpected value"),
- containsString("@KeepForApi"),
- containsString("methodName")));
+ containsString("methodName"),
+ containsString("at annotation: @KeepForApi"),
+ containsString("at method: void main")));
}
static class RefineMethodName {
@@ -102,8 +104,9 @@
() -> extractRuleForClass(RefineFieldName.class),
allOf(
containsString("Unexpected value"),
- containsString("@KeepForApi"),
- containsString("fieldName")));
+ containsString("fieldName"),
+ containsString("at annotation: @KeepForApi"),
+ containsString("at method: void main")));
}
static class RefineFieldName {
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepInvalidTargetTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepInvalidTargetTest.java
index 9165d59..fbba2a1 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepInvalidTargetTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepInvalidTargetTest.java
@@ -68,7 +68,8 @@
allOf(
containsString("Multiple properties"),
containsString("className"),
- containsString("classConstant")));
+ containsString("classConstant"),
+ containsString("at property-group: class-name")));
}
static class MultipleClassDeclarations {
@@ -83,7 +84,10 @@
public void testInvalidClassDeclWithBinding() {
assertThrowsWith(
() -> extractRuleForClass(BindingAndClassDeclarations.class),
- allOf(containsString("class binding"), containsString("class patterns")));
+ allOf(
+ containsString("class binding"),
+ containsString("class patterns"),
+ containsString("at property-group: class")));
}
static class BindingAndClassDeclarations {
@@ -99,9 +103,12 @@
assertThrowsWith(
() -> extractRuleForClass(MultipleExtendsDeclarations.class),
allOf(
- containsString("Multiple declarations"),
+ containsString("Multiple properties"),
containsString("extendsClassName"),
- containsString("extendsClassConstant")));
+ containsString("extendsClassConstant"),
+ containsString("at property-group: instance-of"),
+ containsString("at annotation: @UsesReflection"),
+ containsString("at method: void main")));
}
static class MultipleExtendsDeclarations {
@@ -119,7 +126,10 @@
public void testInvalidMemberDecl() {
assertThrowsWith(
() -> extractRuleForClass(MultipleMemberDeclarations.class),
- allOf(containsString("field"), containsString("method")));
+ allOf(
+ containsString("field"),
+ containsString("method"),
+ containsString("at property-group: member")));
}
static class MultipleMemberDeclarations {
@@ -134,7 +144,11 @@
public void testInvalidOptionsDecl() {
assertThrowsWith(
() -> extractRuleForClass(MultipleOptionDeclarations.class),
- allOf(containsString("options"), containsString("allow"), containsString("disallow")));
+ allOf(
+ containsString("Multiple properties"),
+ containsString("allow"),
+ containsString("disallow"),
+ containsString("at property-group: constraints")));
}
static class MultipleOptionDeclarations {
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 312e8bb..3aebdc0 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
@@ -151,10 +151,17 @@
final List<String> footers = new ArrayList<>();
final LinkedHashMap<String, Group> mutuallyExclusiveGroups = new LinkedHashMap<>();
+ boolean mutuallyExclusiveWithOtherGroups = false;
+
private Group(String name) {
this.name = name;
}
+ Group allowMutuallyExclusiveWithOtherGroups() {
+ mutuallyExclusiveWithOtherGroups = true;
+ return this;
+ }
+
Group addMember(GroupMember member) {
members.add(member);
return this;
@@ -199,6 +206,18 @@
}
void generateConstants(Generator generator) {
+ if (mutuallyExclusiveWithOtherGroups || members.size() > 1) {
+ StringBuilder camelCaseName = new StringBuilder();
+ for (int i = 0; i < name.length(); i++) {
+ char c = name.charAt(i);
+ if (c == '-') {
+ c = Character.toUpperCase(name.charAt(++i));
+ }
+ camelCaseName.append(c);
+ }
+ generator.println(
+ "public static final String " + camelCaseName + "Group = " + quote(name) + ";");
+ }
for (GroupMember member : members) {
member.generateConstants(generator);
}
@@ -206,6 +225,7 @@
public void addMutuallyExclusiveGroups(Group... groups) {
for (Group group : groups) {
+ assert mutuallyExclusiveWithOtherGroups || group.mutuallyExclusiveWithOtherGroups;
mutuallyExclusiveGroups.computeIfAbsent(
group.name,
k -> {
@@ -502,6 +522,7 @@
private Group createClassBindingGroup() {
return new Group(CLASS_GROUP)
+ .allowMutuallyExclusiveWithOtherGroups()
.addMember(classFromBinding())
.addDocFooterParagraph("If none are specified the default is to match any class.");
}
@@ -627,6 +648,7 @@
private Group createMemberBindingGroup() {
return new Group("member")
+ .allowMutuallyExclusiveWithOtherGroups()
.addMember(
new GroupMember("memberFromBinding")
.setDocTitle("Define the member pattern in full by a reference to a binding.")
@@ -810,36 +832,49 @@
}
// Member binding properties.
+ Group memberBindingGroup = null;
if (includeMemberBinding) {
- createMemberBindingGroup().generate(this);
+ memberBindingGroup = createMemberBindingGroup();
+ memberBindingGroup.generate(this);
println();
}
// The remaining member properties.
- generateMemberPropertiesNoBinding();
+ internalGenerateMemberPropertiesNoBinding(memberBindingGroup);
+ }
+
+ private Group maybeLink(Group group, Group maybeExclusiveGroup) {
+ if (maybeExclusiveGroup != null) {
+ maybeExclusiveGroup.addMutuallyExclusiveGroups(group);
+ }
+ return group;
}
private void generateMemberPropertiesNoBinding() {
+ internalGenerateMemberPropertiesNoBinding(null);
+ }
+
+ private void internalGenerateMemberPropertiesNoBinding(Group memberBindingGroup) {
// General member properties.
- createMemberAccessGroup().generate(this);
+ maybeLink(createMemberAccessGroup(), memberBindingGroup).generate(this);
println();
// Method properties.
- createMethodAccessGroup().generate(this);
+ maybeLink(createMethodAccessGroup(), memberBindingGroup).generate(this);
println();
- createMethodNameGroup().generate(this);
+ maybeLink(createMethodNameGroup(), memberBindingGroup).generate(this);
println();
- createMethodReturnTypeGroup().generate(this);
+ maybeLink(createMethodReturnTypeGroup(), memberBindingGroup).generate(this);
println();
- createMethodParametersGroup().generate(this);
+ maybeLink(createMethodParametersGroup(), memberBindingGroup).generate(this);
println();
// Field properties.
- createFieldAccessGroup().generate(this);
+ maybeLink(createFieldAccessGroup(), memberBindingGroup).generate(this);
println();
- createFieldNameGroup().generate(this);
+ maybeLink(createFieldNameGroup(), memberBindingGroup).generate(this);
println();
- createFieldTypeGroup().generate(this);
+ maybeLink(createFieldTypeGroup(), memberBindingGroup).generate(this);
}
private void generateTypePattern() {