[KeepAnno] Parser for arrays of values
This CL also removes the CRTP idiom as it does not work well with
composing by delegation.
Bug: b/248408342
Change-Id: I76cd79961bee14c0f90b1b20bfba551e6c2c1231
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ArrayPropertyParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ArrayPropertyParser.java
new file mode 100644
index 0000000..3c6cd08
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ArrayPropertyParser.java
@@ -0,0 +1,76 @@
+// 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.asm;
+
+import com.android.tools.r8.keepanno.ast.ParsingContext;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import org.objectweb.asm.AnnotationVisitor;
+
+public class ArrayPropertyParser<T, P> extends PropertyParserBase<List<T>, P> {
+
+ private final Function<ParsingContext, PropertyParser<T, P>> elementParser;
+ private List<T> values;
+
+ public ArrayPropertyParser(
+ ParsingContext parsingContext, Function<ParsingContext, PropertyParser<T, P>> elementParser) {
+ super(parsingContext);
+ this.elementParser = elementParser;
+ }
+
+ @Override
+ AnnotationVisitor tryPropertyArray(P property, String name, Consumer<List<T>> setValue) {
+ // The property name and type is forwarded to the element parser.
+ values = new ArrayList<>();
+ ParsingContext parsingContext = getParsingContext();
+ return new AnnotationVisitorBase(parsingContext) {
+
+ private PropertyParser<T, P> getParser() {
+ PropertyParser<T, P> parser = elementParser.apply(parsingContext);
+ getMapping().forEach(parser::setProperty);
+ return parser;
+ }
+
+ @Override
+ public void visitEnd() {
+ setValue.accept(values);
+ }
+
+ @Override
+ public void visit(String unusedName, Object value) {
+ if (!getParser().tryParse(name, value, values::add)) {
+ super.visit(name, value);
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String unusedName, String descriptor) {
+ AnnotationVisitor visitor = getParser().tryParseAnnotation(name, descriptor, values::add);
+ if (visitor != null) {
+ return visitor;
+ }
+ return super.visitAnnotation(name, descriptor);
+ }
+
+ @Override
+ public void visitEnum(String unusedName, String descriptor, String value) {
+ if (!getParser().tryParseEnum(name, descriptor, value, values::add)) {
+ super.visitEnum(name, descriptor, value);
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String unusedName) {
+ AnnotationVisitor visitor = getParser().tryParseArray(name, values::add);
+ if (visitor != null) {
+ return visitor;
+ }
+ return super.visitArray(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 d6c41ac..6712bfe 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
@@ -18,7 +18,7 @@
import org.objectweb.asm.AnnotationVisitor;
public class ClassNameParser
- extends PropertyParserBase<KeepQualifiedClassNamePattern, ClassNameProperty, ClassNameParser> {
+ extends PropertyParserBase<KeepQualifiedClassNamePattern, ClassNameProperty> {
public ClassNameParser(ParsingContext parsingContext) {
super(parsingContext);
@@ -29,11 +29,6 @@
}
@Override
- public ClassNameParser self() {
- return this;
- }
-
- @Override
AnnotationVisitor tryPropertyAnnotation(
ClassNameProperty property,
String name,
@@ -44,12 +39,10 @@
{
AnnotationParsingContext parsingContext =
new AnnotationParsingContext(getParsingContext(), descriptor);
- PackageNameParser packageParser =
- new PackageNameParser(parsingContext)
- .setProperty(PackageNameProperty.NAME, ClassNamePattern.packageName);
- ClassSimpleNameParser nameParser =
- new ClassSimpleNameParser(parsingContext)
- .setProperty(ClassSimpleNameProperty.NAME, ClassNamePattern.simpleName);
+ PackageNameParser packageParser = new PackageNameParser(parsingContext);
+ ClassSimpleNameParser nameParser = new ClassSimpleNameParser(parsingContext);
+ packageParser.setProperty(ClassNamePattern.packageName, PackageNameProperty.NAME);
+ nameParser.setProperty(ClassNamePattern.simpleName, ClassSimpleNameProperty.NAME);
return new ParserVisitor(
parsingContext,
descriptor,
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 d349898..ed46972 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
@@ -10,8 +10,7 @@
import java.util.function.Consumer;
public class ClassSimpleNameParser
- extends PropertyParserBase<
- KeepUnqualfiedClassNamePattern, ClassSimpleNameProperty, ClassSimpleNameParser> {
+ extends PropertyParserBase<KeepUnqualfiedClassNamePattern, ClassSimpleNameProperty> {
public ClassSimpleNameParser(ParsingContext parsingContext) {
super(parsingContext);
@@ -22,11 +21,6 @@
}
@Override
- public ClassSimpleNameParser self() {
- return this;
- }
-
- @Override
public boolean tryProperty(
ClassSimpleNameProperty property,
String name,
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
new file mode 100644
index 0000000..3be9c92
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ConvertingPropertyParser.java
@@ -0,0 +1,72 @@
+// 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.asm;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+import org.objectweb.asm.AnnotationVisitor;
+
+/**
+ * Abstract base parser to help converting a parser of one type to another via delegation.
+ *
+ * @param <T1> Type of input parser.
+ * @param <T2> Type of output parser (e.g., the parser subclassing this base).
+ * @param <P> Properties (same for both parsers).
+ */
+public abstract class ConvertingPropertyParser<T1, T2, P> implements PropertyParser<T2, P> {
+
+ private final PropertyParser<T1, P> parser;
+ private final Function<T1, T2> converter;
+
+ public ConvertingPropertyParser(PropertyParser<T1, P> parser, Function<T1, T2> converter) {
+ this.parser = parser;
+ this.converter = converter;
+ }
+
+ private Consumer<T1> wrap(Consumer<T2> fn) {
+ return v1 -> fn.accept(converter.apply(v1));
+ }
+
+ @Override
+ public String kind() {
+ return parser.kind();
+ }
+
+ @Override
+ public void setProperty(String name, P property) {
+ parser.setProperty(name, property);
+ }
+
+ @Override
+ public boolean isDeclared() {
+ return parser.isDeclared();
+ }
+
+ @Override
+ public T2 getValue() {
+ return converter.apply(parser.getValue());
+ }
+
+ @Override
+ public T2 tryParse(String name, Object value) {
+ return converter.apply(parser.tryParse(name, value));
+ }
+
+ @Override
+ public boolean tryParseEnum(String name, String descriptor, String value, Consumer<T2> setValue) {
+ return parser.tryParseEnum(name, descriptor, value, wrap(setValue));
+ }
+
+ @Override
+ public AnnotationVisitor tryParseArray(String name, Consumer<T2> setValue) {
+ return parser.tryParseArray(name, wrap(setValue));
+ }
+
+ @Override
+ public AnnotationVisitor tryParseAnnotation(
+ String name, String descriptor, Consumer<T2> setValue) {
+ return parser.tryParseAnnotation(name, descriptor, wrap(setValue));
+ }
+}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/FieldTypeParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/FieldTypeParser.java
new file mode 100644
index 0000000..176b1cd
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/FieldTypeParser.java
@@ -0,0 +1,18 @@
+// 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.asm;
+
+import com.android.tools.r8.keepanno.asm.TypeParser.TypeProperty;
+import com.android.tools.r8.keepanno.ast.KeepFieldTypePattern;
+import com.android.tools.r8.keepanno.ast.KeepTypePattern;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
+
+public class FieldTypeParser
+ extends ConvertingPropertyParser<KeepTypePattern, KeepFieldTypePattern, TypeProperty> {
+
+ public FieldTypeParser(ParsingContext parsingContext) {
+ super(new TypeParser(parsingContext), KeepFieldTypePattern::fromType);
+ }
+}
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 00729cb..b49d399 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
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.asm;
+import com.android.tools.r8.keepanno.asm.TypeParser.TypeProperty;
import com.android.tools.r8.keepanno.ast.AccessVisibility;
import com.android.tools.r8.keepanno.ast.AnnotationConstants;
import com.android.tools.r8.keepanno.ast.AnnotationConstants.Binding;
@@ -18,7 +19,6 @@
import com.android.tools.r8.keepanno.ast.AnnotationConstants.MethodAccess;
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.TypePattern;
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;
@@ -62,7 +62,6 @@
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;
import java.util.Collection;
@@ -1533,21 +1532,19 @@
private static class MethodReturnTypeDeclaration
extends SingleDeclaration<KeepMethodReturnTypePattern> {
- private final TypeParser typeParser;
+ private final MethodReturnTypeParser typeParser;
private MethodReturnTypeDeclaration(ParsingContext parsingContext) {
super(parsingContext);
- typeParser =
- new TypeParser(parsingContext)
- .setKind("return type")
- .enableTypePattern(Item.methodReturnTypePattern)
- .enableTypeName(Item.methodReturnType)
- .enableTypeConstant(Item.methodReturnTypeConstant);
+ typeParser = new MethodReturnTypeParser(parsingContext);
+ typeParser.setProperty(Item.methodReturnType, TypeProperty.TYPE_NAME);
+ typeParser.setProperty(Item.methodReturnTypeConstant, TypeProperty.TYPE_CONSTANT);
+ typeParser.setProperty(Item.methodReturnTypePattern, TypeProperty.TYPE_PATTERN);
}
@Override
String kind() {
- return "return type";
+ return typeParser.kind();
}
@Override
@@ -1555,54 +1552,33 @@
return KeepMethodReturnTypePattern.any();
}
- KeepMethodReturnTypePattern fromType(KeepTypePattern typePattern) {
- if (typePattern == null) {
- return null;
- }
- // Special-case method return types to allow void.
- String descriptor = typePattern.getDescriptor();
- if (descriptor.equals("V") || descriptor.equals("Lvoid;")) {
- return KeepMethodReturnTypePattern.voidType();
- }
- return KeepMethodReturnTypePattern.fromType(typePattern);
- }
-
@Override
public KeepMethodReturnTypePattern parse(String name, Object value) {
- return fromType(typeParser.tryParse(name, value));
+ return typeParser.tryParse(name, value);
}
@Override
public AnnotationVisitor parseAnnotation(
String name, String descriptor, Consumer<KeepMethodReturnTypePattern> setValue) {
- return typeParser.tryParseAnnotation(name, descriptor, t -> setValue.accept(fromType(t)));
+ return typeParser.tryParseAnnotation(name, descriptor, setValue);
}
}
private static class MethodParametersDeclaration
extends SingleDeclaration<KeepMethodParametersPattern> {
- private final ParsingContext parsingContext;
- private KeepMethodParametersPattern pattern = null;
+ private final MethodParametersParser parser;
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 parsingContext.error("Cannot declare multiple patterns for the parameter list");
- }
- setValue.accept(pattern);
- this.pattern = pattern;
+ parser = new MethodParametersParser(parsingContext);
+ parser.setProperty(Item.methodParameters, TypeProperty.TYPE_NAME);
+ parser.setProperty(Item.methodParameterTypePatterns, TypeProperty.TYPE_PATTERN);
}
@Override
String kind() {
- return "parameters";
+ return parser.kind();
}
@Override
@@ -1617,29 +1593,7 @@
@Override
AnnotationVisitor parseArray(String name, Consumer<KeepMethodParametersPattern> setValue) {
- if (name.equals(Item.methodParameters)) {
- return new StringArrayVisitor(
- getParsingContext(),
- params -> {
- KeepMethodParametersPattern.Builder builder = KeepMethodParametersPattern.builder();
- for (String param : params) {
- builder.addParameterTypePattern(KeepEdgeReaderUtils.typePatternFromString(param));
- }
- setPattern(builder.build(), setValue);
- });
- }
- if (name.equals(Item.methodParameterTypePatterns)) {
- return new TypePatternsArrayVisitor(
- getParsingContext(),
- params -> {
- KeepMethodParametersPattern.Builder builder = KeepMethodParametersPattern.builder();
- for (KeepTypePattern param : params) {
- builder.addParameterTypePattern(param);
- }
- setPattern(builder.build(), setValue);
- });
- }
- return super.parseArray(name, setValue);
+ return parser.tryParseArray(name, setValue);
}
}
@@ -1717,16 +1671,14 @@
private static class FieldTypeDeclaration extends SingleDeclaration<KeepFieldTypePattern> {
- private final TypeParser typeParser;
+ private final FieldTypeParser typeParser;
private FieldTypeDeclaration(ParsingContext parsingContext) {
super(parsingContext);
- this.typeParser =
- new TypeParser(parsingContext)
- .setKind("field type")
- .enableTypePattern(Item.fieldTypePattern)
- .enableTypeName(Item.fieldType)
- .enableTypeConstant(Item.fieldTypeConstant);
+ typeParser = new FieldTypeParser(parsingContext);
+ typeParser.setProperty(Item.fieldTypePattern, TypeProperty.TYPE_PATTERN);
+ typeParser.setProperty(Item.fieldType, TypeProperty.TYPE_NAME);
+ typeParser.setProperty(Item.fieldTypeConstant, TypeProperty.TYPE_CONSTANT);
}
@Override
@@ -1741,18 +1693,13 @@
@Override
public KeepFieldTypePattern parse(String name, Object value) {
- KeepTypePattern typePattern = typeParser.tryParse(name, value);
- if (typePattern != null) {
- return KeepFieldTypePattern.fromType(typePattern);
- }
- return null;
+ return typeParser.tryParse(name, value);
}
@Override
public AnnotationVisitor parseAnnotation(
String name, String descriptor, Consumer<KeepFieldTypePattern> setValue) {
- return typeParser.tryParseAnnotation(
- name, descriptor, t -> setValue.accept(KeepFieldTypePattern.fromType(t)));
+ return typeParser.tryParseAnnotation(name, descriptor, setValue);
}
}
@@ -2314,89 +2261,6 @@
}
}
- private static class TypePatternVisitor extends AnnotationVisitorBase {
- private final ParsingContext parsingContext;
- private final Consumer<KeepTypePattern> consumer;
- private KeepTypePattern result = null;
-
- private TypePatternVisitor(ParsingContext parsingContext, Consumer<KeepTypePattern> consumer) {
- super(parsingContext);
- this.parsingContext = parsingContext;
- this.consumer = consumer;
- }
-
- private void setResult(KeepTypePattern result) {
- if (this.result != null) {
- throw parsingContext.error("Invalid type annotation defining multiple properties.");
- }
- this.result = result;
- }
-
- @Override
- public void visit(String name, Object value) {
- if (TypePattern.name.equals(name) && value instanceof String) {
- setResult(KeepEdgeReaderUtils.typePatternFromString((String) value));
- return;
- }
- if (TypePattern.constant.equals(name) && value instanceof Type) {
- Type type = (Type) value;
- setResult(KeepTypePattern.fromDescriptor(type.getDescriptor()));
- return;
- }
- super.visit(name, value);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String name, String descriptor) {
- 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()));
- } else {
- // TODO(b/248408342): Extend the AST type patterns.
- throw new Unimplemented("Non-exact class patterns are not implemented yet");
- }
- });
- }
- return super.visitAnnotation(name, descriptor);
- }
-
- @Override
- public void visitEnd() {
- consumer.accept(result != null ? result : KeepTypePattern.any());
- }
- }
-
- private static class TypePatternsArrayVisitor extends AnnotationVisitorBase {
- private final ParsingContext parsingContext;
- private final Consumer<List<KeepTypePattern>> fn;
- private final List<KeepTypePattern> patterns = new ArrayList<>();
-
- public TypePatternsArrayVisitor(
- ParsingContext parsingContext, Consumer<List<KeepTypePattern>> fn) {
- super(parsingContext);
- this.parsingContext = parsingContext;
- this.fn = fn;
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String unusedName, String descriptor) {
- if (TypePattern.DESCRIPTOR.equals(descriptor)) {
- return new TypePatternVisitor(parsingContext, patterns::add);
- }
- return null;
- }
-
- @Override
- public void visitEnd() {
- super.visitEnd();
- fn.accept(patterns);
- }
- }
-
private static class OptionsDeclaration extends SingleDeclaration<KeepOptions> {
public OptionsDeclaration(ParsingContext parsingContext) {
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/MethodParametersParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/MethodParametersParser.java
new file mode 100644
index 0000000..f1cba56
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/MethodParametersParser.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.asm;
+
+import com.android.tools.r8.keepanno.asm.TypeParser.TypeProperty;
+import com.android.tools.r8.keepanno.ast.KeepMethodParametersPattern;
+import com.android.tools.r8.keepanno.ast.KeepTypePattern;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
+import java.util.List;
+
+public class MethodParametersParser
+ extends ConvertingPropertyParser<
+ List<KeepTypePattern>, KeepMethodParametersPattern, TypeProperty> {
+
+ public MethodParametersParser(ParsingContext parsingContext) {
+ super(
+ new ArrayPropertyParser<>(parsingContext, TypeParser::new),
+ MethodParametersParser::convert);
+ }
+
+ private static KeepMethodParametersPattern convert(List<KeepTypePattern> params) {
+ KeepMethodParametersPattern.Builder builder = KeepMethodParametersPattern.builder();
+ for (KeepTypePattern param : params) {
+ builder.addParameterTypePattern(param);
+ }
+ return builder.build();
+ }
+}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/MethodReturnTypeParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/MethodReturnTypeParser.java
new file mode 100644
index 0000000..8a87a70
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/MethodReturnTypeParser.java
@@ -0,0 +1,33 @@
+// 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.asm;
+
+import com.android.tools.r8.keepanno.asm.TypeParser.TypeProperty;
+import com.android.tools.r8.keepanno.ast.KeepMethodReturnTypePattern;
+import com.android.tools.r8.keepanno.ast.KeepTypePattern;
+import com.android.tools.r8.keepanno.ast.ParsingContext;
+
+public class MethodReturnTypeParser
+ extends ConvertingPropertyParser<KeepTypePattern, KeepMethodReturnTypePattern, TypeProperty> {
+
+ public MethodReturnTypeParser(ParsingContext parsingContext) {
+ super(new TypeParser(parsingContext), MethodReturnTypeParser::fromType);
+ }
+
+ // TODO(b/248408342): It may be problematic dealing with the "void" value at the point of return
+ // as it is not actually a type in the normal sense. Consider a set up where the "void" cases are
+ // special cased before dispatch to the underlying type parser.
+ private static KeepMethodReturnTypePattern fromType(KeepTypePattern typePattern) {
+ if (typePattern == null) {
+ return null;
+ }
+ // Special-case method return types to allow void.
+ String descriptor = typePattern.getDescriptor();
+ if (descriptor.equals("V") || descriptor.equals("Lvoid;")) {
+ return KeepMethodReturnTypePattern.voidType();
+ }
+ return KeepMethodReturnTypePattern.fromType(typePattern);
+ }
+}
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 dadb8de..9c9295d 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
@@ -9,8 +9,7 @@
import com.android.tools.r8.keepanno.ast.ParsingContext;
import java.util.function.Consumer;
-public class PackageNameParser
- extends PropertyParserBase<KeepPackagePattern, PackageNameProperty, PackageNameParser> {
+public class PackageNameParser extends PropertyParserBase<KeepPackagePattern, PackageNameProperty> {
public PackageNameParser(ParsingContext parsingContext) {
super(parsingContext);
@@ -21,11 +20,6 @@
}
@Override
- public PackageNameParser self() {
- return this;
- }
-
- @Override
public boolean tryProperty(
PackageNameProperty property,
String 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 77d6087..5f1f69b 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
@@ -12,13 +12,13 @@
/** Convert parser(s) into an annotation visitor. */
public class ParserVisitor extends AnnotationVisitorBase {
- private final List<PropertyParser<?, ?, ?>> parsers;
+ private final List<PropertyParser<?, ?>> parsers;
private final Runnable onVisitEnd;
public ParserVisitor(
AnnotationParsingContext parsingContext,
String annotationDescriptor,
- List<PropertyParser<?, ?, ?>> parsers,
+ List<PropertyParser<?, ?>> parsers,
Runnable onVisitEnd) {
super(parsingContext);
this.parsers = parsers;
@@ -29,7 +29,7 @@
public ParserVisitor(
AnnotationParsingContext parsingContext,
String annotationDescriptor,
- PropertyParser<?, ?, ?> declaration,
+ PropertyParser<?, ?> declaration,
Runnable onVisitEnd) {
this(parsingContext, annotationDescriptor, Collections.singletonList(declaration), onVisitEnd);
}
@@ -38,7 +38,7 @@
@Override
public void visit(String name, Object value) {
- for (PropertyParser<?, ?, ?> parser : parsers) {
+ for (PropertyParser<?, ?> parser : parsers) {
if (parser.tryParse(name, value, this::ignore)) {
return;
}
@@ -48,7 +48,7 @@
@Override
public AnnotationVisitor visitArray(String name) {
- for (PropertyParser<?, ?, ?> parser : parsers) {
+ for (PropertyParser<?, ?> parser : parsers) {
AnnotationVisitor visitor = parser.tryParseArray(name, this::ignore);
if (visitor != null) {
return visitor;
@@ -59,7 +59,7 @@
@Override
public void visitEnum(String name, String descriptor, String value) {
- for (PropertyParser<?, ?, ?> parser : parsers) {
+ for (PropertyParser<?, ?> parser : parsers) {
if (parser.tryParseEnum(name, descriptor, value, this::ignore)) {
return;
}
@@ -69,7 +69,7 @@
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
- for (PropertyParser<?, ?, ?> parser : parsers) {
+ for (PropertyParser<?, ?> parser : parsers) {
AnnotationVisitor visitor = parser.tryParseAnnotation(name, descriptor, this::ignore);
if (visitor != null) {
return visitor;
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 67b181b..4dc7b38 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
@@ -7,13 +7,11 @@
import java.util.function.Consumer;
import org.objectweb.asm.AnnotationVisitor;
-public interface PropertyParser<T, P, S> {
-
- S self();
+public interface PropertyParser<T, P> {
String kind();
- S setProperty(P property, String name);
+ void setProperty(String name, P property);
boolean isDeclared();
@@ -23,7 +21,16 @@
T getValue();
- boolean tryParse(String name, Object value, Consumer<T> setValue);
+ T tryParse(String name, Object value);
+
+ default boolean tryParse(String name, Object value, Consumer<T> setValue) {
+ T result = tryParse(name, value);
+ if (result != null) {
+ setValue.accept(result);
+ return true;
+ }
+ return false;
+ }
boolean tryParseEnum(String name, String descriptor, String value, Consumer<T> setValue);
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 108f086..0982c9f 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
@@ -12,7 +12,7 @@
import org.objectweb.asm.AnnotationVisitor;
/** Special case of a property parser allowing only a single value callback. */
-public abstract class PropertyParserBase<T, P, S> implements PropertyParser<T, P, S> {
+public abstract class PropertyParserBase<T, P> implements PropertyParser<T, P> {
private final ParsingContext parsingContext;
@@ -29,6 +29,10 @@
return parsingContext;
}
+ Map<String, P> getMapping() {
+ return mapping;
+ }
+
boolean tryProperty(P property, String name, Object value, Consumer<T> setValue) {
return false;
}
@@ -87,38 +91,30 @@
return isDeclared() ? resultValue : defaultValue;
}
- /** Helper for parsing directly. Returns non-null if the property-name triggered parsing. */
- public final T tryParse(String name, Object value) {
- boolean triggered = tryParse(name, value, unused -> {});
- assert triggered == (resultValue != null);
- return resultValue;
- }
-
public String kind() {
return kind != null ? kind : "";
}
- public S setKind(String kind) {
+ public void setKind(String kind) {
this.kind = kind;
- return self();
}
/** Add property parsing for the given property-name. */
- public S setProperty(P property, String name) {
+ public void setProperty(String name, P property) {
P old = mapping.put(name, property);
if (old != null) {
throw new IllegalArgumentException("Unexpected attempt to redefine property " + name);
}
- return self();
}
@Override
- public final boolean tryParse(String name, Object value, Consumer<T> setValue) {
+ public final T tryParse(String name, Object value) {
P prop = mapping.get(name);
if (prop != null) {
- return tryProperty(prop, name, value, wrap(name, setValue));
+ tryProperty(prop, name, value, wrap(name, unused -> {}));
+ return resultValue;
}
- return false;
+ return null;
}
@Override
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 6b11f70..e3922c6 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
@@ -15,40 +15,19 @@
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Type;
-public class TypeParser extends PropertyParserBase<KeepTypePattern, TypeProperty, TypeParser> {
+public class TypeParser extends PropertyParserBase<KeepTypePattern, TypeProperty> {
public TypeParser(ParsingContext parsingContext) {
super(parsingContext);
}
public enum TypeProperty {
- SELF_PATTERN,
+ TYPE_PATTERN,
TYPE_NAME,
TYPE_CONSTANT,
CLASS_NAME_PATTERN
}
- public TypeParser enableTypePattern(String propertyName) {
- return setProperty(TypeProperty.SELF_PATTERN, propertyName);
- }
-
- public TypeParser enableTypeName(String propertyName) {
- return setProperty(TypeProperty.TYPE_NAME, propertyName);
- }
-
- public TypeParser enableTypeConstant(String propertyName) {
- return setProperty(TypeProperty.TYPE_CONSTANT, propertyName);
- }
-
- public TypeParser enableTypeClassNamePattern(String propertyName) {
- return setProperty(TypeProperty.CLASS_NAME_PATTERN, propertyName);
- }
-
- @Override
- public TypeParser self() {
- return this;
- }
-
@Override
public boolean tryProperty(
TypeProperty property, String name, Object value, Consumer<KeepTypePattern> setValue) {
@@ -68,16 +47,15 @@
public AnnotationVisitor tryPropertyAnnotation(
TypeProperty property, String name, String descriptor, Consumer<KeepTypePattern> setValue) {
switch (property) {
- case SELF_PATTERN:
+ case TYPE_PATTERN:
{
AnnotationParsingContext parsingContext =
new AnnotationParsingContext(getParsingContext(), descriptor);
- TypeParser typeParser =
- new TypeParser(parsingContext)
- .setKind(kind())
- .enableTypeName(TypePattern.name)
- .enableTypeConstant(TypePattern.constant)
- .enableTypeClassNamePattern(TypePattern.classNamePattern);
+ TypeParser typeParser = new TypeParser(parsingContext);
+ typeParser.setKind(kind());
+ typeParser.setProperty(TypePattern.name, TypeProperty.TYPE_NAME);
+ typeParser.setProperty(TypePattern.constant, TypeProperty.TYPE_CONSTANT);
+ typeParser.setProperty(TypePattern.classNamePattern, TypeProperty.CLASS_NAME_PATTERN);
return new ParserVisitor(
parsingContext,
descriptor,
@@ -86,21 +64,21 @@
}
case CLASS_NAME_PATTERN:
{
- 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");
- }
- });
+ ClassNameParser parser = new ClassNameParser(getParsingContext());
+ parser.setKind(kind());
+ return parser.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;