Reflection: add test on introspection of local classes
kotlin-reflect works correctly already for Kotlin-generated local classes and anonymous objects, but not for Java ones. This is fixed in a subsequent commit. #KT-41373 In Progress
This commit is contained in:
committed by
Space Team
parent
9fcdc10019
commit
1e031d9fb8
+16
@@ -45305,6 +45305,22 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("localClassesAndAnonymousObjects.kt")
|
||||
public void testLocalClassesAndAnonymousObjects() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/localClasses/localClassesAndAnonymousObjects.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+16
@@ -45305,6 +45305,22 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("localClassesAndAnonymousObjects.kt")
|
||||
public void testLocalClassesAndAnonymousObjects() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/localClasses/localClassesAndAnonymousObjects.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
// FILE: anonymousObjects.kt
|
||||
|
||||
package test
|
||||
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.test.*
|
||||
|
||||
interface I
|
||||
|
||||
fun check(x: KClass<*>, value: Any) {
|
||||
assertEquals(null, x.qualifiedName)
|
||||
|
||||
assertEquals(
|
||||
setOf(
|
||||
"foo", "bar",
|
||||
"equals", "hashCode", "toString"
|
||||
),
|
||||
x.members.mapTo(hashSetOf()) { it.name }
|
||||
)
|
||||
|
||||
assertEquals(emptyList(), x.annotations)
|
||||
assertEquals(emptyList(), x.nestedClasses)
|
||||
assertEquals(null, x.objectInstance)
|
||||
assertEquals(emptyList(), x.sealedSubclasses)
|
||||
|
||||
assertEquals(listOf(typeOf<I>(), typeOf<Any>()), x.supertypes)
|
||||
|
||||
// Local class visibility cannot be represented in Kotlin, so `KClass.visibility` is null.
|
||||
assertEquals(null, x.visibility)
|
||||
|
||||
// It's not really important whether the class is considered final or open, but it shouldn't be both (or neither).
|
||||
assertTrue(x.isFinal xor x.isOpen)
|
||||
|
||||
assertFalse(x.isAbstract)
|
||||
assertFalse(x.isSealed)
|
||||
assertFalse(x.isData)
|
||||
assertFalse(x.isInner)
|
||||
assertFalse(x.isCompanion)
|
||||
assertFalse(x.isFun)
|
||||
assertFalse(x.isValue)
|
||||
|
||||
assertFalse(x.isInstance(42))
|
||||
assertTrue(x.isInstance(value))
|
||||
|
||||
val equals = x.members.single { it.name == "equals" } as KFunction<Boolean>
|
||||
assertTrue(equals.call(value, value))
|
||||
|
||||
val foo = x.members.single { it.name == "foo" }.apply { isAccessible = true } as KFunction<String>
|
||||
assertEquals("OK", foo.call(value))
|
||||
|
||||
val bar = x.members.single { it.name == "bar" }.apply { isAccessible = true } as KProperty1<Any, Int>
|
||||
assertEquals(42, bar.get(value))
|
||||
}
|
||||
|
||||
fun checkKotlinAnonymousObject() {
|
||||
val anonymousObject = object : I {
|
||||
val bar: Int = 42
|
||||
fun foo(): String = "OK"
|
||||
}
|
||||
val klass = anonymousObject::class
|
||||
|
||||
// isAnonymousClass/simpleName behavior is different for Kotlin anonymous classes in JDK 1.8 and 9+, see KT-23072.
|
||||
if (klass.java.isAnonymousClass) {
|
||||
assertEquals(null, klass.simpleName)
|
||||
} else {
|
||||
assertEquals("anonymousObject\$1", klass.simpleName)
|
||||
}
|
||||
|
||||
assertEquals(emptyList(), klass.constructors)
|
||||
|
||||
check(klass, anonymousObject)
|
||||
}
|
||||
|
||||
fun checkKotlinLocalClass() {
|
||||
class Local : I {
|
||||
val bar: Int = 42
|
||||
fun foo(): String = "OK"
|
||||
}
|
||||
val instance = Local()
|
||||
val klass = instance::class
|
||||
|
||||
// simpleName behavior is different for Kotlin anonymous classes in JDK 1.8 and 9+, see KT-23072.
|
||||
assertTrue(klass.simpleName!!.endsWith("Local"))
|
||||
|
||||
assertEquals(listOf("fun `<init>`(): test.`AnonymousObjectsKt\$checkKotlinLocalClass\$Local`"), klass.constructors.map { it.toString() })
|
||||
|
||||
check(klass, instance)
|
||||
}
|
||||
|
||||
fun checkJavaAnonymousObject() {
|
||||
val anonymousObject = JavaClass.anonymousObject()
|
||||
val klass = anonymousObject::class
|
||||
|
||||
assertEquals(null, klass.simpleName)
|
||||
|
||||
assertEquals(listOf("fun `<init>`(): `JavaClass$1`"), klass.constructors.map { it.toString() })
|
||||
|
||||
check(klass, anonymousObject)
|
||||
}
|
||||
|
||||
fun checkJavaLocalClass() {
|
||||
val instance = JavaClass.localClassInstance()
|
||||
val klass = instance::class
|
||||
|
||||
assertEquals("Local", klass.simpleName)
|
||||
|
||||
assertEquals(listOf("fun `<init>`(): Local"), klass.constructors.map { it.toString() })
|
||||
|
||||
check(klass, instance)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
checkKotlinAnonymousObject()
|
||||
checkKotlinLocalClass()
|
||||
|
||||
// TODO: fails with KotlinReflectionInternalError: Unresolved class: class JavaClass$1 (kind = null)
|
||||
// checkJavaAnonymousObject()
|
||||
// checkJavaLocalClass()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: JavaClass.java
|
||||
|
||||
public class JavaClass {
|
||||
public static Object anonymousObject() {
|
||||
return new test.I() {
|
||||
int bar = 42;
|
||||
String foo() { return "OK"; }
|
||||
};
|
||||
}
|
||||
|
||||
public static Object localClassInstance() {
|
||||
class Local implements test.I {
|
||||
int bar = 42;
|
||||
String foo() { return "OK"; }
|
||||
}
|
||||
|
||||
return new Local();
|
||||
}
|
||||
}
|
||||
+16
@@ -42647,6 +42647,22 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("localClassesAndAnonymousObjects.kt")
|
||||
public void testLocalClassesAndAnonymousObjects() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/localClasses/localClassesAndAnonymousObjects.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+16
@@ -45305,6 +45305,22 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("localClassesAndAnonymousObjects.kt")
|
||||
public void testLocalClassesAndAnonymousObjects() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/localClasses/localClassesAndAnonymousObjects.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+16
@@ -45305,6 +45305,22 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("localClassesAndAnonymousObjects.kt")
|
||||
public void testLocalClassesAndAnonymousObjects() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/localClasses/localClassesAndAnonymousObjects.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+18
@@ -36008,6 +36008,24 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class LocalClasses extends AbstractLightAnalysisModeTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("localClassesAndAnonymousObjects.kt")
|
||||
public void testLocalClassesAndAnonymousObjects() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/localClasses/localClassesAndAnonymousObjects.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+10
@@ -32537,6 +32537,16 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+10
@@ -32537,6 +32537,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+10
@@ -32537,6 +32537,16 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+13
@@ -35884,6 +35884,19 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("frontend-fir")
|
||||
@FirPipeline()
|
||||
@UseExtTestCaseGroupProvider()
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+15
@@ -36760,6 +36760,21 @@ public class FirNativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenB
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("frontend-fir")
|
||||
@FirPipeline()
|
||||
@UseExtTestCaseGroupProvider()
|
||||
@UsePartialLinkage(mode = Mode.DISABLED)
|
||||
@Tag("no-partial-linkage-may-be-skipped")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+12
@@ -35447,6 +35447,18 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@UseExtTestCaseGroupProvider()
|
||||
@DisabledTestsIfProperty(sourceLocations = { "compiler/testData/codegen/box/coroutines/featureIntersection/defaultExpect.kt", "compiler/testData/codegen/box/multiplatform/defaultArguments/*.kt", "compiler/testData/codegen/box/multiplatform/migratedOldTests/*.kt", "compiler/testData/codegen/boxInline/multiplatform/defaultArguments/receiversAndParametersInLambda.kt" }, property = ClassLevelProperty.TEST_MODE, propertyValue = "ONE_STAGE_MULTI_MODULE")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+13
@@ -35885,6 +35885,19 @@ public class NativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenBoxT
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@UseExtTestCaseGroupProvider()
|
||||
@UsePartialLinkage(mode = Mode.DISABLED)
|
||||
@Tag("no-partial-linkage-may-be-skipped")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
Generated
+10
@@ -32345,6 +32345,16 @@ public class FirWasmCodegenBoxTestGenerated extends AbstractFirWasmCodegenBoxTes
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
Generated
+10
@@ -32345,6 +32345,16 @@ public class K1WasmCodegenBoxTestGenerated extends AbstractK1WasmCodegenBoxTest
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/localClasses")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class LocalClasses {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocalClasses() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/localClasses"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
Reference in New Issue
Block a user