[IR] Support reflection for MFVC

Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com>

#KT-1179
This commit is contained in:
Evgeniy.Zhelenskiy
2023-03-02 01:48:02 +01:00
committed by Space Team
parent 1ff4906880
commit 88f293d4a9
52 changed files with 2910 additions and 172 deletions
@@ -0,0 +1,23 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.javaConstructor
import kotlin.reflect.jvm.kotlinFunction
import kotlin.test.assertEquals
@JvmInline
value class Z(val x1: UInt, val x2: Int)
class Test(val x: Z)
fun box(): String {
val kctor1 = Test::class.primaryConstructor ?: throw AssertionError("No primary constructor")
val jctor1 = kctor1.javaConstructor ?: throw AssertionError("No javaConstructor for $kctor1")
val kctor2 = jctor1.kotlinFunction ?: throw AssertionError("No kotlinFunction for $jctor1")
assertEquals(kctor1, kctor2)
assertEquals("[x]", kctor2.parameters.map { it.name }.toString())
return "OK"
}
@@ -8,20 +8,16 @@ inline class S(val value: String)
fun S.foo(x: Int, s: S): S = this
/* TODO: Support calling members of inline classes in reflection (KT-26748)
inline class T(val s: S) {
fun bar(u: S): T = this
}
*/
fun box(): String {
assertEquals(listOf(String::class.java, Int::class.java, String::class.java), S::foo.parameters.map { it.type.javaType })
assertEquals(String::class.java, S::foo.returnType.javaType)
/*
assertEquals(listOf(), T::bar.parameters.map { it.type.javaType })
assertEquals(listOf(String::class.java, String::class.java), T::bar.parameters.map { it.type.javaType })
assertEquals(String::class.java, T::bar.returnType.javaType)
*/
return "OK"
}
@@ -0,0 +1,46 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
import java.lang.reflect.Type
@JvmInline
value class S(val value1: UInt, val value2: String)
fun S.foo(x: Int, s: S): S = this
fun compoundType(vararg types: Type) = listOf(*types).toString()
@JvmInline
value class T(val s: S) {
fun bar(u: S): T = this
}
data class U(val s: S) {
fun bar(u: S): U = this
}
@kotlin.ExperimentalStdlibApi
fun box(): String {
assertEquals(listOf(Int::class.java, String::class.java), ::S.parameters.map { it.type.javaType })
assertEquals(S::class.java, ::S.returnType.javaType)
assertEquals(listOf(compoundType(Int::class.java, String::class.java)), ::T.parameters.map { it.type.javaType.toString() })
assertEquals(T::class.java, ::T.returnType.javaType)
assertEquals(listOf(compoundType(Int::class.java, String::class.java)), ::U.parameters.map { it.type.javaType.toString() })
assertEquals(U::class.java, ::U.returnType.javaType)
assertEquals(listOf(compoundType(Int::class.java, String::class.java), Int::class.java.toString(), compoundType(Int::class.java, String::class.java)), S::foo.parameters.map { it.type.javaType.toString() })
assertEquals(S::class.java, S::foo.returnType.javaType)
assertEquals(listOf(compoundType(Int::class.java, String::class.java), compoundType(Int::class.java, String::class.java)), T::bar.parameters.map { it.type.javaType.toString() })
assertEquals(T::class.java, T::bar.returnType.javaType)
assertEquals(listOf(U::class.java.toString(), compoundType(Int::class.java, String::class.java)), U::bar.parameters.map { it.type.javaType.toString() })
assertEquals(U::class.java, U::bar.returnType.javaType)
return "OK"
}
@@ -0,0 +1,85 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
package test
import kotlin.reflect.KCallable
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
@JvmInline
value class Z1(val publicX1: UInt, val publicX2: Int) {
companion object {
val publicX1Ref = Z1::publicX1
val publicX2Ref = Z1::publicX2
val publicX1BoundRef = Z1(42U, 43)::publicX1
val publicX2BoundRef = Z1(42U, 43)::publicX2
}
}
@JvmInline
value class Z2(internal val internalX1: UInt, internal val internalX2: Int) {
companion object {
val internalX1Ref = Z2::internalX1
val internalX2Ref = Z2::internalX2
val internalX1BoundRef = Z2(42U, 43)::internalX1
val internalX2BoundRef = Z2(42U, 43)::internalX2
}
}
@JvmInline
value class Z3(private val privateX1: UInt, private val privateX2: Int) {
companion object {
val privateX1Ref = Z3::privateX1
val privateX2Ref = Z3::privateX2
val privateX1BoundRef = Z3(42U, 43)::privateX1
val privateX2BoundRef = Z3(42U, 43)::privateX2
}
}
@JvmInline
value class ZZ(val x1: Z1, val x2: Z1)
fun KCallable<*>.getJavaTypesOfParams() = parameters.map { it.type.javaType }.toString()
fun KCallable<*>.getJavaTypeOfResult() = returnType.javaType.toString()
fun box(): String {
assertEquals("[class test.Z1]", Z1.publicX1Ref.getJavaTypesOfParams())
assertEquals("[class test.Z1]", Z1.publicX2Ref.getJavaTypesOfParams())
assertEquals("int", Z1.publicX1Ref.getJavaTypeOfResult())
assertEquals("int", Z1.publicX2Ref.getJavaTypeOfResult())
assertEquals("[]", Z1.publicX1BoundRef.getJavaTypesOfParams())
assertEquals("[]", Z1.publicX2BoundRef.getJavaTypesOfParams())
assertEquals("int", Z1.publicX1BoundRef.getJavaTypeOfResult())
assertEquals("int", Z1.publicX2BoundRef.getJavaTypeOfResult())
assertEquals("[class test.Z2]", Z2.internalX1Ref.getJavaTypesOfParams())
assertEquals("[class test.Z2]", Z2.internalX2Ref.getJavaTypesOfParams())
assertEquals("int", Z2.internalX1Ref.getJavaTypeOfResult())
assertEquals("int", Z2.internalX2Ref.getJavaTypeOfResult())
assertEquals("[]", Z2.internalX1BoundRef.getJavaTypesOfParams())
assertEquals("[]", Z2.internalX2BoundRef.getJavaTypesOfParams())
assertEquals("int", Z2.internalX1BoundRef.getJavaTypeOfResult())
assertEquals("int", Z2.internalX2BoundRef.getJavaTypeOfResult())
assertEquals("[class test.Z3]", Z3.privateX1Ref.getJavaTypesOfParams())
assertEquals("[class test.Z3]", Z3.privateX2Ref.getJavaTypesOfParams())
assertEquals("int", Z3.privateX1Ref.getJavaTypeOfResult())
assertEquals("int", Z3.privateX2Ref.getJavaTypeOfResult())
assertEquals("[]", Z3.privateX1BoundRef.getJavaTypesOfParams())
assertEquals("[]", Z3.privateX2BoundRef.getJavaTypesOfParams())
assertEquals("int", Z3.privateX1BoundRef.getJavaTypeOfResult())
assertEquals("int", Z3.privateX2BoundRef.getJavaTypeOfResult())
assertEquals("[class test.ZZ]", ZZ::x1.getJavaTypesOfParams())
assertEquals("[class test.ZZ]", ZZ::x2.getJavaTypesOfParams())
assertEquals("class test.Z1", ZZ::x1.getJavaTypeOfResult())
assertEquals("class test.Z1", ZZ::x2.getJavaTypeOfResult())
return "OK"
}
@@ -0,0 +1,90 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@JvmInline
value class Z1(val publicX1: UInt, val publicX2: Int) {
companion object {
val publicX1Ref = Z1::publicX1
val publicX2Ref = Z1::publicX2
val publicX1BoundRef = Z1(42U, -42)::publicX1
val publicX2BoundRef = Z1(42U, -42)::publicX2
}
}
@JvmInline
value class Z2(internal val internalX1: UInt, internal val internalX2: Int) {
companion object {
val internalX1Ref = Z2::internalX1
val internalX2Ref = Z2::internalX2
val internalX1BoundRef = Z2(42U, -42)::internalX1
val internalX2BoundRef = Z2(42U, -42)::internalX2
}
}
@JvmInline
value class Z3(private val privateX1: UInt, private val privateX2: Int) {
companion object {
val privateX1Ref = Z3::privateX1
val privateX2Ref = Z3::privateX2
val privateX1BoundRef = Z3(42U, -42)::privateX1
val privateX2BoundRef = Z3(42U, -42)::privateX2
}
}
@JvmInline
value class Z1_2(val publicX: Z1) {
companion object {
val publicXRef = Z1_2::publicX
val publicXBoundRef = Z1_2(Z1(42U, -42))::publicX
}
}
@JvmInline
value class Z2_2(internal val internalX: Z2) {
companion object {
val internalXRef = Z2_2::internalX
val internalXBoundRef = Z2_2(Z2(42U, -42))::internalX
}
}
@JvmInline
value class Z3_2(private val privateX: Z3) {
companion object {
val privateXRef = Z3_2::privateX
val privateXBoundRef = Z3_2(Z3(42U, -42))::privateX
}
}
fun box(): String {
val suffix = "-pVg5ArA"
assertEquals("getPublicX1$suffix", Z1.publicX1Ref.javaGetter!!.name)
assertEquals("getPublicX2", Z1.publicX2Ref.javaGetter!!.name)
assertEquals("getPublicX1$suffix", Z1.publicX1BoundRef.javaGetter!!.name)
assertEquals("getPublicX2", Z1.publicX2BoundRef.javaGetter!!.name)
assertTrue(Z2.internalX1Ref.javaGetter!!.name.startsWith("getInternalX1$suffix\$"), Z2.internalX1Ref.javaGetter!!.name)
assertTrue(Z2.internalX2Ref.javaGetter!!.name.startsWith("getInternalX2\$"), Z2.internalX2Ref.javaGetter!!.name)
assertTrue(Z2.internalX1BoundRef.javaGetter!!.name.startsWith("getInternalX1$suffix\$"), Z2.internalX1BoundRef.javaGetter!!.name)
assertTrue(Z2.internalX2BoundRef.javaGetter!!.name.startsWith("getInternalX2\$"), Z2.internalX2BoundRef.javaGetter!!.name)
assertEquals(null, Z3.privateX1Ref.javaGetter)
assertEquals(null, Z3.privateX2Ref.javaGetter)
assertEquals(null, Z3.privateX1BoundRef.javaGetter)
assertEquals(null, Z3.privateX2BoundRef.javaGetter)
assertEquals("getPublicX", Z1_2.publicXRef.javaGetter!!.name)
assertEquals("getPublicX", Z1_2.publicXBoundRef.javaGetter!!.name)
assertTrue(Z2_2.internalXRef.javaGetter!!.name.startsWith("getInternalX\$"), Z2_2.internalXRef.javaGetter!!.name)
assertTrue(Z2_2.internalXBoundRef.javaGetter!!.name.startsWith("getInternalX\$"), Z2_2.internalXBoundRef.javaGetter!!.name)
assertEquals("getPrivateX", Z3_2.privateXRef.javaGetter!!.name)
assertEquals("getPrivateX", Z3_2.privateXBoundRef.javaGetter!!.name)
return "OK"
}
@@ -0,0 +1,49 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
package test
import kotlin.reflect.*
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@JvmInline
value class Z(val value1: UInt, val value2: String)
class S {
suspend fun consumeZ(z: Z) {}
suspend fun produceZ(): Z = Z(0U, "")
suspend fun consumeAndProduceZ(z: Z): Z = z
}
fun box(): String {
val members = S::class.members.filterIsInstance<KFunction<*>>().associateBy(KFunction<*>::name)
members["consumeZ"]!!.let { cz ->
val czj = cz.javaMethod!!
assertTrue(czj.name.startsWith("consumeZ-"), czj.name)
assertEquals("int, java.lang.String, kotlin.coroutines.Continuation", czj.parameterTypes.joinToString { it.name })
val czjk = czj.kotlinFunction
assertEquals(cz, czjk)
}
members["produceZ"]!!.let { pz ->
val pzj = pz.javaMethod!!
assertEquals("produceZ", pzj.name)
assertEquals("kotlin.coroutines.Continuation", pzj.parameterTypes.joinToString { it.name })
val pzjk = pzj!!.kotlinFunction
assertEquals(pz, pzjk)
}
members["consumeAndProduceZ"]!!.let { cpz ->
val cpzj = cpz.javaMethod!!
assertTrue(cpzj.name.startsWith("consumeAndProduceZ-"), cpzj.name)
assertEquals("int, java.lang.String, kotlin.coroutines.Continuation", cpzj.parameterTypes.joinToString { it.name })
val cpzjk = cpzj!!.kotlinFunction
assertEquals(cpz, cpzjk)
}
return "OK"
}