[KeepAnno] Add `constraintAdditions` to UsedBy annotations
Bug: b/248408342
Change-Id: I89d0770e878810950137c4ed49f1cab8476a992a
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByNative.java b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByNative.java
index 2bcf8dd..6157cbd 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByNative.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByNative.java
@@ -111,11 +111,27 @@
* <li>{@link KeepConstraint#FIELD_SET}
* </ul>
*
+ * <p>Mutually exclusive with the property `constraintAdditions` also defining constraints.
+ *
* @return Usage constraints for the target.
*/
KeepConstraint[] constraints() default {};
/**
+ * Add additional usage constraints of the target.
+ *
+ * <p>The specified constraints must remain valid for the target in addition to the default
+ * constraints.
+ *
+ * <p>The default constraints are documented in {@link #constraints}
+ *
+ * <p>Mutually exclusive with the property `constraints` also defining constraints.
+ *
+ * @return Additional usage constraints for the target.
+ */
+ KeepConstraint[] constraintAdditions() default {};
+
+ /**
* Define the member-annotated-by pattern by fully qualified class name.
*
* <p>Mutually exclusive with the following other properties defining member-annotated-by:
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByReflection.java b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByReflection.java
index 7133e96..17add2d 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByReflection.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByReflection.java
@@ -111,11 +111,27 @@
* <li>{@link KeepConstraint#FIELD_SET}
* </ul>
*
+ * <p>Mutually exclusive with the property `constraintAdditions` also defining constraints.
+ *
* @return Usage constraints for the target.
*/
KeepConstraint[] constraints() default {};
/**
+ * Add additional usage constraints of the target.
+ *
+ * <p>The specified constraints must remain valid for the target in addition to the default
+ * constraints.
+ *
+ * <p>The default constraints are documented in {@link #constraints}
+ *
+ * <p>Mutually exclusive with the property `constraints` also defining constraints.
+ *
+ * @return Additional usage constraints for the target.
+ */
+ KeepConstraint[] constraintAdditions() default {};
+
+ /**
* Define the member-annotated-by pattern by fully qualified class name.
*
* <p>Mutually exclusive with the following other properties defining member-annotated-by:
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepUsedByNativeAnnotationTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepUsedByNativeAnnotationTest.java
index b3a1579..19e2290 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepUsedByNativeAnnotationTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepUsedByNativeAnnotationTest.java
@@ -11,12 +11,16 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.keepanno.annotations.KeepCondition;
+import com.android.tools.r8.keepanno.annotations.KeepConstraint;
import com.android.tools.r8.keepanno.annotations.KeepItemKind;
import com.android.tools.r8.keepanno.annotations.UsedByNative;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -25,7 +29,7 @@
@RunWith(Parameterized.class)
public class KeepUsedByNativeAnnotationTest extends TestBase {
- static final String EXPECTED = StringUtils.lines("Hello, world");
+ static final String EXPECTED = StringUtils.lines("@Anno.value = anno-on-bar", "Hello, world");
private final TestParameters parameters;
@@ -59,7 +63,7 @@
}
public List<Class<?>> getInputClasses() {
- return ImmutableList.of(TestClass.class, A.class, B.class, C.class);
+ return ImmutableList.of(TestClass.class, Anno.class, A.class, B.class, C.class);
}
private void checkOutput(CodeInspector inspector) {
@@ -71,6 +75,11 @@
assertThat(inspector.clazz(B.class).method("void", "bar", "int"), isAbsent());
}
+ @Retention(RetentionPolicy.RUNTIME)
+ private @interface Anno {
+ String value();
+ }
+
@UsedByNative(
description = "Ensure that the class A remains as we are assuming the contents of its name.",
preconditions = {@KeepCondition(classConstant = A.class, methodName = "foo")},
@@ -81,7 +90,10 @@
public void foo() throws Exception {
Class<?> clazz = Class.forName(A.class.getTypeName().replace("$A", "$B"));
- clazz.getDeclaredMethod("bar").invoke(clazz);
+ Method bar = clazz.getDeclaredMethod("bar");
+ Anno annotation = bar.getAnnotation(Anno.class);
+ System.out.println("@Anno.value = " + annotation.value());
+ bar.invoke(clazz);
}
public void bar() {
@@ -95,7 +107,9 @@
// Only if A.foo is live do we need to keep this.
preconditions = {@KeepCondition(classConstant = A.class, methodName = "foo")},
// Both the class and method are reflectively accessed.
- kind = KeepItemKind.CLASS_AND_MEMBERS)
+ kind = KeepItemKind.CLASS_AND_MEMBERS,
+ constraintAdditions = {KeepConstraint.ANNOTATIONS})
+ @Anno("anno-on-bar")
public static void bar() {
System.out.println("Hello, world");
}
diff --git a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
index c6bb24b..0852bde 100644
--- a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
+++ b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
@@ -1294,7 +1294,7 @@
+ " if annotating a member.")
.generate(this);
println();
- constraints().generate(this);
+ getKeepConstraintsGroup().generate(this);
println();
generateMemberPropertiesNoBinding();
});