Add support for chaining ASM visitors for Keep Annotations
The KeepAnno.createClassVisitorForKeepRulesExtraction now has an
overload taking a ClassVisitor to delegate to.
Change-Id: Id432d141b984219f7656afb276d523c2ca512b72
Fixes: b/463772338
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/KeepAnno.java b/src/keepanno/java/com/android/tools/r8/keepanno/KeepAnno.java
index 392abe0..cd7a85e 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/KeepAnno.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/KeepAnno.java
@@ -19,12 +19,28 @@
* code visited.
*
* <p>Each created {@code ClassVisitor} is independent and share no state (except for the {@code
- * consumer} if the same is used for creating multiple {@code ClassVisitors}) and they can be used
- * concurrently visiting different classes. If the same {@code consumer} is used for creating
+ * consumer}. If the same is used for creating multiple {@code ClassVisitors}) and they can be
+ * used concurrently visiting different classes. If the same {@code consumer} is used for creating
* multiple {@code ClassVisitors}, it must be thread safe.
*/
public static ClassVisitor createClassVisitorForKeepRulesExtraction(Consumer<String> consumer) {
+ return createClassVisitorForKeepRulesExtraction(consumer, null);
+ }
+
+ /**
+ * Experimental API to extract keep rules from keep annotations.
+ *
+ * <p>Create a {@code ClassVisitor} to extract keep rules from keep annotations present in the
+ * code visited.
+ *
+ * <p>Each created {@code ClassVisitor} is independent and share no state (except for the {@code
+ * consumer} and {@code classVisitor}). If the same is used for creating multiple {@code
+ * ClassVisitors}) and they can be used concurrently visiting different classes. If the same
+ * {@code consumer} is used for creating multiple {@code ClassVisitors}, it must be thread safe.
+ */
+ public static ClassVisitor createClassVisitorForKeepRulesExtraction(
+ Consumer<String> consumer, ClassVisitor classVisitor) {
KeepRuleExtractor extractor = new KeepRuleExtractor(consumer, getR8Options());
- return KeepEdgeReader.getClassVisitor(extractor::extract);
+ return KeepEdgeReader.getClassVisitor(extractor::extract, classVisitor);
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/AnnotationPatternParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/AnnotationPatternParser.java
index c628528..4af9001 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/AnnotationPatternParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/AnnotationPatternParser.java
@@ -33,7 +33,8 @@
AnnotationProperty property,
String name,
String descriptor,
- Consumer<KeepAnnotationPattern> setValue) {
+ Consumer<KeepAnnotationPattern> setValue,
+ AnnotationVisitor annotationVisitor) {
switch (property) {
case PATTERN:
AnnotationParsingContext parsingContext =
@@ -46,9 +47,10 @@
setValue.accept(
parser.isDeclared()
? parser.getValue()
- : KeepAnnotationPattern.anyWithRuntimeRetention()));
+ : KeepAnnotationPattern.anyWithRuntimeRetention()),
+ annotationVisitor);
default:
- return super.tryPropertyAnnotation(property, name, descriptor, setValue);
+ return super.tryPropertyAnnotation(property, name, descriptor, setValue, annotationVisitor);
}
}
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 87e9e42..08f5a00 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
@@ -12,8 +12,8 @@
private final ParsingContext parsingContext;
- AnnotationVisitorBase(ParsingContext parsingContext) {
- super(KeepEdgeReader.ASM_VERSION);
+ AnnotationVisitorBase(ParsingContext parsingContext, AnnotationVisitor annotationVisitor) {
+ super(KeepEdgeReader.ASM_VERSION, annotationVisitor);
this.parsingContext = parsingContext;
}
@@ -27,11 +27,19 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
+ }
+
+ protected void unhandledValue(String name, Object value) {
throw parsingContext.error("Unexpected value for property " + name + " with value " + value);
}
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ return super.visitAnnotation(name, descriptor);
+ }
+
+ protected AnnotationVisitor unhandledAnnotation(String name, String descriptor) {
throw parsingContext.error(
"Unexpected annotation for property "
+ name
@@ -41,6 +49,10 @@
@Override
public void visitEnum(String name, String descriptor, String value) {
+ super.visitEnum(name, descriptor, value);
+ }
+
+ protected void unhandledEnum(String name, String descriptor, String value) {
throw parsingContext.error(
"Unexpected enum for property "
+ name
@@ -52,6 +64,10 @@
@Override
public AnnotationVisitor visitArray(String name) {
+ return super.visitArray(name);
+ }
+
+ protected AnnotationVisitor unhandledArray(String name) {
throw parsingContext.error("Unexpected array for property " + name);
}
}
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
index 3ae1bd2..55a6c34 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ArrayPropertyParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ArrayPropertyParser.java
@@ -23,12 +23,13 @@
}
@Override
- AnnotationVisitor tryPropertyArray(P property, String name, Consumer<List<T>> setValue) {
+ AnnotationVisitor tryPropertyArray(
+ P property, String name, Consumer<List<T>> setValue, AnnotationVisitor annotationVisitor) {
// The property name and type is forwarded to the element parser.
values = new ArrayList<>();
// The context is explicitly *not* extended with the property name here as it is forwarded.
ParsingContext parsingContext = getParsingContext();
- return new AnnotationVisitorBase(parsingContext) {
+ return new AnnotationVisitorBase(parsingContext, annotationVisitor) {
private PropertyParser<T, P> getParser() {
PropertyParser<T, P> parser = elementParser.apply(parsingContext);
@@ -43,34 +44,39 @@
@Override
public void visit(String unusedName, Object value) {
+ super.visit(unusedName, value);
if (!getParser().tryParse(name, value, values::add)) {
- super.visit(name, value);
+ unhandledValue(unusedName, value);
}
}
@Override
public AnnotationVisitor visitAnnotation(String unusedName, String descriptor) {
- AnnotationVisitor visitor = getParser().tryParseAnnotation(name, descriptor, values::add);
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(unusedName, descriptor);
+ AnnotationVisitor visitor =
+ getParser().tryParseAnnotation(name, descriptor, values::add, annotationVisitor);
if (visitor != null) {
return visitor;
}
- return super.visitAnnotation(name, descriptor);
+ return annotationVisitor;
}
@Override
public void visitEnum(String unusedName, String descriptor, String value) {
+ super.visitEnum(unusedName, descriptor, value);
if (!getParser().tryParseEnum(name, descriptor, value, values::add)) {
- super.visitEnum(name, descriptor, value);
+ unhandledEnum(unusedName, descriptor, value);
}
}
@Override
public AnnotationVisitor visitArray(String unusedName) {
- AnnotationVisitor visitor = getParser().tryParseArray(name, values::add);
+ AnnotationVisitor annotationVisitor = super.visitArray(unusedName);
+ AnnotationVisitor visitor = getParser().tryParseArray(name, values::add, annotationVisitor);
if (visitor != null) {
return visitor;
}
- return super.visitArray(name);
+ return annotationVisitor;
}
};
}
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 81d3598..abd1ae6 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
@@ -80,7 +80,8 @@
ClassNameProperty property,
String name,
String descriptor,
- Consumer<KeepQualifiedClassNamePattern> setValue) {
+ Consumer<KeepQualifiedClassNamePattern> setValue,
+ AnnotationVisitor annotationVisitor) {
switch (property) {
case PATTERN:
{
@@ -121,7 +122,8 @@
unqualifiedNameParser.getValueOrDefault(
KeepUnqualfiedClassNamePattern.any()))
.build());
- });
+ },
+ annotationVisitor);
}
default:
return null;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassUnqualifiedNameParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassUnqualifiedNameParser.java
index 896fea9..695c15c 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassUnqualifiedNameParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ClassUnqualifiedNameParser.java
@@ -50,7 +50,8 @@
ClassUnqualifiedNameProperty property,
String name,
String descriptor,
- Consumer<KeepUnqualfiedClassNamePattern> setValue) {
+ Consumer<KeepUnqualfiedClassNamePattern> setValue,
+ AnnotationVisitor annotationVisitor) {
switch (property) {
case PATTERN:
return parser.tryPropertyAnnotation(
@@ -58,9 +59,10 @@
name,
descriptor,
stringPattern ->
- setValue.accept(KeepUnqualfiedClassNamePattern.fromStringPattern(stringPattern)));
+ setValue.accept(KeepUnqualfiedClassNamePattern.fromStringPattern(stringPattern)),
+ annotationVisitor);
default:
- return super.tryPropertyAnnotation(property, name, descriptor, setValue);
+ return super.tryPropertyAnnotation(property, name, descriptor, setValue, annotationVisitor);
}
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ConstraintPropertiesParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ConstraintPropertiesParser.java
index c652e91..3d9c495 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/ConstraintPropertiesParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/ConstraintPropertiesParser.java
@@ -25,15 +25,19 @@
@Override
AnnotationVisitor tryPropertyArray(
- ConstraintsProperty property, String name, Consumer<KeepConstraints> setValue) {
+ ConstraintsProperty property,
+ String name,
+ Consumer<KeepConstraints> setValue,
+ AnnotationVisitor annotationVisitor) {
ParsingContext parsingContext = getParsingContext().property(name);
switch (property) {
case ADDITIONS:
return new KeepConstraintsVisitor(
parsingContext,
- constraints -> setValue.accept(KeepConstraints.defaultAdditions(constraints)));
+ constraints -> setValue.accept(KeepConstraints.defaultAdditions(constraints)),
+ annotationVisitor);
case CONSTRAINTS:
- return new KeepConstraintsVisitor(parsingContext, setValue::accept);
+ return new KeepConstraintsVisitor(parsingContext, setValue::accept, annotationVisitor);
default:
return null;
}
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 e449c88..cb6f364 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
@@ -55,13 +55,14 @@
}
@Override
- public AnnotationVisitor tryParseArray(String name, Consumer<T2> setValue) {
- return parser.tryParseArray(name, wrap(setValue));
+ public AnnotationVisitor tryParseArray(
+ String name, Consumer<T2> setValue, AnnotationVisitor annotationVisitor) {
+ return parser.tryParseArray(name, wrap(setValue), annotationVisitor);
}
@Override
public AnnotationVisitor tryParseAnnotation(
- String name, String descriptor, Consumer<T2> setValue) {
- return parser.tryParseAnnotation(name, descriptor, wrap(setValue));
+ String name, String descriptor, Consumer<T2> setValue, AnnotationVisitor annotationVisitor) {
+ return parser.tryParseAnnotation(name, descriptor, wrap(setValue), annotationVisitor);
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/DeclarationParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/DeclarationParser.java
index cc9a74d..05e65e1 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/DeclarationParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/DeclarationParser.java
@@ -36,14 +36,15 @@
}
@Override
- public AnnotationVisitor tryParseArray(String name, Consumer<T> setValue) {
- return tryParseArray(name);
+ public AnnotationVisitor tryParseArray(
+ String name, Consumer<T> setValue, AnnotationVisitor annotationVisitor) {
+ return tryParseArray(name, annotationVisitor);
}
@Override
public AnnotationVisitor tryParseAnnotation(
- String name, String descriptor, Consumer<T> setValue) {
- return tryParseAnnotation(name, descriptor);
+ String name, String descriptor, Consumer<T> setValue, AnnotationVisitor annotationVisitor) {
+ return tryParseAnnotation(name, descriptor, annotationVisitor);
}
public boolean tryParse(String name, Object value) {
@@ -64,23 +65,25 @@
return false;
}
- public AnnotationVisitor tryParseArray(String name) {
+ public AnnotationVisitor tryParseArray(String name, AnnotationVisitor annotationVisitor) {
for (Parser<?> parser : parsers()) {
- AnnotationVisitor visitor = parser.tryParseArray(name, this::ignore);
+ AnnotationVisitor visitor = parser.tryParseArray(name, this::ignore, annotationVisitor);
if (visitor != null) {
return visitor;
}
}
- return null;
+ return annotationVisitor;
}
- public AnnotationVisitor tryParseAnnotation(String name, String descriptor) {
+ public AnnotationVisitor tryParseAnnotation(
+ String name, String descriptor, AnnotationVisitor annotationVisitor) {
for (Parser<?> parser : parsers()) {
- AnnotationVisitor visitor = parser.tryParseAnnotation(name, descriptor, this::ignore);
+ AnnotationVisitor visitor =
+ parser.tryParseAnnotation(name, descriptor, this::ignore, annotationVisitor);
if (visitor != null) {
return visitor;
}
}
- return null;
+ return annotationVisitor;
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/InstanceOfParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/InstanceOfParser.java
index 73b4905..7f2308b 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/InstanceOfParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/InstanceOfParser.java
@@ -77,7 +77,8 @@
InstanceOfProperties property,
String name,
String descriptor,
- Consumer<KeepInstanceOfPattern> setValue) {
+ Consumer<KeepInstanceOfPattern> setValue,
+ AnnotationVisitor annotationVisitor) {
if (property.equals(InstanceOfProperties.PATTERN)) {
AnnotationParsingContext parsingContext =
getParsingContext().property(name).annotation(descriptor);
@@ -94,8 +95,9 @@
.setInclusive(inclusiveParser.getValueOrDefault(true))
.classPattern(
classNameParser.getValueOrDefault(KeepQualifiedClassNamePattern.any()))
- .build()));
+ .build()),
+ annotationVisitor);
}
- return super.tryPropertyAnnotation(property, name, descriptor, setValue);
+ return super.tryPropertyAnnotation(property, name, descriptor, setValue, annotationVisitor);
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepConstraintsVisitor.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepConstraintsVisitor.java
index 1df490b..79cf8a8 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepConstraintsVisitor.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepConstraintsVisitor.java
@@ -10,21 +10,27 @@
import com.android.tools.r8.keepanno.ast.KeepConstraint;
import com.android.tools.r8.keepanno.ast.KeepConstraints;
import com.android.tools.r8.keepanno.ast.ParsingContext;
+import org.objectweb.asm.AnnotationVisitor;
public class KeepConstraintsVisitor extends AnnotationVisitorBase {
private final Parent<KeepConstraints> parent;
private final KeepConstraints.Builder builder = KeepConstraints.builder();
- public KeepConstraintsVisitor(ParsingContext parsingContext, Parent<KeepConstraints> parent) {
- super(parsingContext);
+ public KeepConstraintsVisitor(
+ ParsingContext parsingContext,
+ Parent<KeepConstraints> parent,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parent = parent;
}
@Override
public void visitEnum(String ignore, String descriptor, String value) {
+ super.visitEnum(ignore, descriptor, value);
if (!AnnotationConstants.Constraints.isDescriptor(descriptor)) {
- super.visitEnum(ignore, descriptor, value);
+ unhandledEnum(ignore, descriptor, value);
+ return;
}
switch (value) {
case Constraints.LOOKUP:
@@ -71,7 +77,7 @@
builder.add(KeepConstraint.genericSignature());
break;
default:
- super.visitEnum(ignore, descriptor, value);
+ unhandledEnum(ignore, descriptor, value);
}
}
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 edb9cb4..6a4d08c 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
@@ -154,8 +154,9 @@
return internalReadKeepEdges(classFileBytes, true);
}
- public static ClassVisitor getClassVisitor(Parent<KeepDeclaration> consumer) {
- return new KeepEdgeClassVisitor(true, consumer);
+ public static ClassVisitor getClassVisitor(
+ Parent<KeepDeclaration> consumer, ClassVisitor classVisitor) {
+ return new KeepEdgeClassVisitor(true, consumer, classVisitor);
}
private static List<KeepDeclaration> internalReadKeepEdges(
@@ -183,7 +184,8 @@
builder -> {
builder.setContextFromClassDescriptor(
KeepEdgeReaderUtils.getDescriptorFromClassTypeName(className));
- });
+ },
+ null);
}
public static AnnotationVisitor createFieldKeepAnnotationVisitor(
@@ -209,7 +211,8 @@
KeepEdgeReaderUtils.getDescriptorFromClassTypeName(className),
fieldName,
fieldTypeDescriptor);
- });
+ },
+ null);
}
public static AnnotationVisitor createMethodKeepAnnotationVisitor(
@@ -235,7 +238,8 @@
KeepEdgeReaderUtils.getDescriptorFromClassTypeName(className),
methodName,
methodDescriptor);
- });
+ },
+ null);
}
private static KeepClassBindingReference classReferenceFromName(
@@ -331,7 +335,12 @@
private ClassParsingContext parsingContext;
public KeepEdgeClassVisitor(boolean readEmbedded, Parent<KeepDeclaration> parent) {
- super(ASM_VERSION);
+ this(readEmbedded, parent, null);
+ }
+
+ public KeepEdgeClassVisitor(
+ boolean readEmbedded, Parent<KeepDeclaration> parent, ClassVisitor classVisitor) {
+ super(ASM_VERSION, classVisitor);
this.readEmbedded = readEmbedded;
this.parent = parent;
}
@@ -359,6 +368,7 @@
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(descriptor, visible);
return createAnnotationVisitor(
descriptor,
visible,
@@ -366,27 +376,29 @@
parent::accept,
annotationParsingContext(descriptor),
className,
- this::setContext);
+ this::setContext,
+ annotationVisitor);
}
- private static AnnotationVisitorBase createAnnotationVisitor(
+ private static AnnotationVisitor createAnnotationVisitor(
String descriptor,
boolean visible,
boolean readEmbedded,
Consumer<KeepDeclaration> parent,
AnnotationParsingContext parsingContext,
String className,
- Consumer<KeepEdgeMetaInfo.Builder> setContext) {
+ Consumer<KeepEdgeMetaInfo.Builder> setContext,
+ AnnotationVisitor annotationVisitor) {
// Skip any visible annotations as keep annotations are not runtime visible.
if (visible) {
- return null;
+ return annotationVisitor;
}
if (!readEmbedded || !isEmbeddedAnnotation(descriptor)) {
- return null;
+ return annotationVisitor;
}
if (Edge.isDescriptor(descriptor)) {
- return new KeepEdgeVisitor(parsingContext, parent::accept, setContext);
+ return new KeepEdgeVisitor(parsingContext, parent::accept, setContext, annotationVisitor);
}
if (AnnotationConstants.UsesReflection.isDescriptor(descriptor)) {
return new UsesReflectionVisitor(
@@ -396,7 +408,8 @@
bindingsHelper ->
KeepClassItemPattern.builder()
.setClassNamePattern(KeepQualifiedClassNamePattern.exact(className))
- .build());
+ .build(),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToConstruct.isDescriptor(descriptor)) {
return new UsesReflectionToConstructVisitor(
@@ -406,7 +419,8 @@
bindingsHelper ->
KeepClassItemPattern.builder()
.setClassNamePattern(KeepQualifiedClassNamePattern.exact(className))
- .build());
+ .build(),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToConstruct.isKotlinRepeatableContainerDescriptor(
descriptor)) {
@@ -417,7 +431,8 @@
bindingsHelper ->
KeepClassItemPattern.builder()
.setClassNamePattern(KeepQualifiedClassNamePattern.exact(className))
- .build());
+ .build(),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToAccessMethod.isDescriptor(descriptor)) {
return new UsesReflectionToAccessMethodVisitor(
@@ -427,7 +442,8 @@
bindingsHelper ->
KeepClassItemPattern.builder()
.setClassNamePattern(KeepQualifiedClassNamePattern.exact(className))
- .build());
+ .build(),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToAccessMethod.isKotlinRepeatableContainerDescriptor(
descriptor)) {
@@ -438,7 +454,8 @@
bindingsHelper ->
KeepClassItemPattern.builder()
.setClassNamePattern(KeepQualifiedClassNamePattern.exact(className))
- .build());
+ .build(),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToAccessField.isDescriptor(descriptor)) {
return new UsesReflectionToAccessFieldVisitor(
@@ -448,7 +465,8 @@
bindingsHelper ->
KeepClassItemPattern.builder()
.setClassNamePattern(KeepQualifiedClassNamePattern.exact(className))
- .build());
+ .build(),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToAccessField.isKotlinRepeatableContainerDescriptor(
descriptor)) {
@@ -459,29 +477,41 @@
bindingsHelper ->
KeepClassItemPattern.builder()
.setClassNamePattern(KeepQualifiedClassNamePattern.exact(className))
- .build());
+ .build(),
+ annotationVisitor);
}
if (AnnotationConstants.UnconditionallyKeep.isDescriptor(descriptor)) {
return new UnconditionallyKeepClassVisitor(
- parsingContext, parent::accept, setContext, className);
+ parsingContext, parent::accept, setContext, className, annotationVisitor);
}
if (ForApi.isDescriptor(descriptor)) {
- return new ForApiClassVisitor(parsingContext, parent::accept, setContext, className);
+ return new ForApiClassVisitor(
+ parsingContext, parent::accept, setContext, className, annotationVisitor);
}
if (UsedByReflection.isDescriptor(descriptor)
|| AnnotationConstants.UsedByNative.isDescriptor(descriptor)) {
return new UsedByReflectionClassVisitor(
- parsingContext, parent::accept, setContext, className);
+ parsingContext, parent::accept, setContext, className, annotationVisitor);
}
if (AnnotationConstants.CheckRemoved.isDescriptor(descriptor)) {
return new CheckRemovedClassVisitor(
- parsingContext, parent::accept, setContext, className, KeepCheckKind.REMOVED);
+ parsingContext,
+ parent::accept,
+ setContext,
+ className,
+ KeepCheckKind.REMOVED,
+ annotationVisitor);
}
if (AnnotationConstants.CheckOptimizedOut.isDescriptor(descriptor)) {
return new CheckRemovedClassVisitor(
- parsingContext, parent::accept, setContext, className, KeepCheckKind.OPTIMIZED_OUT);
+ parsingContext,
+ parent::accept,
+ setContext,
+ className,
+ KeepCheckKind.OPTIMIZED_OUT,
+ annotationVisitor);
}
- return null;
+ return annotationVisitor;
}
private void setContext(KeepEdgeMetaInfo.Builder builder) {
@@ -492,21 +522,24 @@
@Override
public MethodVisitor visitMethod(
int access, String name, String descriptor, String signature, String[] exceptions) {
+ MethodVisitor methodVisitor =
+ super.visitMethod(access, name, descriptor, signature, exceptions);
if (readEmbedded) {
return new KeepEdgeMethodVisitor(
- parsingContext, parent::accept, className, name, descriptor);
+ parsingContext, parent::accept, className, name, descriptor, methodVisitor);
}
- return null;
+ return methodVisitor;
}
@Override
public FieldVisitor visitField(
int access, String name, String descriptor, String signature, Object value) {
+ FieldVisitor fieldVisitor = super.visitField(access, name, descriptor, signature, value);
if (readEmbedded) {
return new KeepEdgeFieldVisitor(
- parsingContext, parent::accept, className, name, descriptor);
+ parsingContext, parent::accept, className, name, descriptor, fieldVisitor);
}
- return null;
+ return fieldVisitor;
}
}
@@ -522,8 +555,9 @@
Parent<KeepDeclaration> parent,
String className,
String methodName,
- String methodDescriptor) {
- super(ASM_VERSION);
+ String methodDescriptor,
+ MethodVisitor methodVisitor) {
+ super(ASM_VERSION, methodVisitor);
this.parent = parent;
this.className = className;
this.methodName = methodName;
@@ -566,6 +600,7 @@
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(descriptor, visible);
return createAnnotationVisitor(
descriptor,
visible,
@@ -575,7 +610,8 @@
className,
methodName,
methodDescriptor,
- this::setContext);
+ this::setContext,
+ annotationVisitor);
}
public static AnnotationVisitor createAnnotationVisitor(
@@ -587,17 +623,18 @@
String className,
String methodName,
String methodDescriptor,
- Consumer<KeepEdgeMetaInfo.Builder> setContext) {
+ Consumer<KeepEdgeMetaInfo.Builder> setContext,
+ AnnotationVisitor annotationVisitor) {
// Skip any visible annotations as @KeepEdge is not runtime visible.
if (visible) {
- return null;
+ return annotationVisitor;
}
if (!readEmbedded) {
// Only the embedded annotations can be on methods.
- return null;
+ return annotationVisitor;
}
if (Edge.isDescriptor(descriptor)) {
- return new KeepEdgeVisitor(parsingContext, parent::accept, setContext);
+ return new KeepEdgeVisitor(parsingContext, parent::accept, setContext, annotationVisitor);
}
if (AnnotationConstants.UsesReflection.isDescriptor(descriptor)) {
return new UsesReflectionVisitor(
@@ -605,7 +642,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToConstruct.isDescriptor(descriptor)) {
return new UsesReflectionToConstructVisitor(
@@ -613,7 +651,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToConstruct.isKotlinRepeatableContainerDescriptor(
descriptor)) {
@@ -622,7 +661,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToAccessMethod.isDescriptor(descriptor)) {
return new UsesReflectionToAccessMethodVisitor(
@@ -630,7 +670,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToAccessMethod.isKotlinRepeatableContainerDescriptor(
descriptor)) {
@@ -639,7 +680,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToAccessField.isDescriptor(descriptor)) {
return new UsesReflectionToAccessFieldVisitor(
@@ -647,7 +689,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.UsesReflectionToAccessField.isKotlinRepeatableContainerDescriptor(
descriptor)) {
@@ -656,7 +699,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.UnconditionallyKeep.isDescriptor(descriptor)) {
return new UnconditionallyKeepMemberVisitor(
@@ -664,7 +708,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.ForApi.isDescriptor(descriptor)) {
return new ForApiMemberVisitor(
@@ -672,7 +717,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.UsedByReflection.isDescriptor(descriptor)
|| AnnotationConstants.UsedByNative.isDescriptor(descriptor)) {
@@ -681,7 +727,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper));
+ createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.CheckRemoved.isDescriptor(descriptor)) {
return new CheckRemovedMemberVisitor(
@@ -690,7 +737,8 @@
setContext,
bindingsHelper ->
createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
- KeepCheckKind.REMOVED);
+ KeepCheckKind.REMOVED,
+ annotationVisitor);
}
if (AnnotationConstants.CheckOptimizedOut.isDescriptor(descriptor)) {
return new CheckRemovedMemberVisitor(
@@ -699,9 +747,10 @@
setContext,
bindingsHelper ->
createMethodItemContext(className, methodName, methodDescriptor, bindingsHelper),
- KeepCheckKind.OPTIMIZED_OUT);
+ KeepCheckKind.OPTIMIZED_OUT,
+ annotationVisitor);
}
- return null;
+ return annotationVisitor;
}
private void setContext(KeepEdgeMetaInfo.Builder builder) {
@@ -722,8 +771,9 @@
Parent<KeepEdge> parent,
String className,
String fieldName,
- String fieldTypeDescriptor) {
- super(ASM_VERSION);
+ String fieldTypeDescriptor,
+ FieldVisitor fieldVisitor) {
+ super(ASM_VERSION, fieldVisitor);
this.parent = parent;
this.className = className;
this.fieldName = fieldName;
@@ -760,6 +810,7 @@
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(descriptor, visible);
return createAnnotationVisitor(
descriptor,
visible,
@@ -769,7 +820,8 @@
className,
fieldName,
fieldTypeDescriptor,
- this::setContext);
+ this::setContext,
+ annotationVisitor);
}
public static AnnotationVisitor createAnnotationVisitor(
@@ -781,17 +833,18 @@
String className,
String fieldName,
String fieldTypeDescriptor,
- Consumer<KeepEdgeMetaInfo.Builder> setContext) {
+ Consumer<KeepEdgeMetaInfo.Builder> setContext,
+ AnnotationVisitor annotationVisitor) {
// Skip any visible annotations as @KeepEdge is not runtime visible.
if (visible) {
- return null;
+ return annotationVisitor;
}
if (!readEmbedded) {
// Only the embedded annotations can be on fields.
- return null;
+ return annotationVisitor;
}
if (Edge.isDescriptor(descriptor)) {
- return new KeepEdgeVisitor(parsingContext, parent::accept, setContext);
+ return new KeepEdgeVisitor(parsingContext, parent::accept, setContext, annotationVisitor);
}
if (AnnotationConstants.UsesReflection.isDescriptor(descriptor)) {
return new UsesReflectionVisitor(
@@ -799,7 +852,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMemberItemContext(className, fieldName, fieldTypeDescriptor, bindingsHelper));
+ createMemberItemContext(className, fieldName, fieldTypeDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (AnnotationConstants.UnconditionallyKeep.isDescriptor(descriptor)) {
return new UnconditionallyKeepMemberVisitor(
@@ -807,7 +861,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMemberItemContext(className, fieldName, fieldTypeDescriptor, bindingsHelper));
+ createMemberItemContext(className, fieldName, fieldTypeDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (ForApi.isDescriptor(descriptor)) {
return new ForApiMemberVisitor(
@@ -815,7 +870,8 @@
parent::accept,
setContext,
bindingsHelper ->
- createMemberItemContext(className, fieldName, fieldTypeDescriptor, bindingsHelper));
+ createMemberItemContext(className, fieldName, fieldTypeDescriptor, bindingsHelper),
+ annotationVisitor);
}
if (UsedByReflection.isDescriptor(descriptor)
|| AnnotationConstants.UsedByNative.isDescriptor(descriptor)) {
@@ -824,9 +880,10 @@
parent::accept,
setContext,
bindingsHelper ->
- createMemberItemContext(className, fieldName, fieldTypeDescriptor, bindingsHelper));
+ createMemberItemContext(className, fieldName, fieldTypeDescriptor, bindingsHelper),
+ annotationVisitor);
}
- return null;
+ return annotationVisitor;
}
}
@@ -926,8 +983,9 @@
KeepEdgeVisitor(
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
- Consumer<KeepEdgeMetaInfo.Builder> addContext) {
- super(parsingContext);
+ Consumer<KeepEdgeMetaInfo.Builder> addContext,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
addContext.accept(metaInfoBuilder);
@@ -935,28 +993,28 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
- return;
}
- super.visit(name, value);
}
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
PropertyParsingContext propertyParsingContext = parsingContext.property(name);
if (name.equals(Edge.bindings)) {
- return new KeepBindingsVisitor(propertyParsingContext, bindingsHelper);
+ return new KeepBindingsVisitor(propertyParsingContext, bindingsHelper, annotationVisitor);
}
if (name.equals(Edge.preconditions)) {
return new KeepPreconditionsVisitor(
- propertyParsingContext, builder::setPreconditions, bindingsHelper);
+ propertyParsingContext, builder::setPreconditions, bindingsHelper, annotationVisitor);
}
if (name.equals(Edge.consequences)) {
return new KeepConsequencesVisitor(
- propertyParsingContext, builder::setConsequences, bindingsHelper);
+ propertyParsingContext, builder::setConsequences, bindingsHelper, annotationVisitor);
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -987,8 +1045,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- String className) {
- super(parsingContext);
+ String className,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.className = className;
this.parent = parent;
@@ -1006,24 +1065,25 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
- return;
}
- super.visit(name, value);
}
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
if (name.equals(ForApi.additionalTargets)) {
return new KeepConsequencesVisitor(
parsingContext.property(name),
additionalConsequences -> {
additionalConsequences.forEachTarget(consequences::addTarget);
},
- bindingsHelper);
+ bindingsHelper,
+ annotationVisitor);
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -1117,8 +1177,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepMemberItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepMemberItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
addContext.accept(metaInfoBuilder);
@@ -1133,24 +1194,29 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
- return;
+ } else {
+ unhandledValue(name, value);
}
- super.visit(name, value);
}
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
if (name.equals(ForApi.additionalTargets)) {
return new KeepConsequencesVisitor(
parsingContext.property(name),
additionalConsequences -> {
additionalConsequences.forEachTarget(consequences::addTarget);
},
- bindingsHelper);
+ bindingsHelper,
+ annotationVisitor);
+ } else {
+ unhandledArray(name);
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -1161,6 +1227,7 @@
.setBindings(bindingsHelper.build())
.setConsequences(consequences.build())
.build());
+ super.visitEnd();
}
}
@@ -1244,8 +1311,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- String className) {
- super(parsingContext);
+ String className,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.className = className;
this.parent = parent;
@@ -1262,19 +1330,19 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
- return;
}
- super.visit(name, value);
}
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
PropertyParsingContext propertyParsingContext = parsingContext.property(name);
if (name.equals(Edge.preconditions)) {
return new KeepPreconditionsVisitor(
- propertyParsingContext, builder::setPreconditions, bindingsHelper);
+ propertyParsingContext, builder::setPreconditions, bindingsHelper, annotationVisitor);
}
if (name.equals(UsedByReflection.additionalTargets)) {
return new KeepConsequencesVisitor(
@@ -1282,13 +1350,15 @@
additionalConsequences -> {
additionalConsequences.forEachTarget(consequences::addTarget);
},
- bindingsHelper);
+ bindingsHelper,
+ annotationVisitor);
}
- AnnotationVisitor visitor = constraintsParser.tryParseArray(name, unused -> {});
+ AnnotationVisitor visitor =
+ constraintsParser.tryParseArray(name, unused -> {}, annotationVisitor);
if (visitor != null) {
return visitor;
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -1361,8 +1431,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepMemberItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepMemberItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.context = contextBuilder.apply(bindingsHelper);
@@ -1372,32 +1443,34 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
- return;
}
- super.visit(name, value);
}
@Override
public void visitEnum(String name, String descriptor, String value) {
+ super.visitEnum(name, descriptor, value);
if (!Kind.isDescriptor(descriptor)) {
- super.visitEnum(name, descriptor, value);
+ unhandledEnum(name, descriptor, value);
+ return;
}
KeepEdgeReader.ItemKind kind = KeepEdgeReader.ItemKind.fromString(value);
if (kind != null) {
this.kind = kind;
} else {
- super.visitEnum(name, descriptor, value);
+ unhandledEnum(name, descriptor, value);
}
}
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
PropertyParsingContext propertyParsingContext = parsingContext.property(name);
if (name.equals(Edge.preconditions)) {
return new KeepPreconditionsVisitor(
- propertyParsingContext, builder::setPreconditions, bindingsHelper);
+ propertyParsingContext, builder::setPreconditions, bindingsHelper, annotationVisitor);
}
if (name.equals(UsedByReflection.additionalTargets)) {
return new KeepConsequencesVisitor(
@@ -1405,13 +1478,15 @@
additionalConsequences -> {
additionalConsequences.forEachTarget(consequences::addTarget);
},
- bindingsHelper);
+ bindingsHelper,
+ annotationVisitor);
}
- AnnotationVisitor visitor = constraintsParser.tryParseArray(name, unused -> {});
+ AnnotationVisitor visitor =
+ constraintsParser.tryParseArray(name, unused -> {}, annotationVisitor);
if (visitor != null) {
return visitor;
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -1439,6 +1514,7 @@
.setBindings(bindingsHelper.build())
.setConsequences(consequences.build())
.build());
+ super.visitEnd();
}
private void validateConsistentKind(KeepMemberPattern memberPattern) {
@@ -1467,8 +1543,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
KeepItemPattern context = contextBuilder.apply(bindingsHelper);
@@ -1482,17 +1559,17 @@
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
- return;
}
super.visit(name, value);
}
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
PropertyParsingContext propertyParsingContext = parsingContext.property(name);
if (name.equals(AnnotationConstants.UsesReflection.value)) {
return new KeepConsequencesVisitor(
- propertyParsingContext, builder::setConsequences, bindingsHelper);
+ propertyParsingContext, builder::setConsequences, bindingsHelper, annotationVisitor);
}
if (name.equals(AnnotationConstants.UsesReflection.additionalPreconditions)) {
return new KeepPreconditionsVisitor(
@@ -1500,9 +1577,10 @@
additionalPreconditions -> {
additionalPreconditions.forEach(preconditions::addCondition);
},
- bindingsHelper);
+ bindingsHelper,
+ annotationVisitor);
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -1513,6 +1591,7 @@
.setBindings(bindingsHelper.build())
.setPreconditions(preconditions.build())
.build());
+ super.visitEnd();
}
}
@@ -1523,8 +1602,10 @@
KeepMethodParametersPattern.builder();
public ParametersClassVisitor(
- PropertyParsingContext parsingContext, Consumer<KeepMethodParametersPattern> consumer) {
- super(parsingContext);
+ PropertyParsingContext parsingContext,
+ Consumer<KeepMethodParametersPattern> consumer,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.consumer = consumer;
}
@@ -1537,14 +1618,14 @@
} else if (value instanceof Type) {
builder.addParameterTypePattern(
KeepTypePattern.fromDescriptor(((Type) value).getDescriptor()));
- } else {
- super.visit(name, value);
}
+ super.visit(name, value);
}
@Override
public void visitEnd() {
consumer.accept(builder.build());
+ super.visitEnd();
}
}
@@ -1555,8 +1636,10 @@
KeepMethodParametersPattern.builder();
public ParametersClassNamesVisitor(
- PropertyParsingContext parsingContext, Consumer<KeepMethodParametersPattern> consumer) {
- super(parsingContext);
+ PropertyParsingContext parsingContext,
+ Consumer<KeepMethodParametersPattern> consumer,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.consumer = consumer;
}
@@ -1568,14 +1651,14 @@
builder.addParameterTypePattern(
KeepTypePattern.fromDescriptor(
DescriptorUtils.javaTypeToDescriptor(kotlinTypeToJavaType((String) value))));
- } else {
- super.visit(name, value);
}
+ super.visit(name, value);
}
@Override
public void visitEnd() {
consumer.accept(builder.build());
+ super.visitEnd();
}
}
@@ -1590,8 +1673,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.addContext = addContext;
@@ -1600,11 +1684,12 @@
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
if (name.equals("value")) {
return new UsesReflectionForInstantiationsVisitor(
- parsingContext, parent, addContext, contextBuilder);
+ parsingContext, parent, addContext, contextBuilder, annotationVisitor);
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -1623,8 +1708,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.addContext = addContext;
@@ -1633,12 +1719,13 @@
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, descriptor);
assert name == null;
if (AnnotationConstants.UsesReflectionToConstruct.isDescriptor(descriptor)) {
return new UsesReflectionToConstructVisitor(
- parsingContext, parent, addContext, contextBuilder);
+ parsingContext, parent, addContext, contextBuilder, annotationVisitor);
}
- return super.visitAnnotation(name, descriptor);
+ return annotationVisitor;
}
}
@@ -1653,8 +1740,9 @@
protected KeepQualifiedClassNamePattern qualifiedName;
protected boolean includeSubclasses = false;
- UsesReflectionToXXXVisitor(AnnotationParsingContext parsingContext) {
- super(parsingContext);
+ UsesReflectionToXXXVisitor(
+ AnnotationParsingContext parsingContext, AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
assert UsesReflectionToXXXClassConstant.equals(UsesReflectionToConstruct.classConstant);
assert UsesReflectionToXXXClassConstant.equals(UsesReflectionToAccessMethod.classConstant);
@@ -1720,8 +1808,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parent = parent;
KeepItemPattern context = contextBuilder.apply(bindingsHelper);
KeepBindingReference contextBinding =
@@ -1732,27 +1821,28 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
if (maybeVisitQualifiedName(name, value)) {
return;
}
if (maybeVisitIncludeSubclasses(name, value)) {
return;
}
- super.visit(name, value);
}
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
PropertyParsingContext propertyParsingContext = parsingContext.property(name);
if (name.equals(UsesReflectionToConstruct.parameterTypes)) {
return new ParametersClassVisitor(
- propertyParsingContext, parameters -> this.parameters = parameters);
+ propertyParsingContext, parameters -> this.parameters = parameters, annotationVisitor);
}
if (name.equals(UsesReflectionToConstruct.parameterTypeNames)) {
return new ParametersClassNamesVisitor(
- propertyParsingContext, parameters -> this.parameters = parameters);
+ propertyParsingContext, parameters -> this.parameters = parameters, annotationVisitor);
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -1783,6 +1873,8 @@
.setPreconditions(preconditions.build())
.setConsequences(consequencesBuilder.build())
.build());
+
+ super.visitEnd();
}
}
@@ -1797,8 +1889,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.addContext = addContext;
@@ -1807,11 +1900,12 @@
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
if (name.equals("value")) {
return new UsesReflectionToAccessMethodContainerElementVisitor(
- parsingContext, parent, addContext, contextBuilder);
+ parsingContext, parent, addContext, contextBuilder, annotationVisitor);
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -1836,8 +1930,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.addContext = addContext;
@@ -1846,12 +1941,13 @@
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, descriptor);
assert name == null;
if (AnnotationConstants.UsesReflectionToAccessMethod.isDescriptor(descriptor)) {
return new UsesReflectionToAccessMethodVisitor(
- parsingContext, parent, addContext, contextBuilder);
+ parsingContext, parent, addContext, contextBuilder, annotationVisitor);
}
- return super.visitAnnotation(name, descriptor);
+ return annotationVisitor;
}
@Override
@@ -1879,8 +1975,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parent = parent;
KeepItemPattern context = contextBuilder.apply(bindingsHelper);
KeepBindingReference contextBinding =
@@ -1891,6 +1988,7 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
if (maybeVisitQualifiedName(name, value)) {
return;
}
@@ -1922,21 +2020,21 @@
}
return;
}
- super.visit(name, value);
}
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
PropertyParsingContext propertyParsingContext = parsingContext.property(name);
if (name.equals(UsesReflectionToAccessMethod.parameterTypes)) {
return new ParametersClassVisitor(
- propertyParsingContext, parameters -> this.parameters = parameters);
+ propertyParsingContext, parameters -> this.parameters = parameters, annotationVisitor);
}
if (name.equals(UsesReflectionToAccessMethod.parameterTypeNames)) {
return new ParametersClassNamesVisitor(
- propertyParsingContext, parameters -> this.parameters = parameters);
+ propertyParsingContext, parameters -> this.parameters = parameters, annotationVisitor);
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -1987,6 +2085,8 @@
.setPreconditions(preconditions.build())
.setConsequences(consequencesBuilder.build())
.build());
+
+ super.visitEnd();
}
}
@@ -2001,8 +2101,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.addContext = addContext;
@@ -2011,11 +2112,12 @@
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
if (name.equals("value")) {
return new UsesReflectionToAccessFieldContainerElementVisitor(
- parsingContext, parent, addContext, contextBuilder);
+ parsingContext, parent, addContext, contextBuilder, annotationVisitor);
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -2040,8 +2142,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.addContext = addContext;
@@ -2050,12 +2153,13 @@
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, descriptor);
assert name == null;
if (AnnotationConstants.UsesReflectionToAccessField.isDescriptor(descriptor)) {
return new UsesReflectionToAccessFieldVisitor(
- parsingContext, parent, addContext, contextBuilder);
+ parsingContext, parent, addContext, contextBuilder, annotationVisitor);
}
- return super.visitAnnotation(name, descriptor);
+ return annotationVisitor;
}
@Override
@@ -2082,8 +2186,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parent = parent;
KeepItemPattern context = contextBuilder.apply(bindingsHelper);
KeepBindingReference contextBinding =
@@ -2094,6 +2199,7 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
if (maybeVisitQualifiedName(name, value)) {
return;
}
@@ -2118,7 +2224,6 @@
KeepQualifiedClassNamePattern.exact((String) value))));
return;
}
- super.visit(name, value);
}
@Override
@@ -2149,6 +2254,8 @@
.setPreconditions(preconditions.build())
.setConsequences(consequencesBuilder.build())
.build());
+
+ super.visitEnd();
}
}
@@ -2164,8 +2271,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- String className) {
- super(parsingContext);
+ String className,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parent = parent;
addContext.accept(metaInfoBuilder);
KeepClassBindingReference kotlinMetadataBinding =
@@ -2184,6 +2292,7 @@
.setBindings(bindingsHelper.build())
.setConsequences(consequences.build())
.build());
+ super.visitEnd();
}
}
@@ -2199,8 +2308,9 @@
AnnotationParsingContext parsingContext,
Parent<KeepEdge> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
- Function<UserBindingsHelper, KeepMemberItemPattern> contextBuilder) {
- super(parsingContext);
+ Function<UserBindingsHelper, KeepMemberItemPattern> contextBuilder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parent = parent;
addContext.accept(metaInfoBuilder);
KeepMemberItemPattern context = contextBuilder.apply(bindingsHelper);
@@ -2220,6 +2330,8 @@
.setBindings(bindingsHelper.build())
.setConsequences(consequences.build())
.build());
+
+ super.visitEnd();
}
}
@@ -2227,19 +2339,24 @@
private final ParsingContext parsingContext;
private final UserBindingsHelper helper;
- public KeepBindingsVisitor(PropertyParsingContext parsingContext, UserBindingsHelper helper) {
- super(parsingContext);
+ public KeepBindingsVisitor(
+ PropertyParsingContext parsingContext,
+ UserBindingsHelper helper,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.helper = helper;
}
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, descriptor);
assert name == null;
if (AnnotationConstants.Binding.isDescriptor(descriptor)) {
- return new KeepBindingVisitor(parsingContext.annotation(descriptor), helper);
+ return new KeepBindingVisitor(
+ parsingContext.annotation(descriptor), helper, annotationVisitor);
}
- return super.visitAnnotation(name, descriptor);
+ return annotationVisitor;
}
}
@@ -2252,8 +2369,9 @@
public KeepPreconditionsVisitor(
PropertyParsingContext parsingContext,
Parent<KeepPreconditions> parent,
- UserBindingsHelper bindingsHelper) {
- super(parsingContext);
+ UserBindingsHelper bindingsHelper,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.bindingsHelper = bindingsHelper;
@@ -2261,17 +2379,22 @@
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, descriptor);
assert name == null;
if (Condition.isDescriptor(descriptor)) {
return new KeepConditionVisitor(
- parsingContext.annotation(descriptor), builder::addCondition, bindingsHelper);
+ parsingContext.annotation(descriptor),
+ builder::addCondition,
+ bindingsHelper,
+ annotationVisitor);
}
- return super.visitAnnotation(name, descriptor);
+ return annotationVisitor;
}
@Override
public void visitEnd() {
parent.accept(builder.build());
+ super.visitEnd();
}
}
@@ -2284,8 +2407,9 @@
public KeepConsequencesVisitor(
PropertyParsingContext parsingContext,
Parent<KeepConsequences> parent,
- UserBindingsHelper bindingsHelper) {
- super(parsingContext);
+ UserBindingsHelper bindingsHelper,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.bindingsHelper = bindingsHelper;
@@ -2293,17 +2417,22 @@
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, descriptor);
assert name == null;
if (Target.isDescriptor(descriptor)) {
return KeepTargetVisitor.create(
- parsingContext.annotation(descriptor), builder::addTarget, bindingsHelper);
+ parsingContext.annotation(descriptor),
+ builder::addTarget,
+ bindingsHelper,
+ annotationVisitor);
}
- return super.visitAnnotation(name, descriptor);
+ return annotationVisitor;
}
@Override
public void visitEnd() {
parent.accept(builder.build());
+ super.visitEnd();
}
}
@@ -2321,8 +2450,9 @@
Parent<KeepCheck> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
String className,
- KeepCheckKind kind) {
- super(parsingContext);
+ KeepCheckKind kind,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.parent = parent;
this.className = className;
@@ -2334,7 +2464,6 @@
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
- return;
}
super.visit(name, value);
}
@@ -2343,7 +2472,7 @@
public void visitEnd() {
UserBindingsHelper bindingsHelper = new UserBindingsHelper();
KeepItemVisitorBase itemVisitor =
- new KeepItemVisitorBase(parsingContext) {
+ new KeepItemVisitorBase(parsingContext, null) {
@Override
public UserBindingsHelper getBindingsHelper() {
return bindingsHelper;
@@ -2358,6 +2487,7 @@
.setBindings(itemVisitor.getBindingsHelper().build())
.setItemReference(itemVisitor.getItemReference())
.build());
+ super.visitEnd();
}
}
@@ -2375,8 +2505,9 @@
Parent<KeepDeclaration> parent,
Consumer<KeepEdgeMetaInfo.Builder> addContext,
Function<UserBindingsHelper, KeepMemberItemPattern> contextBuilder,
- KeepCheckKind kind) {
- super(parsingContext);
+ KeepCheckKind kind,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parent = parent;
this.context = bindingsHelper.defineFreshMemberBinding(contextBuilder.apply(bindingsHelper));
this.kind = kind;
@@ -2387,15 +2518,14 @@
public void visit(String name, Object value) {
if (name.equals(Edge.description) && value instanceof String) {
metaInfoBuilder.setDescription((String) value);
- return;
}
super.visit(name, value);
}
@Override
public void visitEnd() {
- super.visitEnd();
parent.accept(buildKeepCheckFromItem(metaInfoBuilder.build(), kind, context, bindingsHelper));
+ super.visitEnd();
}
private static KeepCheck buildKeepCheckFromItem(
@@ -2594,12 +2724,12 @@
}
@Override
- public AnnotationVisitor tryParseArray(String name) {
+ public AnnotationVisitor tryParseArray(String name, AnnotationVisitor annotationVisitor) {
if (name.equals(Item.methodAccess)) {
accessBuilder = KeepMethodAccessPattern.builder();
- return new MethodAccessVisitor(parsingContext, accessBuilder);
+ return new MethodAccessVisitor(parsingContext, accessBuilder, annotationVisitor);
}
- return super.tryParseArray(name);
+ return super.tryParseArray(name, annotationVisitor);
}
}
@@ -2667,12 +2797,12 @@
}
@Override
- public AnnotationVisitor tryParseArray(String name) {
+ public AnnotationVisitor tryParseArray(String name, AnnotationVisitor annotationVisitor) {
if (name.equals(Item.fieldAccess)) {
accessBuilder = KeepFieldAccessPattern.builder();
- return new FieldAccessVisitor(parsingContext, accessBuilder);
+ return new FieldAccessVisitor(parsingContext, accessBuilder, annotationVisitor);
}
- return super.tryParseArray(name);
+ return super.tryParseArray(name, annotationVisitor);
}
}
@@ -2739,12 +2869,12 @@
}
@Override
- public AnnotationVisitor tryParseArray(String name) {
+ public AnnotationVisitor tryParseArray(String name, AnnotationVisitor annotationVisitor) {
if (name.equals(Item.memberAccess)) {
accessBuilder = KeepMemberAccessPattern.memberBuilder();
- return new MemberAccessVisitor(parsingContext, accessBuilder);
+ return new MemberAccessVisitor(parsingContext, accessBuilder, annotationVisitor);
}
- return super.tryParseArray(name);
+ return super.tryParseArray(name, annotationVisitor);
}
}
@@ -2764,8 +2894,8 @@
// Constructed bindings available once visitEnd has been called.
private List<KeepBindingReference> itemReferences = null;
- KeepItemVisitorBase(ParsingContext parsingContext) {
- super(parsingContext);
+ KeepItemVisitorBase(ParsingContext parsingContext, AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
classDeclaration = new ClassDeclarationParser(parsingContext, this::getBindingsHelper);
memberDeclaration = new MemberDeclarationParser(parsingContext);
@@ -2803,8 +2933,9 @@
@Override
public void visitEnum(String name, String descriptor, String value) {
+ super.visitEnum(name, descriptor, value);
if (!AnnotationConstants.Kind.isDescriptor(descriptor)) {
- super.visitEnum(name, descriptor, value);
+ return;
}
ItemKind kind = ItemKind.fromString(value);
if (kind != null) {
@@ -2814,6 +2945,7 @@
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
if (name.equals(Item.memberFromBinding) && value instanceof String) {
memberBindingReference = (String) value;
return;
@@ -2822,29 +2954,31 @@
|| memberDeclaration.tryParse(name, value)) {
return;
}
- super.visit(name, value);
}
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
- AnnotationVisitor visitor = classDeclaration.tryParseAnnotation(name, descriptor);
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, descriptor);
+ AnnotationVisitor visitor =
+ classDeclaration.tryParseAnnotation(name, descriptor, annotationVisitor);
if (visitor != null) {
return visitor;
}
- visitor = memberDeclaration.tryParseAnnotation(name, descriptor);
+ visitor = memberDeclaration.tryParseAnnotation(name, descriptor, annotationVisitor);
if (visitor != null) {
return visitor;
}
- return super.visitAnnotation(name, descriptor);
+ return annotationVisitor;
}
@Override
public AnnotationVisitor visitArray(String name) {
- AnnotationVisitor visitor = memberDeclaration.tryParseArray(name);
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
+ AnnotationVisitor visitor = memberDeclaration.tryParseArray(name, annotationVisitor);
if (visitor != null) {
return visitor;
}
- return super.visitArray(name);
+ return annotationVisitor;
}
private void visitEndWithMemberBindingReference() {
@@ -2881,6 +3015,8 @@
@Override
public void visitEnd() {
+ super.visitEnd();
+
// Item defined by binding reference.
if (memberBindingReference != null) {
visitEndWithMemberBindingReference();
@@ -2960,8 +3096,11 @@
private final UserBindingsHelper helper;
private String bindingName;
- public KeepBindingVisitor(AnnotationParsingContext parsingContext, UserBindingsHelper helper) {
- super(parsingContext);
+ public KeepBindingVisitor(
+ AnnotationParsingContext parsingContext,
+ UserBindingsHelper helper,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsingContext = parsingContext;
this.helper = helper;
}
@@ -2975,7 +3114,6 @@
public void visit(String name, Object value) {
if (name.equals(Binding.bindingName) && value instanceof String) {
bindingName = (String) value;
- return;
}
super.visit(name, value);
}
@@ -2998,15 +3136,17 @@
static KeepTargetVisitor create(
AnnotationParsingContext parsingContext,
Parent<KeepTarget> parent,
- UserBindingsHelper bindingsHelper) {
- return new KeepTargetVisitor(parsingContext, parent, bindingsHelper);
+ UserBindingsHelper bindingsHelper,
+ AnnotationVisitor annotationVisitor) {
+ return new KeepTargetVisitor(parsingContext, parent, bindingsHelper, annotationVisitor);
}
private KeepTargetVisitor(
AnnotationParsingContext parsingContext,
Parent<KeepTarget> parent,
- UserBindingsHelper bindingsHelper) {
- super(parsingContext);
+ UserBindingsHelper bindingsHelper,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parent = parent;
this.bindingsHelper = bindingsHelper;
constraintsParser = new ConstraintDeclarationParser(parsingContext);
@@ -3019,11 +3159,13 @@
@Override
public AnnotationVisitor visitArray(String name) {
- AnnotationVisitor visitor = constraintsParser.tryParseArray(name, unused -> {});
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
+ AnnotationVisitor visitor =
+ constraintsParser.tryParseArray(name, unused -> {}, annotationVisitor);
if (visitor != null) {
return visitor;
}
- return super.visitArray(name);
+ return annotationVisitor;
}
@Override
@@ -3045,8 +3187,9 @@
public KeepConditionVisitor(
AnnotationParsingContext parsingContext,
Parent<KeepCondition> parent,
- UserBindingsHelper bindingsHelper) {
- super(parsingContext);
+ UserBindingsHelper bindingsHelper,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parent = parent;
this.bindingsHelper = bindingsHelper;
}
@@ -3066,8 +3209,11 @@
private static class MemberAccessVisitor extends AnnotationVisitorBase {
private KeepMemberAccessPattern.BuilderBase<?, ?> builder;
- public MemberAccessVisitor(ParsingContext parsingContext, BuilderBase<?, ?> builder) {
- super(parsingContext);
+ public MemberAccessVisitor(
+ ParsingContext parsingContext,
+ BuilderBase<?, ?> builder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.builder = builder;
}
@@ -3079,36 +3225,39 @@
}
@Override
- public void visitEnum(String ignore, String descriptor, String value) {
- if (!AnnotationConstants.MemberAccess.isDescriptor(descriptor)) {
- super.visitEnum(ignore, descriptor, value);
+ public void visitEnum(String name, String descriptor, String value) {
+ if (AnnotationConstants.MemberAccess.isDescriptor(descriptor)) {
+ boolean handled = handleCommonAccessFlags(value);
+ if (!handled) {
+ unhandledEnum(name, descriptor, value);
+ }
}
- boolean handled =
- withNormalizedAccessFlag(
- value,
- (flag, allow) -> {
- AccessVisibility visibility = getAccessVisibilityFromString(flag);
- if (visibility != null) {
- builder.setAccessVisibility(visibility, allow);
- return true;
- }
- switch (flag) {
- case MemberAccess.STATIC:
- builder.setStatic(allow);
- return true;
- case MemberAccess.FINAL:
- builder.setFinal(allow);
- return true;
- case MemberAccess.SYNTHETIC:
- builder.setSynthetic(allow);
- return true;
- default:
- return false;
- }
- });
- if (!handled) {
- super.visitEnum(ignore, descriptor, value);
- }
+ super.visitEnum(name, descriptor, value);
+ }
+
+ public boolean handleCommonAccessFlags(String value) {
+ return withNormalizedAccessFlag(
+ value,
+ (flag, allow) -> {
+ AccessVisibility visibility = getAccessVisibilityFromString(flag);
+ if (visibility != null) {
+ builder.setAccessVisibility(visibility, allow);
+ return true;
+ }
+ switch (flag) {
+ case MemberAccess.STATIC:
+ builder.setStatic(allow);
+ return true;
+ case MemberAccess.FINAL:
+ builder.setFinal(allow);
+ return true;
+ case MemberAccess.SYNTHETIC:
+ builder.setSynthetic(allow);
+ return true;
+ default:
+ return false;
+ }
+ });
}
private AccessVisibility getAccessVisibilityFromString(String value) {
@@ -3132,44 +3281,48 @@
private KeepMethodAccessPattern.Builder methodAccessBuilder;
public MethodAccessVisitor(
- ParsingContext parsingContext, KeepMethodAccessPattern.Builder builder) {
- super(parsingContext, builder);
+ ParsingContext parsingContext,
+ KeepMethodAccessPattern.Builder builder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, builder, annotationVisitor);
this.methodAccessBuilder = builder;
}
@Override
- public void visitEnum(String ignore, String descriptor, String value) {
- if (!AnnotationConstants.MethodAccess.isDescriptor(descriptor)) {
- super.visitEnum(ignore, descriptor, value);
+ public void visitEnum(String name, String descriptor, String value) {
+ if (AnnotationConstants.MethodAccess.isDescriptor(descriptor)) {
+ boolean handled =
+ withNormalizedAccessFlag(
+ value,
+ (flag, allow) -> {
+ switch (flag) {
+ case MethodAccess.SYNCHRONIZED:
+ methodAccessBuilder.setSynchronized(allow);
+ return true;
+ case MethodAccess.BRIDGE:
+ methodAccessBuilder.setBridge(allow);
+ return true;
+ case MethodAccess.NATIVE:
+ methodAccessBuilder.setNative(allow);
+ return true;
+ case MethodAccess.ABSTRACT:
+ methodAccessBuilder.setAbstract(allow);
+ return true;
+ case MethodAccess.STRICT_FP:
+ methodAccessBuilder.setStrictFp(allow);
+ return true;
+ default:
+ return false;
+ }
+ });
+ if (!handled) {
+ handled = handleCommonAccessFlags(value);
+ if (!handled) {
+ unhandledEnum(name, descriptor, value);
+ }
+ }
}
- boolean handled =
- withNormalizedAccessFlag(
- value,
- (flag, allow) -> {
- switch (flag) {
- case MethodAccess.SYNCHRONIZED:
- methodAccessBuilder.setSynchronized(allow);
- return true;
- case MethodAccess.BRIDGE:
- methodAccessBuilder.setBridge(allow);
- return true;
- case MethodAccess.NATIVE:
- methodAccessBuilder.setNative(allow);
- return true;
- case MethodAccess.ABSTRACT:
- methodAccessBuilder.setAbstract(allow);
- return true;
- case MethodAccess.STRICT_FP:
- methodAccessBuilder.setStrictFp(allow);
- return true;
- default:
- return false;
- }
- });
- if (!handled) {
- // Continue visitation with the "member" descriptor to allow matching the common values.
- super.visitEnum(ignore, MemberAccess.getDescriptor(), value);
- }
+ super.visitEnum(name, descriptor, value);
}
}
@@ -3178,36 +3331,39 @@
private KeepFieldAccessPattern.Builder fieldAccessBuilder;
public FieldAccessVisitor(
- ParsingContext parsingContext, KeepFieldAccessPattern.Builder builder) {
- super(parsingContext, builder);
+ ParsingContext parsingContext,
+ KeepFieldAccessPattern.Builder builder,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, builder, annotationVisitor);
this.fieldAccessBuilder = builder;
}
@Override
- public void visitEnum(String ignore, String descriptor, String value) {
- if (!AnnotationConstants.FieldAccess.isDescriptor(descriptor)) {
- super.visitEnum(ignore, descriptor, value);
+ public void visitEnum(String name, String descriptor, String value) {
+ if (AnnotationConstants.FieldAccess.isDescriptor(descriptor)) {
+ boolean handled =
+ withNormalizedAccessFlag(
+ value,
+ (flag, allow) -> {
+ switch (flag) {
+ case FieldAccess.VOLATILE:
+ fieldAccessBuilder.setVolatile(allow);
+ return true;
+ case FieldAccess.TRANSIENT:
+ fieldAccessBuilder.setTransient(allow);
+ return true;
+ default:
+ return false;
+ }
+ });
+ if (!handled) {
+ handled = handleCommonAccessFlags(value);
+ if (!handled) {
+ unhandledEnum(name, descriptor, value);
+ }
+ }
}
- boolean handled =
- withNormalizedAccessFlag(
- value,
- (flag, allow) -> {
- switch (flag) {
- case FieldAccess.VOLATILE:
- fieldAccessBuilder.setVolatile(allow);
- return true;
- case FieldAccess.TRANSIENT:
- fieldAccessBuilder.setTransient(allow);
- return true;
- default:
- return false;
- }
- });
- if (!handled) {
- // Continue visitation with the "member" descriptor to allow matching the common values.
- super.visitEnum(ignore, MemberAccess.getDescriptor(), value);
- }
+ super.visitEnum(name, descriptor, value);
}
}
-
}
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
index ccf5183..d5a1b6c 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/MethodReturnTypeParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/MethodReturnTypeParser.java
@@ -66,8 +66,11 @@
@Override
AnnotationVisitor tryPropertyArray(
- TypeProperty property, String name, Consumer<KeepMethodReturnTypePattern> setValue) {
- return typeParser.tryPropertyArray(property, name, wrap(setValue));
+ TypeProperty property,
+ String name,
+ Consumer<KeepMethodReturnTypePattern> setValue,
+ AnnotationVisitor annotationVisitor) {
+ return typeParser.tryPropertyArray(property, name, wrap(setValue), annotationVisitor);
}
@Override
@@ -75,7 +78,9 @@
TypeProperty property,
String name,
String descriptor,
- Consumer<KeepMethodReturnTypePattern> setValue) {
- return typeParser.tryPropertyAnnotation(property, name, descriptor, wrap(setValue));
+ Consumer<KeepMethodReturnTypePattern> setValue,
+ AnnotationVisitor annotationVisitor) {
+ return typeParser.tryPropertyAnnotation(
+ property, name, descriptor, wrap(setValue), annotationVisitor);
}
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/Parser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/Parser.java
index 3ca879b..58925e1 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/Parser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/Parser.java
@@ -19,7 +19,9 @@
boolean tryParseEnum(String name, String descriptor, String value, Consumer<T> setValue);
- AnnotationVisitor tryParseArray(String name, Consumer<T> setValue);
+ AnnotationVisitor tryParseArray(
+ String name, Consumer<T> setValue, AnnotationVisitor annotationVisitor);
- AnnotationVisitor tryParseAnnotation(String name, String descriptor, Consumer<T> setValue);
+ AnnotationVisitor tryParseAnnotation(
+ String name, String descriptor, Consumer<T> setValue, AnnotationVisitor annotationVisitor);
}
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 5acb59f..92aab67 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
@@ -16,64 +16,75 @@
private final Runnable onVisitEnd;
public ParserVisitor(
- AnnotationParsingContext parsingContext, List<Parser<?>> parsers, Runnable onVisitEnd) {
- super(parsingContext);
+ AnnotationParsingContext parsingContext,
+ List<Parser<?>> parsers,
+ Runnable onVisitEnd,
+ AnnotationVisitor annotationVisitor) {
+ super(parsingContext, annotationVisitor);
this.parsers = parsers;
this.onVisitEnd = onVisitEnd;
}
public ParserVisitor(
- AnnotationParsingContext parsingContext, Parser<?> parser, Runnable onVisitEnd) {
- this(parsingContext, Collections.singletonList(parser), onVisitEnd);
+ AnnotationParsingContext parsingContext,
+ Parser<?> parser,
+ Runnable onVisitEnd,
+ AnnotationVisitor annotationVisitor) {
+ this(parsingContext, Collections.singletonList(parser), onVisitEnd, annotationVisitor);
}
private <T> void ignore(T unused) {}
@Override
public void visit(String name, Object value) {
+ super.visit(name, value);
for (Parser<?> parser : parsers) {
if (parser.tryParse(name, value, this::ignore)) {
return;
}
}
- super.visit(name, value);
+ unhandledValue(name, value);
}
@Override
public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor annotationVisitor = super.visitArray(name);
for (Parser<?> parser : parsers) {
- AnnotationVisitor visitor = parser.tryParseArray(name, this::ignore);
+ AnnotationVisitor visitor = parser.tryParseArray(name, this::ignore, annotationVisitor);
if (visitor != null) {
return visitor;
}
}
- return super.visitArray(name);
+ return unhandledArray(name);
}
@Override
public void visitEnum(String name, String descriptor, String value) {
+ super.visitEnum(name, descriptor, value);
for (Parser<?> parser : parsers) {
if (parser.tryParseEnum(name, descriptor, value, this::ignore)) {
return;
}
}
- super.visitEnum(name, descriptor, value);
+ unhandledEnum(name, descriptor, value);
}
@Override
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ AnnotationVisitor annotationVisitor = super.visitAnnotation(name, descriptor);
for (Parser<?> parser : parsers) {
- AnnotationVisitor visitor = parser.tryParseAnnotation(name, descriptor, this::ignore);
+ AnnotationVisitor visitor =
+ parser.tryParseAnnotation(name, descriptor, this::ignore, annotationVisitor);
if (visitor != null) {
return visitor;
}
}
- return super.visitAnnotation(name, descriptor);
+ return unhandledAnnotation(name, descriptor);
}
@Override
public void visitEnd() {
- onVisitEnd.run();
super.visitEnd();
+ onVisitEnd.run();
}
}
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 f5b40c3..5360348 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
@@ -42,13 +42,18 @@
return false;
}
- AnnotationVisitor tryPropertyArray(P property, String name, Consumer<T> setValue) {
- return null;
+ AnnotationVisitor tryPropertyArray(
+ P property, String name, Consumer<T> setValue, AnnotationVisitor annotationVisitor) {
+ return annotationVisitor;
}
AnnotationVisitor tryPropertyAnnotation(
- P property, String name, String descriptor, Consumer<T> setValue) {
- return null;
+ P property,
+ String name,
+ String descriptor,
+ Consumer<T> setValue,
+ AnnotationVisitor annotationVisitor) {
+ return annotationVisitor;
}
private Consumer<T> wrap(String propertyName, Consumer<T> setValue) {
@@ -124,30 +129,32 @@
}
@Override
- public final AnnotationVisitor tryParseArray(String name, Consumer<T> setValue) {
+ public final AnnotationVisitor tryParseArray(
+ String name, Consumer<T> setValue, AnnotationVisitor annotationVisitor) {
P prop = mapping.get(name);
if (prop != null) {
try {
- return tryPropertyArray(prop, name, wrap(name, setValue));
+ return tryPropertyArray(prop, name, wrap(name, setValue), annotationVisitor);
} catch (RuntimeException e) {
throw parsingContext.rethrow(e);
}
}
- return null;
+ return annotationVisitor;
}
@Override
public final AnnotationVisitor tryParseAnnotation(
- String name, String descriptor, Consumer<T> setValue) {
+ String name, String descriptor, Consumer<T> setValue, AnnotationVisitor annotationVisitor) {
P prop = mapping.get(name);
if (prop != null) {
try {
- return tryPropertyAnnotation(prop, name, descriptor, wrap(name, setValue));
+ return tryPropertyAnnotation(
+ prop, name, descriptor, wrap(name, setValue), annotationVisitor);
} catch (RuntimeException e) {
throw parsingContext.rethrow(e);
}
}
- return null;
+ return annotationVisitor;
}
public void setValueCheck(BiConsumer<T, ParsingContext> check) {
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/StringPatternParser.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/StringPatternParser.java
index 2bb95df..486f586 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/StringPatternParser.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/StringPatternParser.java
@@ -43,7 +43,8 @@
StringProperty property,
String name,
String descriptor,
- Consumer<KeepStringPattern> setValue) {
+ Consumer<KeepStringPattern> setValue,
+ AnnotationVisitor annotationVisitor) {
switch (property) {
case PATTERN:
{
@@ -74,7 +75,8 @@
.setSuffix(suffixParser.getValueOrDefault(null))
.build());
}
- });
+ },
+ annotationVisitor);
}
default:
return null;
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 85962be..1e2198c 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
@@ -49,7 +49,11 @@
@Override
public AnnotationVisitor tryPropertyAnnotation(
- TypeProperty property, String name, String descriptor, Consumer<KeepTypePattern> setValue) {
+ TypeProperty property,
+ String name,
+ String descriptor,
+ Consumer<KeepTypePattern> setValue,
+ AnnotationVisitor annotationVisitor) {
switch (property) {
case TYPE_PATTERN:
{
@@ -63,7 +67,8 @@
return new ParserVisitor(
context,
typeParser,
- () -> setValue.accept(typeParser.getValueOrDefault(KeepTypePattern.any())));
+ () -> setValue.accept(typeParser.getValueOrDefault(KeepTypePattern.any())),
+ annotationVisitor);
}
case CLASS_NAME_PATTERN:
{
@@ -72,8 +77,8 @@
ClassNameProperty.PATTERN,
name,
descriptor,
- value ->
- setValue.accept(KeepTypePattern.fromClass(KeepClassPattern.fromName(value))));
+ value -> setValue.accept(KeepTypePattern.fromClass(KeepClassPattern.fromName(value))),
+ annotationVisitor);
}
case INSTANCE_OF_PATTERN:
{
@@ -85,7 +90,8 @@
value ->
setValue.accept(
KeepTypePattern.fromClass(
- KeepClassPattern.builder().setInstanceOfPattern(value).build())));
+ KeepClassPattern.builder().setInstanceOfPattern(value).build())),
+ annotationVisitor);
}
default:
return null;
diff --git a/src/test/java8/keepanno/com/android/tools/r8/keepanno/KeepAnnoChainingTest.java b/src/test/java8/keepanno/com/android/tools/r8/keepanno/KeepAnnoChainingTest.java
new file mode 100644
index 0000000..fca830b
--- /dev/null
+++ b/src/test/java8/keepanno/com/android/tools/r8/keepanno/KeepAnnoChainingTest.java
@@ -0,0 +1,150 @@
+// Copyright (c) 2026, 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.UsedByReflection;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class KeepAnnoChainingTest extends TestBase {
+
+ @UsedByReflection(kind = KeepItemKind.CLASS_AND_MEMBERS)
+ static class AnnotatedClass {
+ @UsedByReflection(kind = KeepItemKind.CLASS_AND_MEMBERS)
+ public int field;
+
+ @UsedByReflection(kind = KeepItemKind.CLASS_AND_MEMBERS)
+ public void method() {}
+ }
+
+ private static class RecordingVisitor extends ClassVisitor {
+ int visitCount = 0;
+ int visitAnnotationCount = 0;
+ int visitFieldCount = 0;
+ int visitMethodCount = 0;
+ List<String> visitedAnnotations = new ArrayList<>();
+ List<String> visitedFields = new ArrayList<>();
+ List<String> visitedMethods = new ArrayList<>();
+ List<String> visitedFieldAnnotations = new ArrayList<>();
+ List<String> visitedMethodAnnotations = new ArrayList<>();
+
+ RecordingVisitor() {
+ super(Opcodes.ASM9);
+ }
+
+ @Override
+ public void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ visitCount++;
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ visitAnnotationCount++;
+ visitedAnnotations.add(descriptor);
+ return super.visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ int access, String name, String descriptor, String signature, Object value) {
+ visitFieldCount++;
+ visitedFields.add(name);
+ FieldVisitor fieldVisitor = super.visitField(access, name, descriptor, signature, value);
+ return new FieldVisitor(Opcodes.ASM9, fieldVisitor) {
+ @Override
+ public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ visitedFieldAnnotations.add(descriptor);
+ return super.visitAnnotation(descriptor, visible);
+ }
+ };
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ int access, String name, String descriptor, String signature, String[] exceptions) {
+ visitMethodCount++;
+ visitedMethods.add(name);
+ MethodVisitor methodVisitor =
+ super.visitMethod(access, name, descriptor, signature, exceptions);
+ return new MethodVisitor(Opcodes.ASM9, methodVisitor) {
+ @Override
+ public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ visitedMethodAnnotations.add(descriptor);
+ return super.visitAnnotation(descriptor, visible);
+ }
+ };
+ }
+ }
+
+ @Test
+ public void testChainingRulesExtractor() throws Exception {
+ byte[] bytes = Files.readAllBytes(ToolHelper.getClassFileForTestClass(AnnotatedClass.class));
+ ClassReader reader = new ClassReader(bytes);
+
+ List<String> rules = new ArrayList<>();
+ RecordingVisitor recorder = new RecordingVisitor();
+ ClassVisitor extractor =
+ KeepAnno.createClassVisitorForKeepRulesExtraction(rules::add, recorder);
+
+ reader.accept(extractor, ClassReader.SKIP_CODE);
+
+ // Verify rules were extracted
+ assertTrue(rules.size() > 0);
+
+ // Verify recorder saw everything
+ assertEquals(1, recorder.visitCount);
+ // AnnotatedClass has @UsedByReflection on class
+ assertTrue(recorder.visitedAnnotations.stream().anyMatch(d -> d.contains("UsedByReflection")));
+ // And it has field and method
+ assertTrue(recorder.visitedFields.contains("field"));
+ assertTrue(recorder.visitedMethods.contains("method"));
+
+ // Verify field and method annotations were delegated
+ assertTrue(
+ recorder.visitedFieldAnnotations.stream().anyMatch(d -> d.contains("UsedByReflection")));
+ assertTrue(
+ recorder.visitedMethodAnnotations.stream().anyMatch(d -> d.contains("UsedByReflection")));
+ }
+
+ @Test
+ public void testChainingRulesExtractorWithItself() throws Exception {
+ byte[] bytes = Files.readAllBytes(ToolHelper.getClassFileForTestClass(AnnotatedClass.class));
+ ClassReader reader = new ClassReader(bytes);
+
+ List<String> rules = new ArrayList<>();
+ ClassVisitor extractor = KeepAnno.createClassVisitorForKeepRulesExtraction(rules::add);
+
+ List<String> rules2 = new ArrayList<>();
+ ClassVisitor extractor2 =
+ KeepAnno.createClassVisitorForKeepRulesExtraction(rules2::add, extractor);
+
+ reader.accept(extractor2, ClassReader.SKIP_CODE);
+
+ // As the visitor is not making any changes but only reading the annotations chaining it with
+ // itself should extract the same rules twice.
+ assertTrue(rules.size() > 0);
+ assertEquals(rules2, rules);
+ }
+}