[KeepAnno] Extend parser to composite definitions.
This makes the "single value" parser the base implementation and
pulls out the interface. The visitor is extended to support
composing parsers.
Bug: b/248408342
Change-Id: I5e068f4d376108e57781336d3e6a01d48466426d
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
new file mode 100644
index 0000000..c1e5655
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassNameParser.java
@@ -0,0 +1,61 @@
+// 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.ClassNameParser.ClassNameProperty;
+import com.android.tools.r8.keepanno.asm.ClassSimpleNameParser.ClassSimpleNameProperty;
+import com.android.tools.r8.keepanno.asm.PackageNameParser.PackageNameProperty;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.ClassNamePattern;
+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.google.common.collect.ImmutableList;
+import java.util.function.Consumer;
+import org.objectweb.asm.AnnotationVisitor;
+
+public class ClassNameParser
+ extends PropertyParserBase<KeepQualifiedClassNamePattern, ClassNameProperty, ClassNameParser> {
+
+ public enum ClassNameProperty {
+ PATTERN
+ }
+
+ @Override
+ public ClassNameParser self() {
+ return this;
+ }
+
+ @Override
+ AnnotationVisitor tryPropertyAnnotation(
+ ClassNameProperty property,
+ String name,
+ String descriptor,
+ Consumer<KeepQualifiedClassNamePattern> setValue) {
+ switch (property) {
+ case PATTERN:
+ {
+ PackageNameParser packageParser =
+ new PackageNameParser()
+ .setProperty(PackageNameProperty.NAME, ClassNamePattern.packageName);
+ ClassSimpleNameParser nameParser =
+ new ClassSimpleNameParser()
+ .setProperty(ClassSimpleNameProperty.NAME, ClassNamePattern.simpleName);
+ return new ParserVisitor(
+ descriptor,
+ ImmutableList.of(packageParser, nameParser),
+ () ->
+ setValue.accept(
+ KeepQualifiedClassNamePattern.builder()
+ .setPackagePattern(
+ packageParser.getValueOrDefault(KeepPackagePattern.any()))
+ .setNamePattern(
+ nameParser.getValueOrDefault(KeepUnqualfiedClassNamePattern.any()))
+ .build()));
+ }
+ default:
+ return null;
+ }
+ }
+}
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
new file mode 100644
index 0000000..17296bc
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassSimpleNameParser.java
@@ -0,0 +1,38 @@
+// 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.ClassSimpleNameParser.ClassSimpleNameProperty;
+import com.android.tools.r8.keepanno.ast.KeepUnqualfiedClassNamePattern;
+import java.util.function.Consumer;
+
+public class ClassSimpleNameParser
+ extends PropertyParserBase<
+ KeepUnqualfiedClassNamePattern, ClassSimpleNameProperty, ClassSimpleNameParser> {
+
+ public enum ClassSimpleNameProperty {
+ NAME
+ }
+
+ @Override
+ public ClassSimpleNameParser self() {
+ return this;
+ }
+
+ @Override
+ public boolean tryProperty(
+ ClassSimpleNameProperty property,
+ String name,
+ Object value,
+ Consumer<KeepUnqualfiedClassNamePattern> setValue) {
+ switch (property) {
+ case NAME:
+ setValue.accept(KeepUnqualfiedClassNamePattern.exact((String) value));
+ return true;
+ default:
+ return false;
+ }
+ }
+}
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 2ba3cbf..4513464 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
@@ -2275,7 +2275,7 @@
setResult(KeepTypePattern.fromDescriptor(p.getExactDescriptor()));
} else {
// TODO(b/248408342): Extend the AST type patterns.
- throw new Unimplemented("Non-exact class patterns are not unimplemented yet");
+ throw new Unimplemented("Non-exact class patterns are not implemented yet");
}
});
}
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
new file mode 100644
index 0000000..adef04f
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/PackageNameParser.java
@@ -0,0 +1,37 @@
+// 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.PackageNameParser.PackageNameProperty;
+import com.android.tools.r8.keepanno.ast.KeepPackagePattern;
+import java.util.function.Consumer;
+
+public class PackageNameParser
+ extends PropertyParserBase<KeepPackagePattern, PackageNameProperty, PackageNameParser> {
+
+ public enum PackageNameProperty {
+ NAME
+ }
+
+ @Override
+ public PackageNameParser self() {
+ return this;
+ }
+
+ @Override
+ public boolean tryProperty(
+ PackageNameProperty property,
+ String name,
+ Object value,
+ Consumer<KeepPackagePattern> setValue) {
+ switch (property) {
+ case NAME:
+ setValue.accept(KeepPackagePattern.exact((String) value));
+ return true;
+ default:
+ return false;
+ }
+ }
+}
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 e95494b..5c8ea6f 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,25 +4,31 @@
package com.android.tools.r8.keepanno.asm;
-import java.util.function.Consumer;
+import java.util.Collections;
+import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
-/** Convert a parser into an annotation visitor. */
-public class ParserVisitor<T, P, S> extends AnnotationVisitorBase {
+/** Convert parser(s) into an annotation visitor. */
+public class ParserVisitor extends AnnotationVisitorBase {
private final String annotationDescriptor;
- private final SingleValuePropertyParser<T, P, S> declaration;
- private final Consumer<T> callback;
+ private final List<PropertyParser<?, ?, ?>> parsers;
+ private final Runnable onVisitEnd;
public ParserVisitor(
- String annotationDescriptor,
- SingleValuePropertyParser<T, P, S> declaration,
- Consumer<T> callback) {
+ String annotationDescriptor, List<PropertyParser<?, ?, ?>> parsers, Runnable onVisitEnd) {
this.annotationDescriptor = annotationDescriptor;
- this.declaration = declaration;
- this.callback = callback;
+ this.parsers = parsers;
+ this.onVisitEnd = onVisitEnd;
}
+ public ParserVisitor(
+ String annotationDescriptor, PropertyParser<?, ?, ?> declaration, Runnable onVisitEnd) {
+ this(annotationDescriptor, Collections.singletonList(declaration), onVisitEnd);
+ }
+
+ private <T> void ignore(T unused) {}
+
@Override
public String getAnnotationName() {
int start = annotationDescriptor.lastIndexOf('/') + 1;
@@ -32,39 +38,49 @@
@Override
public void visit(String name, Object value) {
- if (declaration.tryParse(name, value, unused -> {})) {
- return;
+ for (PropertyParser<?, ?, ?> parser : parsers) {
+ if (parser.tryParse(name, value, this::ignore)) {
+ return;
+ }
}
super.visit(name, value);
}
@Override
public AnnotationVisitor visitArray(String name) {
- AnnotationVisitor visitor = declaration.tryParseArray(name, unused -> {});
- if (visitor != null) {
- return visitor;
+ for (PropertyParser<?, ?, ?> parser : parsers) {
+ AnnotationVisitor visitor = parser.tryParseArray(name, this::ignore);
+ if (visitor != null) {
+ return visitor;
+ }
}
return super.visitArray(name);
}
@Override
public void visitEnum(String name, String descriptor, String value) {
+ for (PropertyParser<?, ?, ?> parser : parsers) {
+ if (parser.tryParseEnum(name, descriptor, value, this::ignore)) {
+ return;
+ }
+ }
super.visitEnum(name, descriptor, value);
}
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
- AnnotationVisitor visitor = declaration.tryParseAnnotation(name, descriptor, unused -> {});
- if (visitor != null) {
- return visitor;
+ for (PropertyParser<?, ?, ?> parser : parsers) {
+ AnnotationVisitor visitor = parser.tryParseAnnotation(name, descriptor, this::ignore);
+ if (visitor != null) {
+ return visitor;
+ }
}
return super.visitAnnotation(name, descriptor);
}
@Override
public void visitEnd() {
- if (declaration.isDeclared()) {
- callback.accept(declaration.getSingleValue());
- }
+ onVisitEnd.run();
+ super.visitEnd();
}
}
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 70160a3..67b181b 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
@@ -4,68 +4,30 @@
package com.android.tools.r8.keepanno.asm;
-import java.util.HashMap;
-import java.util.Map;
import java.util.function.Consumer;
import org.objectweb.asm.AnnotationVisitor;
-public abstract class PropertyParser<T, P, S> {
+public interface PropertyParser<T, P, S> {
- private String kind;
- private final Map<String, P> mapping = new HashMap<>();
+ S self();
- abstract S self();
+ String kind();
- abstract boolean tryProperty(P property, String name, Object value, Consumer<T> setValue);
+ S setProperty(P property, String name);
- abstract AnnotationVisitor tryPropertyArray(P property, String name, Consumer<T> setValue);
+ boolean isDeclared();
- abstract AnnotationVisitor tryPropertyAnnotation(
- P property, String name, String descriptor, Consumer<T> setValue);
-
- String kind() {
- return kind != null ? kind : "";
+ default boolean isDefault() {
+ return !isDeclared();
}
- public S setKind(String kind) {
- this.kind = kind;
- return self();
- }
+ T getValue();
- /** Add property parsing for the given property-name. */
- public S setProperty(P property, String name) {
- P old = mapping.put(name, property);
- if (old != null) {
- throw new IllegalArgumentException("Unexpected attempt to redefine property " + name);
- }
- return self();
- }
+ boolean tryParse(String name, Object value, Consumer<T> setValue);
- /** Parse a property. Returns true if the property-name triggered parsing. */
- public final boolean tryParse(String name, Object value, Consumer<T> setValue) {
- P prop = mapping.get(name);
- if (prop != null) {
- return tryProperty(prop, name, value, setValue);
- }
- return false;
- }
+ boolean tryParseEnum(String name, String descriptor, String value, Consumer<T> setValue);
- /** Parse a property. Returns non-null if the property-name triggered parsing. */
- public final AnnotationVisitor tryParseArray(String name, Consumer<T> setValue) {
- P prop = mapping.get(name);
- if (prop != null) {
- return tryPropertyArray(prop, name, setValue);
- }
- return null;
- }
+ AnnotationVisitor tryParseArray(String name, Consumer<T> setValue);
- /** Parse a property. Returns non-null if the property-name triggered parsing. */
- public final AnnotationVisitor tryParseAnnotation(
- String name, String descriptor, Consumer<T> setValue) {
- P prop = mapping.get(name);
- if (prop != null) {
- return tryPropertyAnnotation(prop, name, descriptor, setValue);
- }
- return null;
- }
+ AnnotationVisitor tryParseAnnotation(String name, String descriptor, 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
new file mode 100644
index 0000000..027b6c2
--- /dev/null
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/PropertyParserBase.java
@@ -0,0 +1,141 @@
+// 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.KeepEdgeException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+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> {
+
+ private String kind;
+ private final Map<String, P> mapping = new HashMap<>();
+ private String resultPropertyName = null;
+ private T resultValue = null;
+
+ boolean tryProperty(P property, String name, Object value, Consumer<T> setValue) {
+ return false;
+ }
+
+ public boolean tryPropertyEnum(
+ P property, String name, String descriptor, String value, Consumer<T> setValue) {
+ return false;
+ }
+
+ AnnotationVisitor tryPropertyArray(P property, String name, Consumer<T> setValue) {
+ return null;
+ }
+
+ AnnotationVisitor tryPropertyAnnotation(
+ P property, String name, String descriptor, Consumer<T> setValue) {
+ return null;
+ }
+
+ private Consumer<T> wrap(String propertyName, Consumer<T> setValue) {
+ return value -> {
+ assert value != null;
+ if (resultPropertyName != null) {
+ assert resultValue != null;
+ error(propertyName);
+ } else {
+ resultPropertyName = propertyName;
+ resultValue = value;
+ setValue.accept(value);
+ }
+ };
+ }
+
+ private void error(String name) {
+ throw new KeepEdgeException(
+ "Multiple properties defining "
+ + kind()
+ + ": '"
+ + resultPropertyName
+ + "' and '"
+ + name
+ + "'");
+ }
+
+ public final boolean isDeclared() {
+ assert (resultPropertyName != null) == (resultValue != null);
+ return resultPropertyName != null;
+ }
+
+ public T getValue() {
+ assert (resultPropertyName != null) == (resultValue != null);
+ return resultValue;
+ }
+
+ public T getValueOrDefault(T defaultValue) {
+ assert (resultPropertyName != null) == (resultValue != null);
+ 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) {
+ this.kind = kind;
+ return self();
+ }
+
+ /** Add property parsing for the given property-name. */
+ public S setProperty(P property, String name) {
+ 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) {
+ P prop = mapping.get(name);
+ if (prop != null) {
+ return tryProperty(prop, name, value, wrap(name, setValue));
+ }
+ return false;
+ }
+
+ @Override
+ public final boolean tryParseEnum(
+ String name, String descriptor, String value, Consumer<T> setValue) {
+ P prop = mapping.get(name);
+ if (prop != null) {
+ return tryPropertyEnum(prop, name, descriptor, value, wrap(name, setValue));
+ }
+ return false;
+ }
+
+ @Override
+ public final AnnotationVisitor tryParseArray(String name, Consumer<T> setValue) {
+ P prop = mapping.get(name);
+ if (prop != null) {
+ return tryPropertyArray(prop, name, wrap(name, setValue));
+ }
+ return null;
+ }
+
+ @Override
+ public final AnnotationVisitor tryParseAnnotation(
+ String name, String descriptor, Consumer<T> setValue) {
+ P prop = mapping.get(name);
+ if (prop != null) {
+ return tryPropertyAnnotation(prop, name, descriptor, wrap(name, setValue));
+ }
+ return null;
+ }
+}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/SingleValuePropertyParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/SingleValuePropertyParser.java
deleted file mode 100644
index dcb8088..0000000
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/SingleValuePropertyParser.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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.KeepEdgeException;
-import java.util.function.Consumer;
-import org.objectweb.asm.AnnotationVisitor;
-
-/** Special case of a property parser allowing only a single value callback. */
-public abstract class SingleValuePropertyParser<T, P, S> extends PropertyParser<T, P, S> {
-
- private String resultPropertyName = null;
- private T resultValue = null;
-
- abstract boolean trySingleProperty(P property, String name, Object value, Consumer<T> setValue);
-
- abstract AnnotationVisitor trySinglePropertyArray(P property, String name, Consumer<T> setValue);
-
- abstract AnnotationVisitor trySinglePropertyAnnotation(
- P property, String name, String descriptor, Consumer<T> setValue);
-
- private Consumer<T> wrap(String propertyName, Consumer<T> setValue) {
- return value -> {
- assert value != null;
- if (resultPropertyName != null) {
- assert resultValue != null;
- error(propertyName);
- } else {
- resultPropertyName = propertyName;
- resultValue = value;
- setValue.accept(value);
- }
- };
- }
-
- private void error(String name) {
- throw new KeepEdgeException(
- "Multiple properties defining "
- + kind()
- + ": '"
- + resultPropertyName
- + "' and '"
- + name
- + "'");
- }
-
- public final boolean isDeclared() {
- assert (resultPropertyName != null) == (resultValue != null);
- return resultPropertyName != null;
- }
-
- public T getSingleValue() {
- assert (resultPropertyName != null) == (resultValue != null);
- return resultValue;
- }
-
- /** 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;
- }
-
- @Override
- final boolean tryProperty(P property, String name, Object value, Consumer<T> setValue) {
- return trySingleProperty(property, name, value, wrap(name, setValue));
- }
-
- @Override
- final AnnotationVisitor tryPropertyArray(P property, String name, Consumer<T> setValue) {
- return trySinglePropertyArray(property, name, wrap(name, setValue));
- }
-
- @Override
- final AnnotationVisitor tryPropertyAnnotation(
- P property, String name, String descriptor, Consumer<T> setValue) {
- return trySinglePropertyAnnotation(property, name, descriptor, wrap(name, setValue));
- }
-}
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 dd9b475..f9c6739 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
@@ -4,7 +4,8 @@
package com.android.tools.r8.keepanno.asm;
-import com.android.tools.r8.keepanno.asm.TypeParser.Properties;
+import com.android.tools.r8.keepanno.asm.ClassNameParser.ClassNameProperty;
+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.utils.Unimplemented;
@@ -12,9 +13,9 @@
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Type;
-public class TypeParser extends SingleValuePropertyParser<KeepTypePattern, Properties, TypeParser> {
+public class TypeParser extends PropertyParserBase<KeepTypePattern, TypeProperty, TypeParser> {
- public enum Properties {
+ public enum TypeProperty {
SELF_PATTERN,
TYPE_NAME,
TYPE_CONSTANT,
@@ -22,29 +23,29 @@
}
public TypeParser enableTypePattern(String propertyName) {
- return setProperty(Properties.SELF_PATTERN, propertyName);
+ return setProperty(TypeProperty.SELF_PATTERN, propertyName);
}
public TypeParser enableTypeName(String propertyName) {
- return setProperty(Properties.TYPE_NAME, propertyName);
+ return setProperty(TypeProperty.TYPE_NAME, propertyName);
}
public TypeParser enableTypeConstant(String propertyName) {
- return setProperty(Properties.TYPE_CONSTANT, propertyName);
+ return setProperty(TypeProperty.TYPE_CONSTANT, propertyName);
}
public TypeParser enableTypeClassNamePattern(String propertyName) {
- return setProperty(Properties.CLASS_NAME_PATTERN, propertyName);
+ return setProperty(TypeProperty.CLASS_NAME_PATTERN, propertyName);
}
@Override
- TypeParser self() {
+ public TypeParser self() {
return this;
}
@Override
- public boolean trySingleProperty(
- Properties property, String name, Object value, Consumer<KeepTypePattern> setValue) {
+ public boolean tryProperty(
+ TypeProperty property, String name, Object value, Consumer<KeepTypePattern> setValue) {
switch (property) {
case TYPE_NAME:
setValue.accept(KeepEdgeReaderUtils.typePatternFromString((String) value));
@@ -58,26 +59,36 @@
}
@Override
- public AnnotationVisitor trySinglePropertyArray(
- Properties property, String name, Consumer<KeepTypePattern> setValue) {
- return null;
- }
-
- @Override
- public AnnotationVisitor trySinglePropertyAnnotation(
- Properties property, String name, String descriptor, Consumer<KeepTypePattern> setValue) {
+ public AnnotationVisitor tryPropertyAnnotation(
+ TypeProperty property, String name, String descriptor, Consumer<KeepTypePattern> setValue) {
switch (property) {
case SELF_PATTERN:
- return new ParserVisitor<>(
- descriptor,
+ TypeParser typeParser =
new TypeParser()
.setKind(kind())
.enableTypeName(TypePattern.name)
.enableTypeConstant(TypePattern.constant)
- .enableTypeClassNamePattern(TypePattern.classNamePattern),
- setValue);
+ .enableTypeClassNamePattern(TypePattern.classNamePattern);
+ return new ParserVisitor(
+ descriptor,
+ typeParser,
+ () -> setValue.accept(typeParser.getValueOrDefault(KeepTypePattern.any())));
case CLASS_NAME_PATTERN:
- throw new Unimplemented("Non-exact class patterns are not unimplemented yet");
+ 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");
+ }
+ });
default:
return null;
}