[keepanno] @UsesReflectiontoAccessField kotlin-reflect properties test
Bug: b/392865072
Change-Id: I4c5ffa9401a1d9616d67e2bc535a02544ed5972e
diff --git a/src/test/java/com/android/tools/r8/keepanno/androidx/KeepUsesReflectionToAccessFieldTest.java b/src/test/java/com/android/tools/r8/keepanno/androidx/KeepUsesReflectionToAccessFieldTest.java
index d5ce9e4..5ddca5d 100644
--- a/src/test/java/com/android/tools/r8/keepanno/androidx/KeepUsesReflectionToAccessFieldTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/androidx/KeepUsesReflectionToAccessFieldTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.keepanno.androidx;
import static com.android.tools.r8.ToolHelper.getFilesInTestFolderRelativeToClass;
+import static org.hamcrest.CoreMatchers.containsString;
import androidx.annotation.keep.UsesReflectionToAccessField;
import com.android.tools.r8.ToolHelper.DexVm.Version;
@@ -18,6 +19,8 @@
import java.nio.file.Path;
import java.util.Collection;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,8 +46,14 @@
private static Collection<Path> getKotlinSources() {
try {
- return getFilesInTestFolderRelativeToClass(
- KeepUsesReflectionToAccessFieldTest.class, "kt", "Fields.kt", "FieldsKeptClass.kt");
+ return Stream.concat(
+ getFilesInTestFolderRelativeToClass(
+ KeepUsesReflectionToAccessFieldTest.class, "kt", "Fields.kt")
+ .stream(),
+ getFilesInTestFolderRelativeToClass(
+ KeepUsesReflectionToAccessFieldTest.class, "kt", "FieldsPropertyAccess.kt")
+ .stream())
+ .collect(Collectors.toList());
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -269,6 +278,42 @@
StringUtils.lines("3"));
}
+ @Test
+ public void testPropertyAccessKotlin() throws Exception {
+ testExtractedRulesAndRunKotlin(
+ compilationResults,
+ (classReference, classFileBytes) ->
+ setAnnotationOnMethod(
+ classReference,
+ classFileBytes,
+ Reference.classFromTypeName(
+ "com.android.tools.r8.keepanno.androidx.kt.FieldsPropertyAccess"),
+ MethodPredicate.onName("foo"),
+ builder ->
+ buildUsesReflectionToAccessField(
+ builder,
+ Type.getType(
+ DescriptorUtils.javaTypeToDescriptor(
+ "com.android.tools.r8.keepanno.androidx.kt.FieldsPropertyAccessKeptClass")),
+ "x",
+ int.class)),
+ "com.android.tools.r8.keepanno.androidx.kt.FieldsPropertyAccessKt",
+ getExpectedRulesKotlin(
+ "com.android.tools.r8.keepanno.androidx.kt.FieldsPropertyAccess",
+ "{ void foo(); }",
+ "com.android.tools.r8.keepanno.androidx.kt.FieldsPropertyAccessKeptClass",
+ "{ int x; }"),
+ // TODO(b/392865072): Not sure why this succeeds on DEX even though the getter getX has
+ // been removed.
+ parameters.getBackend().isDex()
+ ? r -> r.assertSuccessWithOutput(StringUtils.lines("1"))
+ : r ->
+ r.assertFailureWithErrorThatMatches(
+ containsString(
+ "Property 'x' (JVM signature: getX()I) not resolved in class"
+ + " com.android.tools.r8.keepanno.androidx.kt")));
+ }
+
// Test class without annotation to be used by multiple tests inserting annotations using a
// transformer.
static class ClassWithAnnotation {
diff --git a/src/test/java/com/android/tools/r8/keepanno/androidx/kt/FieldsPropertyAccess.kt b/src/test/java/com/android/tools/r8/keepanno/androidx/kt/FieldsPropertyAccess.kt
new file mode 100644
index 0000000..69a27b4
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/keepanno/androidx/kt/FieldsPropertyAccess.kt
@@ -0,0 +1,27 @@
+// Copyright (c) 2025, 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.androidx.kt
+
+import kotlin.reflect.KProperty
+
+class FieldsPropertyAccess {
+ fun foo() {
+ val x: KProperty<*> = FieldsPropertyAccessKeptClass::x
+ val y: KProperty<*> = FieldsPropertyAccessKeptClass::y
+ val s: KProperty<*> = FieldsPropertyAccessKeptClass::s
+ println(x.call(FieldsPropertyAccessKeptClass()))
+ }
+}
+
+class FieldsPropertyAccessKeptClass {
+ var x: Int = 1
+
+ var y: Long = 2
+
+ var s: String = "3"
+}
+
+fun main() {
+ FieldsPropertyAccess().foo()
+}