Support KCallable.call
#KT-2187 Fixed
This commit is contained in:
+25
@@ -0,0 +1,25 @@
|
||||
class A
|
||||
|
||||
data class D(val s: String)
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
assert(A::equals.call(a, a))
|
||||
assert(!A::equals.call(a, 0))
|
||||
assert(A::hashCode.call(a) == A::hashCode.call(a))
|
||||
assert(A::toString.call(a).startsWith("A@"))
|
||||
|
||||
assert(D::equals.call(D("foo"), D("foo")))
|
||||
assert(!D::equals.call(D("foo"), D("bar")))
|
||||
assert(D::hashCode.call(D("foo")) == D::hashCode.call(D("foo")))
|
||||
assert(D::toString.call(D("foo")) == "D(s=foo)")
|
||||
|
||||
assert(Int::equals.call(-1, -1))
|
||||
assert(Int::hashCode.call(0) != Int::hashCode.call(1))
|
||||
assert(Int::toString.call(42) == "42")
|
||||
|
||||
assert(String::equals.call("beer", "beer"))
|
||||
String::hashCode.call("beer")
|
||||
|
||||
return String::toString.call("OK")
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// FULL_JDK
|
||||
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
|
||||
fun fail(message: String) {
|
||||
throw AssertionError(message)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
::fail.call("OK")
|
||||
} catch (e: InvocationTargetException) {
|
||||
return e.getTargetException().getMessage().toString()
|
||||
}
|
||||
|
||||
return "Fail: no exception was thrown"
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class A {
|
||||
class Nested(val result: String)
|
||||
inner class Inner(val result: String)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return (A::Nested).call("O").result + (A::Inner).call((::A).call(), "K").result
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import kotlin.platform.platformStatic as static
|
||||
|
||||
object Obj {
|
||||
static fun foo() {}
|
||||
}
|
||||
|
||||
class C {
|
||||
companion object {
|
||||
static fun bar() {}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
(Obj::foo).call(Obj)
|
||||
(C.Companion::bar).call(C.Companion)
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
import kotlin.platform.platformStatic as static
|
||||
|
||||
object Obj {
|
||||
static fun foo(s: String) {}
|
||||
static fun bar() {}
|
||||
static fun sly(obj: Obj) {}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
// This should succeed
|
||||
(Obj::foo).call(Obj, "")
|
||||
(Obj::bar).call(Obj)
|
||||
(Obj::sly).call(Obj, Obj)
|
||||
|
||||
// This shouldn't: first argument should always be Obj
|
||||
try {
|
||||
(Obj::foo).call(null, "")
|
||||
return "Fail foo"
|
||||
} catch (e: IllegalArgumentException) {}
|
||||
|
||||
try {
|
||||
(Obj::bar).call("")
|
||||
return "Fail bar"
|
||||
} catch (e: IllegalArgumentException) {}
|
||||
|
||||
try {
|
||||
(Obj::sly).call(Obj)
|
||||
return "Fail sly 1"
|
||||
} catch (e: IllegalArgumentException) {}
|
||||
|
||||
try {
|
||||
(Obj::sly).call(null, Obj)
|
||||
return "Fail sly 2"
|
||||
} catch (e: IllegalArgumentException) {}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.jvm.*
|
||||
import kotlin.test.*
|
||||
|
||||
class A(private var result: String)
|
||||
|
||||
fun box(): String {
|
||||
val a = A("abc")
|
||||
|
||||
val p = A::class.declaredProperties.single() as KMutableProperty1<A, String>
|
||||
p.accessible = true
|
||||
assertEquals("abc", p.call(a))
|
||||
assertEquals(Unit, p.setter.call(a, "def"))
|
||||
assertEquals("def", p.getter.call(a))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import kotlin.reflect.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
val p0 = 1
|
||||
val Int.p1: Int get() = this
|
||||
class A {
|
||||
val Int.p2: Int get() = this
|
||||
}
|
||||
|
||||
var globalCounter = 0
|
||||
|
||||
var mp0 = 1
|
||||
set(value) { globalCounter += value }
|
||||
var Int.mp1: Int
|
||||
get() = this
|
||||
set(value) { globalCounter += value }
|
||||
class B {
|
||||
var Int.mp2: Int
|
||||
get() = this
|
||||
set(value) { globalCounter += value }
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(1, (::p0).call())
|
||||
assertEquals(1, (::p0).getter.call())
|
||||
assertEquals(2, (Int::p1).call(2))
|
||||
assertEquals(2, (Int::p1).getter.call(2))
|
||||
val p2 = A::class.extensionProperties.single()
|
||||
assertEquals(3, p2.call(A(), 3))
|
||||
assertEquals(3, p2.getter.call(A(), 3))
|
||||
|
||||
assertEquals(1, (::mp0).call())
|
||||
assertEquals(1, (::mp0).getter.call())
|
||||
assertEquals(2, (Int::mp1).call(2))
|
||||
assertEquals(2, (Int::mp1).getter.call(2))
|
||||
val mp2 = B::class.extensionProperties.single() as KMutableProperty2
|
||||
assertEquals(3, mp2.call(B(), 3))
|
||||
assertEquals(3, mp2.getter.call(B(), 3))
|
||||
|
||||
assertEquals(Unit, (::mp0).setter.call(1))
|
||||
assertEquals(Unit, (Int::mp1).setter.call(0, 3))
|
||||
assertEquals(Unit, mp2.setter.call(B(), 0, 5))
|
||||
if (globalCounter != 9) return "Fail: $globalCounter"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun foo() {}
|
||||
|
||||
class A {
|
||||
fun bar() {}
|
||||
}
|
||||
|
||||
object O {
|
||||
kotlin.platform.platformStatic fun baz() {}
|
||||
}
|
||||
|
||||
fun nullableUnit(unit: Boolean): Unit? = if (unit) Unit else null
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(Unit, ::foo.call())
|
||||
assertEquals(Unit, A::bar.call(A()))
|
||||
assertEquals(Unit, O::baz.call(O))
|
||||
|
||||
assertEquals(Unit, (::nullableUnit).call(true))
|
||||
assertEquals(null, (::nullableUnit).call(false))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
class A(val result: String)
|
||||
|
||||
fun box(): String {
|
||||
val a = (::A).call("OK")
|
||||
return a.result
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
class A {
|
||||
fun foo(x: Int, y: Int) = x + y
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val x = (A::foo).call(A(), 42, 239)
|
||||
if (x != 281) return "Fail: $x"
|
||||
|
||||
try {
|
||||
(A::foo).call()
|
||||
return "Fail: no exception"
|
||||
}
|
||||
catch (e: Exception) {}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
fun String.foo(): Int = length()
|
||||
|
||||
var state = "Fail"
|
||||
|
||||
fun bar(result: String) {
|
||||
state = result
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val f = (String::foo).call("abc")
|
||||
if (f != 3) return "Fail: $f"
|
||||
|
||||
try {
|
||||
(String::foo).call()
|
||||
return "Fail: IllegalArgumentException should have been thrown"
|
||||
}
|
||||
catch (e: IllegalArgumentException) {}
|
||||
|
||||
try {
|
||||
(String::foo).call(42)
|
||||
return "Fail: IllegalArgumentException should have been thrown"
|
||||
}
|
||||
catch (e: IllegalArgumentException) {}
|
||||
|
||||
(::bar).call("OK")
|
||||
return state
|
||||
}
|
||||
+75
@@ -2767,6 +2767,81 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Call extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInCall() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/call"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("equalsHashCodeToString.kt")
|
||||
public void testEqualsHashCodeToString() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/equalsHashCodeToString.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("exceptionHappened.kt")
|
||||
public void testExceptionHappened() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/exceptionHappened.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassConstructor.kt")
|
||||
public void testInnerClassConstructor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/innerClassConstructor.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("platformStatic.kt")
|
||||
public void testPlatformStatic() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/platformStatic.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("platformStaticInObjectIncorrectReceiver.kt")
|
||||
public void testPlatformStaticInObjectIncorrectReceiver() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/platformStaticInObjectIncorrectReceiver.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateProperty.kt")
|
||||
public void testPrivateProperty() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/privateProperty.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccessors.kt")
|
||||
public void testPropertyAccessors() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/propertyAccessors.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnit.kt")
|
||||
public void testReturnUnit() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/returnUnit.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleConstructor.kt")
|
||||
public void testSimpleConstructor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/simpleConstructor.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleMemberFunction.kt")
|
||||
public void testSimpleMemberFunction() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/simpleMemberFunction.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleTopLevelFunctions.kt")
|
||||
public void testSimpleTopLevelFunctions() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/call/simpleTopLevelFunctions.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -34,6 +34,15 @@ public interface KCallable<out R> {
|
||||
|
||||
/**
|
||||
* Parameters required to make a call to this callable.
|
||||
* If this callable requires a `this` instance or an extension receiver parameter,
|
||||
* they come first in the list in that order.
|
||||
*/
|
||||
public val parameters: List<KParameter>
|
||||
|
||||
/**
|
||||
* Calls this callable with the specified arguments and returns the result.
|
||||
* Throws an exception if the number of specified arguments is not equal to the size of [parameters],
|
||||
* or if their types do not match the types of the parameters.
|
||||
*/
|
||||
public fun call(vararg args: Any?): R
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ public interface KParameter {
|
||||
public val name: String?
|
||||
|
||||
/**
|
||||
* Type of this parameter.
|
||||
* Type of this parameter. For a `vararg` parameter, this is the type of the corresponding array,
|
||||
* not the individual element.
|
||||
*/
|
||||
public val type: KType
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import java.lang.reflect.Constructor as ReflectConstructor
|
||||
import java.lang.reflect.Method as ReflectMethod
|
||||
|
||||
internal sealed class FunctionCaller {
|
||||
abstract fun call(args: Array<*>): Any?
|
||||
|
||||
class Constructor(val constructor: ReflectConstructor<*>) : FunctionCaller() {
|
||||
override fun call(args: Array<*>): Any? {
|
||||
return constructor.newInstance(*args)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Method(val method: ReflectMethod) : FunctionCaller() {
|
||||
private val isVoidMethod = method.returnType == Void.TYPE
|
||||
|
||||
protected fun callMethod(instance: Any?, args: Array<*>): Any? {
|
||||
val result = method.invoke(instance, *args)
|
||||
|
||||
// If this is a Unit function, the method returns void, Method#invoke returns null, while we should return Unit
|
||||
return if (isVoidMethod) Unit else result
|
||||
}
|
||||
}
|
||||
|
||||
class StaticMethod(method: ReflectMethod) : Method(method) {
|
||||
override fun call(args: Array<*>): Any? {
|
||||
return callMethod(null, args)
|
||||
}
|
||||
}
|
||||
|
||||
class InstanceMethod(method: ReflectMethod) : Method(method) {
|
||||
override fun call(args: Array<*>): Any? {
|
||||
return callMethod(args[0], args.asList().subList(1, args.size()).toTypedArray())
|
||||
}
|
||||
}
|
||||
|
||||
class PlatformStaticInObject(method: ReflectMethod) : Method(method) {
|
||||
override fun call(args: Array<*>): Any? {
|
||||
if (args.isEmpty() || !method.declaringClass.isInstance(args[0])) {
|
||||
throw IllegalArgumentException("A function in an object requires the object instance passed as the first argument.")
|
||||
}
|
||||
return callMethod(null, args.asList().subList(1, args.size()).toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.ReflectJavaConstructor
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.ReflectJavaMethod
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.jvm.internal.FunctionImpl
|
||||
import kotlin.reflect.*
|
||||
|
||||
@@ -68,7 +70,7 @@ open class KFunctionImpl protected constructor(
|
||||
}
|
||||
|
||||
internal val javaMethod: Method? by ReflectProperties.lazySoft {
|
||||
if (name != "<init>") {
|
||||
if (!isConstructor) {
|
||||
val proto = protoData
|
||||
if (proto != null) {
|
||||
container.findMethodBySignature(proto.proto, proto.signature, proto.nameResolver,
|
||||
@@ -82,7 +84,7 @@ open class KFunctionImpl protected constructor(
|
||||
}
|
||||
|
||||
internal val javaConstructor: Constructor<*>? by ReflectProperties.lazySoft {
|
||||
if (name == "<init>") {
|
||||
if (isConstructor) {
|
||||
val proto = protoData
|
||||
if (proto != null) {
|
||||
return@lazySoft container.findConstructorBySignature(
|
||||
@@ -98,6 +100,22 @@ open class KFunctionImpl protected constructor(
|
||||
|
||||
override val name: String get() = descriptor.getName().asString()
|
||||
|
||||
private val caller: FunctionCaller by ReflectProperties.lazySoft {
|
||||
javaConstructor?.let { FunctionCaller.Constructor(it) } ?:
|
||||
javaMethod?.let { method ->
|
||||
when {
|
||||
!Modifier.isStatic(method.modifiers) -> FunctionCaller.InstanceMethod(method)
|
||||
descriptor.annotations.findAnnotation(PLATFORM_STATIC) != null -> FunctionCaller.PlatformStaticInObject(method)
|
||||
else -> FunctionCaller.StaticMethod(method)
|
||||
}
|
||||
} ?:
|
||||
throw KotlinReflectionInternalError("Call is not yet supported for this function: $descriptor")
|
||||
}
|
||||
|
||||
override fun call(vararg args: Any?): Any? = caller.call(args)
|
||||
|
||||
private val isConstructor: Boolean get() = name == "<init>"
|
||||
|
||||
override fun getArity(): Int {
|
||||
// TODO: test?
|
||||
return descriptor.getValueParameters().size() +
|
||||
@@ -113,4 +131,8 @@ open class KFunctionImpl protected constructor(
|
||||
|
||||
override fun toString(): String =
|
||||
ReflectionObjectRenderer.renderFunction(descriptor)
|
||||
|
||||
private companion object {
|
||||
val PLATFORM_STATIC = FqName("kotlin.platform.platformStatic")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,11 @@ open class KProperty0Impl<out R> : DescriptorBasedProperty<R>, KProperty0<R>, KP
|
||||
}
|
||||
}
|
||||
|
||||
override fun call(vararg args: Any?): R {
|
||||
require(args.isEmpty()) { "Property $name expects no arguments, but ${args.size()} were provided." }
|
||||
return get()
|
||||
}
|
||||
|
||||
class Getter<out R>(override val property: KProperty0Impl<R>) : KPropertyImpl.Getter<R>(), KProperty0.Getter<R> {
|
||||
override fun invoke(): R = property.get()
|
||||
}
|
||||
@@ -70,6 +75,12 @@ open class KMutableProperty0Impl<R> : KProperty0Impl<R>, KMutableProperty0<R>, K
|
||||
|
||||
class Setter<R>(override val property: KMutableProperty0Impl<R>) : KMutablePropertyImpl.Setter<R>(), KMutableProperty0.Setter<R> {
|
||||
override fun invoke(value: R): Unit = property.set(value)
|
||||
|
||||
@suppress("UNCHECKED_CAST")
|
||||
override fun call(vararg args: Any?) {
|
||||
require(args.size() == 1) { "Property setter for ${property.name} expects one argument, but ${args.size()} were provided." }
|
||||
property.set(args.single() as R)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,12 @@ open class KProperty1Impl<T, out R> : DescriptorBasedProperty<R>, KProperty1<T,
|
||||
}
|
||||
}
|
||||
|
||||
@suppress("UNCHECKED_CAST")
|
||||
override fun call(vararg args: Any?): R {
|
||||
require(args.size() == 1) { "Property $name expects one argument, but ${args.size()} were provided." }
|
||||
return get(args.single() as T)
|
||||
}
|
||||
|
||||
class Getter<T, out R>(override val property: KProperty1Impl<T, R>) : KPropertyImpl.Getter<R>(), KProperty1.Getter<T, R> {
|
||||
override fun invoke(receiver: T): R = property.get(receiver)
|
||||
}
|
||||
@@ -94,6 +100,12 @@ open class KMutableProperty1Impl<T, R> : KProperty1Impl<T, R>, KMutableProperty1
|
||||
|
||||
class Setter<T, R>(override val property: KMutableProperty1Impl<T, R>) : KMutablePropertyImpl.Setter<R>(), KMutableProperty1.Setter<T, R> {
|
||||
override fun invoke(receiver: T, value: R): Unit = property.set(receiver, value)
|
||||
|
||||
@suppress("UNCHECKED_CAST")
|
||||
override fun call(vararg args: Any?) {
|
||||
require(args.size() == 2) { "Property setter for ${property.name} expects two arguments, but ${args.size()} were provided." }
|
||||
property.set(args[0] as T, args[1] as R)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,12 @@ open class KProperty2Impl<D, E, out R> : DescriptorBasedProperty<R>, KProperty2<
|
||||
}
|
||||
}
|
||||
|
||||
@suppress("UNCHECKED_CAST")
|
||||
override fun call(vararg args: Any?): R {
|
||||
require(args.size() == 2) { "Property $name expects two arguments, but ${args.size()} were provided." }
|
||||
return get(args[0] as D, args[1] as E)
|
||||
}
|
||||
|
||||
class Getter<D, E, out R>(override val property: KProperty2Impl<D, E, R>) : KPropertyImpl.Getter<R>(), KProperty2.Getter<D, E, R> {
|
||||
override fun invoke(receiver1: D, receiver2: E): R = property.get(receiver1, receiver2)
|
||||
}
|
||||
@@ -72,5 +78,11 @@ class KMutableProperty2Impl<D, E, R> : KProperty2Impl<D, E, R>, KMutableProperty
|
||||
|
||||
class Setter<D, E, R>(override val property: KMutableProperty2Impl<D, E, R>) : KMutablePropertyImpl.Setter<R>(), KMutableProperty2.Setter<D, E, R> {
|
||||
override fun invoke(receiver1: D, receiver2: E, value: R): Unit = property.set(receiver1, receiver2, value)
|
||||
|
||||
@suppress("UNCHECKED_CAST")
|
||||
override fun call(vararg args: Any?) {
|
||||
require(args.size() == 3) { "Property setter for ${property.name} expects three arguments, but ${args.size()} were provided." }
|
||||
property.set(args[0] as D, args[1] as E, args[2] as R)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ interface KPropertyImpl<out R> : KProperty<R>, KCallableImpl<R> {
|
||||
// TODO: default getter created this way won't have any source information
|
||||
property.descriptor.getGetter() ?: DescriptorFactory.createDefaultGetter(property.descriptor)
|
||||
}
|
||||
|
||||
override fun call(vararg args: Any?): R = property.call(*args)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import kotlin.jvm.KotlinReflectionNotSupportedError;
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
import kotlin.reflect.KParameter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -68,6 +69,11 @@ public abstract class CallableReference implements KCallable {
|
||||
throw error();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(@NotNull Object... args) {
|
||||
throw error();
|
||||
}
|
||||
|
||||
protected static Error error() {
|
||||
throw new KotlinReflectionNotSupportedError();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.jvm.KotlinReflectionNotSupportedError;
|
||||
import kotlin.reflect.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -65,6 +66,11 @@ public class FunctionReference
|
||||
throw error();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(@NotNull Object... args) {
|
||||
throw error();
|
||||
}
|
||||
|
||||
protected static Error error() {
|
||||
throw new KotlinReflectionNotSupportedError();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user