Support inline classes in function signatures in call/callBy
#KT-25664 Fixed #KT-26748 Open #KT-26765 Open
This commit is contained in:
+37
@@ -0,0 +1,37 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KCallable
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline class S(val value: String) {
|
||||
operator fun plus(other: S): S = S(this.value + other.value)
|
||||
}
|
||||
|
||||
class C {
|
||||
private var member: S = S("")
|
||||
|
||||
fun unboundRef() = C::member.apply { isAccessible = true }
|
||||
fun boundRef() = this::member.apply { isAccessible = true }
|
||||
}
|
||||
|
||||
private var topLevel: S = S("")
|
||||
|
||||
fun box(): String {
|
||||
val c = C()
|
||||
assertEquals(Unit, c.unboundRef().setter.call(c, S("ab")))
|
||||
assertEquals(S("ab"), c.unboundRef().call(c))
|
||||
assertEquals(S("ab"), c.unboundRef().getter.call(c))
|
||||
|
||||
assertEquals(Unit, c.boundRef().setter.call(S("cd")))
|
||||
assertEquals(S("cd"), c.boundRef().call())
|
||||
assertEquals(S("cd"), c.boundRef().getter.call())
|
||||
|
||||
val topLevel = ::topLevel.apply { isAccessible = true }
|
||||
assertEquals(Unit, topLevel.setter.call(S("ef")))
|
||||
assertEquals(S("ef"), topLevel.call())
|
||||
assertEquals(S("ef"), topLevel.getter.call())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline class S(val value: String) {
|
||||
operator fun plus(other: S): S = S(this.value + other.value)
|
||||
}
|
||||
|
||||
class C {
|
||||
fun member(x: S, y: String): S = x + S(y)
|
||||
}
|
||||
|
||||
fun topLevel(x: String, y: S): S = S(x) + y
|
||||
|
||||
/* TODO: support constructors with inline class types in the signature (KT-26765)
|
||||
class D {
|
||||
inner class Inner(x: S, y: S) {
|
||||
val result = x + y
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
fun S.extension(y: S): S = this + y
|
||||
|
||||
fun S.extension2(): String = value
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(S("ab"), C::member.call(C(), S("a"), "b"))
|
||||
assertEquals(S("cd"), ::topLevel.call("c", S("d")))
|
||||
// assertEquals(S("ef"), D::Inner.call(D(), S("e"), S("f")).result)
|
||||
assertEquals(S("gh"), S::extension.call(S("g"), S("h")))
|
||||
assertEquals("_", S::extension2.call(S("_")))
|
||||
|
||||
assertEquals(S("ij"), C()::member.call(S("i"), "j"))
|
||||
// assertEquals(S("kl"), D()::Inner.call(S("k"), S("l")).result)
|
||||
assertEquals(S("mn"), S("m")::extension.call(S("n")))
|
||||
assertEquals("_", S("_")::extension2.call())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline class S(val value: String) {
|
||||
operator fun plus(other: S): S = S(this.value + other.value)
|
||||
}
|
||||
|
||||
object C {
|
||||
@JvmStatic
|
||||
private var p: S = S("")
|
||||
|
||||
fun boundRef() = this::p.apply { isAccessible = true }
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val unboundRef = C::class.members.single { it.name == "p" } as KMutableProperty1<C, S>
|
||||
unboundRef.isAccessible = true
|
||||
assertEquals(Unit, unboundRef.setter.call(C, S("ab")))
|
||||
assertEquals(S("ab"), unboundRef.call(C))
|
||||
assertEquals(S("ab"), unboundRef.getter.call(C))
|
||||
|
||||
val boundRef = C.boundRef()
|
||||
assertEquals(Unit, boundRef.setter.call(S("cd")))
|
||||
assertEquals(S("cd"), boundRef.call())
|
||||
assertEquals(S("cd"), boundRef.getter.call())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline class S(val value: String) {
|
||||
operator fun plus(other: S): S = S(this.value + other.value)
|
||||
}
|
||||
|
||||
object C {
|
||||
@JvmStatic
|
||||
fun foo(x: S, y: String): S = x + S(y)
|
||||
}
|
||||
|
||||
interface I {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun bar(x: String, y: S): S = S(x) + y
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(S("ab"), C::foo.call(S("a"), "b"))
|
||||
assertEquals(S("cd"), (I)::bar.call("c", S("d")))
|
||||
|
||||
val unboundFoo = C::class.members.single { it.name == "foo" } as KFunction<*>
|
||||
assertEquals(S("ef"), unboundFoo.call(C, S("e"), "f"))
|
||||
|
||||
val unboundBar = I.Companion::class.members.single { it.name == "bar" } as KFunction<*>
|
||||
assertEquals(S("gh"), unboundBar.call(I, "g", S("h")))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KMutableProperty2
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline class S(val value: String) {
|
||||
operator fun plus(other: S): S = S(this.value + other.value)
|
||||
}
|
||||
|
||||
class C {
|
||||
var member: S = S("")
|
||||
|
||||
private var suffix = S("")
|
||||
var S.memExt: S
|
||||
get() = this + suffix
|
||||
set(value) { suffix = this + value }
|
||||
}
|
||||
|
||||
var topLevel: S = S("")
|
||||
|
||||
private var suffix = S("")
|
||||
var S.ext: S
|
||||
get() = this + suffix
|
||||
set(value) { suffix = this + value }
|
||||
|
||||
fun box(): String {
|
||||
val c = C()
|
||||
assertEquals(Unit, C::member.setter.call(c, S("ab")))
|
||||
assertEquals(S("ab"), C::member.call(c))
|
||||
assertEquals(S("ab"), C::member.getter.call(c))
|
||||
|
||||
assertEquals(Unit, c::member.setter.call(S("cd")))
|
||||
assertEquals(S("cd"), c::member.call())
|
||||
assertEquals(S("cd"), c::member.getter.call())
|
||||
|
||||
val memExt = C::class.members.single { it.name == "memExt" } as KMutableProperty2<C, S, S>
|
||||
assertEquals(Unit, memExt.setter.call(c, S(""), S("f")))
|
||||
assertEquals(S("ef"), memExt.call(c, S("e")))
|
||||
assertEquals(S("ef"), memExt.getter.call(c, S("e")))
|
||||
|
||||
assertEquals(Unit, ::topLevel.setter.call(S("gh")))
|
||||
assertEquals(S("gh"), ::topLevel.call())
|
||||
assertEquals(S("gh"), ::topLevel.getter.call())
|
||||
|
||||
assertEquals(Unit, S::ext.setter.call(S(""), S("j")))
|
||||
assertEquals(S("ij"), S::ext.call(S("i")))
|
||||
assertEquals(S("ij"), S::ext.getter.call(S("i")))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline class S(val value: String) {
|
||||
operator fun plus(other: S): S = S(this.value + other.value)
|
||||
}
|
||||
|
||||
class C {
|
||||
fun member(a: S, b: S = S("b")): S = a + b
|
||||
}
|
||||
|
||||
fun topLevel(c: S, d: S = S("d")): S = c + d
|
||||
|
||||
/* TODO: support constructors with inline class types in the signature (KT-26765)
|
||||
class D(e: S, f: S = S("f")) {
|
||||
val result = e + f
|
||||
}
|
||||
*/
|
||||
|
||||
fun S.extension(h: S = S("h")): S = this + h
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(S("ab"), C::member.callBy(C::member.parameters.filter { it.name != "b" }.associate {
|
||||
it to (if (it.name == "a") S("a") else C())
|
||||
}))
|
||||
|
||||
assertEquals(S("cd"), ::topLevel.callBy(::topLevel.parameters.filter { it.name != "d" }.associate { it to S("c") }))
|
||||
|
||||
// assertEquals(S("ef"), ::D.callBy(::D.parameters.filter { it.name != "f" }.associate { it to S("e") }).result)
|
||||
|
||||
assertEquals(S("gh"), S::extension.callBy(S::extension.parameters.filter { it.name != "h" }.associate { it to S("g") }))
|
||||
|
||||
|
||||
val boundMember = C()::member
|
||||
assertEquals(S("ab"), boundMember.callBy(boundMember.parameters.associate { it to S(it.name!!) }))
|
||||
|
||||
val boundExtension = S("g")::extension
|
||||
assertEquals(S("gh"), boundExtension.callBy(boundExtension.parameters.associate { it to S(it.name!!) }))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// IGNORE_BACKEND: JVM_IR, JS_IR, JS, NATIVE
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.jvm.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
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(S::class.java, S::foo.returnType.javaType)
|
||||
|
||||
/*
|
||||
assertEquals(listOf(), T::bar.parameters.map { it.type.javaType })
|
||||
assertEquals(String::class.java, T::bar.returnType.javaType)
|
||||
*/
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user