Support KCallable.callBy with map of parameters to arguments
callBy is able to handle optional parameters. #KT-8827 Fixed
This commit is contained in:
@@ -25,16 +25,17 @@ import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class ArgumentGenerator {
|
public abstract class ArgumentGenerator {
|
||||||
/**
|
/**
|
||||||
* @return a {@code List} of bit masks of default arguments that should be passed as last arguments to $default method, if there were
|
* @return a {@code List} of bit masks of default arguments that should be passed as last arguments to $default method, if there were
|
||||||
* any default arguments, or an empty {@code List} if there were none
|
* any default arguments, or an empty {@code List} if there were none
|
||||||
|
* @see kotlin.reflect.jvm.internal.KCallableImpl#callBy(Map...)
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<Integer> generate(@NotNull List<ResolvedValueArgument> valueArguments) {
|
public List<Integer> generate(@NotNull List<ResolvedValueArgument> valueArguments) {
|
||||||
List<Integer> masks = new ArrayList<Integer>(1);
|
List<Integer> masks = new ArrayList<Integer>(1);
|
||||||
boolean maskIsNeeded = false;
|
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
int n = valueArguments.size();
|
int n = valueArguments.size();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
@@ -47,7 +48,6 @@ public abstract class ArgumentGenerator {
|
|||||||
generateExpression(i, (ExpressionValueArgument) argument);
|
generateExpression(i, (ExpressionValueArgument) argument);
|
||||||
}
|
}
|
||||||
else if (argument instanceof DefaultValueArgument) {
|
else if (argument instanceof DefaultValueArgument) {
|
||||||
maskIsNeeded = true;
|
|
||||||
mask |= 1 << (i % Integer.SIZE);
|
mask |= 1 << (i % Integer.SIZE);
|
||||||
generateDefault(i, (DefaultValueArgument) argument);
|
generateDefault(i, (DefaultValueArgument) argument);
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ public abstract class ArgumentGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!maskIsNeeded) {
|
if (mask == 0 && masks.isEmpty()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+15
@@ -0,0 +1,15 @@
|
|||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun foo(a: String, b: String = "b", c: String, d: String = "d", e: String) =
|
||||||
|
a + b + c + d + e
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = ::foo.parameters
|
||||||
|
assertEquals("abcde", ::foo.callBy(mapOf(
|
||||||
|
p[0] to "a",
|
||||||
|
p[2] to "c",
|
||||||
|
p[4] to "e"
|
||||||
|
)))
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun String.sum(other: String = "b") = this + other
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val f = String::sum
|
||||||
|
assertEquals("ab", f.callBy(mapOf(f.parameters.first() to "a")))
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
// Generate:
|
||||||
|
// (1..70).map { " p${"%02d".format(it)}: Int," }.joinToString("\n")
|
||||||
|
|
||||||
|
class A {
|
||||||
|
fun foo(
|
||||||
|
p01: Int,
|
||||||
|
p02: Int,
|
||||||
|
p03: Int,
|
||||||
|
p04: Int,
|
||||||
|
p05: Int,
|
||||||
|
p06: Int,
|
||||||
|
p07: Int,
|
||||||
|
p08: Int,
|
||||||
|
p09: Int,
|
||||||
|
p10: Int,
|
||||||
|
p11: Int,
|
||||||
|
p12: Int,
|
||||||
|
p13: Int,
|
||||||
|
p14: Int,
|
||||||
|
p15: Int,
|
||||||
|
p16: Int,
|
||||||
|
p17: Int,
|
||||||
|
p18: Int,
|
||||||
|
p19: Int,
|
||||||
|
p20: Int,
|
||||||
|
p21: Int,
|
||||||
|
p22: Int,
|
||||||
|
p23: Int,
|
||||||
|
p24: Int,
|
||||||
|
p25: Int,
|
||||||
|
p26: Int,
|
||||||
|
p27: Int,
|
||||||
|
p28: Int,
|
||||||
|
p29: Int,
|
||||||
|
p30: Int,
|
||||||
|
p31: Int,
|
||||||
|
p32: Int,
|
||||||
|
p33: Int,
|
||||||
|
p34: Int,
|
||||||
|
p35: Int,
|
||||||
|
p36: Int,
|
||||||
|
p37: Int,
|
||||||
|
p38: Int,
|
||||||
|
p39: Int,
|
||||||
|
p40: Int,
|
||||||
|
p41: Int,
|
||||||
|
p42: Int = 239,
|
||||||
|
p43: Int,
|
||||||
|
p44: Int,
|
||||||
|
p45: Int,
|
||||||
|
p46: Int,
|
||||||
|
p47: Int,
|
||||||
|
p48: Int,
|
||||||
|
p49: Int,
|
||||||
|
p50: Int,
|
||||||
|
p51: Int,
|
||||||
|
p52: Int,
|
||||||
|
p53: Int,
|
||||||
|
p54: Int,
|
||||||
|
p55: Int,
|
||||||
|
p56: Int,
|
||||||
|
p57: Int,
|
||||||
|
p58: Int,
|
||||||
|
p59: Int,
|
||||||
|
p60: Int,
|
||||||
|
p61: Int,
|
||||||
|
p62: Int,
|
||||||
|
p63: Int,
|
||||||
|
p64: Int,
|
||||||
|
p65: Int,
|
||||||
|
p66: Int,
|
||||||
|
p67: Int,
|
||||||
|
p68: Int,
|
||||||
|
p69: Int,
|
||||||
|
p70: Int
|
||||||
|
) {
|
||||||
|
assertEquals(1, p01)
|
||||||
|
assertEquals(41, p41)
|
||||||
|
assertEquals(239, p42)
|
||||||
|
assertEquals(43, p43)
|
||||||
|
assertEquals(70, p70)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val f = A::class.members.single { it.name == "foo" }
|
||||||
|
val parameters = f.parameters
|
||||||
|
|
||||||
|
f.callBy(mapOf(
|
||||||
|
parameters.first() to A(),
|
||||||
|
*((1..41) + (43..70)).map { i -> parameters[i] to i }.toTypedArray()
|
||||||
|
))
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+95
@@ -0,0 +1,95 @@
|
|||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
// Generate:
|
||||||
|
// (1..70).map { " p${"%02d".format(it)}: Int = $it," }.joinToString("\n")
|
||||||
|
|
||||||
|
class A {
|
||||||
|
fun foo(
|
||||||
|
p01: Int = 1,
|
||||||
|
p02: Int = 2,
|
||||||
|
p03: Int = 3,
|
||||||
|
p04: Int = 4,
|
||||||
|
p05: Int = 5,
|
||||||
|
p06: Int = 6,
|
||||||
|
p07: Int = 7,
|
||||||
|
p08: Int = 8,
|
||||||
|
p09: Int = 9,
|
||||||
|
p10: Int = 10,
|
||||||
|
p11: Int = 11,
|
||||||
|
p12: Int = 12,
|
||||||
|
p13: Int = 13,
|
||||||
|
p14: Int = 14,
|
||||||
|
p15: Int = 15,
|
||||||
|
p16: Int = 16,
|
||||||
|
p17: Int = 17,
|
||||||
|
p18: Int = 18,
|
||||||
|
p19: Int = 19,
|
||||||
|
p20: Int = 20,
|
||||||
|
p21: Int = 21,
|
||||||
|
p22: Int = 22,
|
||||||
|
p23: Int = 23,
|
||||||
|
p24: Int = 24,
|
||||||
|
p25: Int = 25,
|
||||||
|
p26: Int = 26,
|
||||||
|
p27: Int = 27,
|
||||||
|
p28: Int = 28,
|
||||||
|
p29: Int = 29,
|
||||||
|
p30: Int = 30,
|
||||||
|
p31: Int = 31,
|
||||||
|
p32: Int = 32,
|
||||||
|
p33: Int = 33,
|
||||||
|
p34: Int = 34,
|
||||||
|
p35: Int = 35,
|
||||||
|
p36: Int = 36,
|
||||||
|
p37: Int = 37,
|
||||||
|
p38: Int = 38,
|
||||||
|
p39: Int = 39,
|
||||||
|
p40: Int = 40,
|
||||||
|
p41: Int = 41,
|
||||||
|
p42: Int,
|
||||||
|
p43: Int = 43,
|
||||||
|
p44: Int = 44,
|
||||||
|
p45: Int = 45,
|
||||||
|
p46: Int = 46,
|
||||||
|
p47: Int = 47,
|
||||||
|
p48: Int = 48,
|
||||||
|
p49: Int = 49,
|
||||||
|
p50: Int = 50,
|
||||||
|
p51: Int = 51,
|
||||||
|
p52: Int = 52,
|
||||||
|
p53: Int = 53,
|
||||||
|
p54: Int = 54,
|
||||||
|
p55: Int = 55,
|
||||||
|
p56: Int = 56,
|
||||||
|
p57: Int = 57,
|
||||||
|
p58: Int = 58,
|
||||||
|
p59: Int = 59,
|
||||||
|
p60: Int = 60,
|
||||||
|
p61: Int = 61,
|
||||||
|
p62: Int = 62,
|
||||||
|
p63: Int = 63,
|
||||||
|
p64: Int = 64,
|
||||||
|
p65: Int = 65,
|
||||||
|
p66: Int = 66,
|
||||||
|
p67: Int = 67,
|
||||||
|
p68: Int = 68,
|
||||||
|
p69: Int = 69,
|
||||||
|
p70: Int = 70
|
||||||
|
) {
|
||||||
|
assertEquals(1, p01)
|
||||||
|
assertEquals(41, p41)
|
||||||
|
assertEquals(239, p42)
|
||||||
|
assertEquals(43, p43)
|
||||||
|
assertEquals(70, p70)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val f = A::class.members.single { it.name == "foo" }
|
||||||
|
val parameters = f.parameters
|
||||||
|
f.callBy(mapOf(
|
||||||
|
parameters.first() to A(),
|
||||||
|
parameters.single { it.name == "p42" } to 239
|
||||||
|
))
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
fun foo(x: Int, y: Int = 2) = x + y
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
try {
|
||||||
|
::foo.callBy(mapOf())
|
||||||
|
return "Fail: IllegalArgumentException must have been thrown"
|
||||||
|
}
|
||||||
|
catch (e: IllegalArgumentException) {
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
::foo.callBy(mapOf(::foo.parameters.last() to 1))
|
||||||
|
return "Fail: IllegalArgumentException must have been thrown"
|
||||||
|
}
|
||||||
|
catch (e: IllegalArgumentException) {
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import kotlin.test.assertNull
|
||||||
|
|
||||||
|
fun foo(x: String? = "Fail") {
|
||||||
|
assertNull(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
::foo.callBy(mapOf(::foo.parameters.single() to null))
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun foo(result: String = "foo") {
|
||||||
|
assertEquals("box", result)
|
||||||
|
|
||||||
|
// Check that this function was invoked directly and not through the "foo$default", i.e. there's no "foo$default" in the stack trace
|
||||||
|
val st = Thread.currentThread().stackTrace
|
||||||
|
for (i in 0..5) {
|
||||||
|
if ("foo\$default" in st[i].methodName) {
|
||||||
|
throw AssertionError("KCallable.call should invoke the method directly if all arguments are provided")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
::foo.callBy(mapOf(::foo.parameters.single() to "box"))
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
import kotlin.platform.platformStatic as static
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
object Obj {
|
||||||
|
static fun foo(a: String, b: String = "b") = a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val f = Obj::foo
|
||||||
|
|
||||||
|
// Any object method currently requires the object instance passed
|
||||||
|
try {
|
||||||
|
f.callBy(mapOf(
|
||||||
|
f.parameters.single { it.name == "a" } to "a"
|
||||||
|
))
|
||||||
|
return "Fail: IllegalArgumentException should have been thrown"
|
||||||
|
}
|
||||||
|
catch (e: IllegalArgumentException) {
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("ab", f.callBy(mapOf(
|
||||||
|
f.parameters.first() to Obj,
|
||||||
|
f.parameters.single { it.name == "a" } to "a"
|
||||||
|
)))
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun primitives(
|
||||||
|
boolean: Boolean = true,
|
||||||
|
character: Char = 'z',
|
||||||
|
byte: Byte = 5.toByte(),
|
||||||
|
short: Short = (-5).toShort(),
|
||||||
|
int: Int = 2000000000,
|
||||||
|
float: Float = -2.72f,
|
||||||
|
long: Long = 1000000000000000000L,
|
||||||
|
double: Double = 3.14159265359
|
||||||
|
) {
|
||||||
|
assertEquals(true, boolean)
|
||||||
|
assertEquals('z', character)
|
||||||
|
assertEquals(5.toByte(), byte)
|
||||||
|
assertEquals((-5).toShort(), short)
|
||||||
|
assertEquals(2000000000, int)
|
||||||
|
assertEquals(-2.72f, float)
|
||||||
|
assertEquals(1000000000000000000L, long)
|
||||||
|
assertEquals(3.14159265359, double)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
::primitives.callBy(emptyMap())
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
import kotlin.reflect.IllegalCallableAccessException
|
||||||
|
import kotlin.reflect.jvm.isAccessible
|
||||||
|
|
||||||
|
class A {
|
||||||
|
private fun foo(default: Any? = this) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f() = A::foo
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A()
|
||||||
|
val f = a.f()
|
||||||
|
|
||||||
|
try {
|
||||||
|
f.callBy(mapOf(f.parameters.first() to a))
|
||||||
|
return "Fail: IllegalCallableAccessException should have been thrown"
|
||||||
|
}
|
||||||
|
catch (e: IllegalCallableAccessException) {
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
|
||||||
|
f.isAccessible = true
|
||||||
|
f.callBy(mapOf(f.parameters.first() to a))
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class A(val result: String = "OK")
|
||||||
|
|
||||||
|
fun box(): String = ::A.callBy(mapOf()).result
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
class A(val result: String = "OK") {
|
||||||
|
fun foo(x: Int = 42): String {
|
||||||
|
assert(x == 42) { x }
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String = A::foo.callBy(mapOf(A::foo.parameters.first() to A()))
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun foo(result: String = "OK") = result
|
||||||
|
|
||||||
|
fun box(): String = ::foo.callBy(mapOf())
|
||||||
+87
@@ -2947,6 +2947,93 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class CallBy extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInCallBy() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/callBy"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("defaultAndNonDefaultIntertwined.kt")
|
||||||
|
public void testDefaultAndNonDefaultIntertwined() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/defaultAndNonDefaultIntertwined.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionFunction.kt")
|
||||||
|
public void testExtensionFunction() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/extensionFunction.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("manyArgumentsOnlyOneDefault.kt")
|
||||||
|
public void testManyArgumentsOnlyOneDefault() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/manyArgumentsOnlyOneDefault.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("manyMaskArguments.kt")
|
||||||
|
public void testManyMaskArguments() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/manyMaskArguments.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonDefaultParameterOmitted.kt")
|
||||||
|
public void testNonDefaultParameterOmitted() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/nonDefaultParameterOmitted.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nullValue.kt")
|
||||||
|
public void testNullValue() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/nullValue.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ordinaryMethodIsInvokedWhenNoDefaultValuesAreUsed.kt")
|
||||||
|
public void testOrdinaryMethodIsInvokedWhenNoDefaultValuesAreUsed() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/ordinaryMethodIsInvokedWhenNoDefaultValuesAreUsed.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("platformStaticInObject.kt")
|
||||||
|
public void testPlatformStaticInObject() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/platformStaticInObject.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitiveDefaultValues.kt")
|
||||||
|
public void testPrimitiveDefaultValues() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/primitiveDefaultValues.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("privateMemberFunction.kt")
|
||||||
|
public void testPrivateMemberFunction() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/privateMemberFunction.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleConstructor.kt")
|
||||||
|
public void testSimpleConstructor() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/simpleConstructor.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleMemberFunciton.kt")
|
||||||
|
public void testSimpleMemberFunciton() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/simpleMemberFunciton.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleTopLevelFunction.kt")
|
||||||
|
public void testSimpleTopLevelFunction() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/callBy/simpleTopLevelFunction.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals")
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -45,9 +45,16 @@ public interface KCallable<out R> : KAnnotatedElement {
|
|||||||
public val returnType: KType
|
public val returnType: KType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls this callable with the specified arguments and returns the result.
|
* Calls this callable with the specified list of arguments and returns the result.
|
||||||
* Throws an exception if the number of specified arguments is not equal to the size of [parameters],
|
* 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.
|
* or if their types do not match the types of the parameters.
|
||||||
*/
|
*/
|
||||||
public fun call(vararg args: Any?): R
|
public fun call(vararg args: Any?): R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls this callable with the specified mapping of parameters to arguments and returns the result.
|
||||||
|
* If a parameter is not found in the mapping and is not optional (as per [KParameter.isOptional]),
|
||||||
|
* or its type does not match the type of the provided value, an exception is thrown.
|
||||||
|
*/
|
||||||
|
public fun callBy(args: Map<KParameter, Any?>): R
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public interface KParameter : KAnnotatedElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `true` if this parameter is optional, or `false` otherwise.
|
* `true` if this parameter is optional and can be omitted when making a call via [KCallable.call], or `false` otherwise.
|
||||||
*
|
*
|
||||||
* A parameter is optional in any of the two cases:
|
* A parameter is optional in any of the two cases:
|
||||||
* 1. The default value is provided at the declaration of this parameter.
|
* 1. The default value is provided at the declaration of this parameter.
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package kotlin.reflect.jvm
|
package kotlin.reflect.jvm
|
||||||
|
|
||||||
|
import java.lang.reflect.AccessibleObject
|
||||||
import kotlin.reflect.KCallable
|
import kotlin.reflect.KCallable
|
||||||
import kotlin.reflect.KFunction
|
import kotlin.reflect.KFunction
|
||||||
import kotlin.reflect.KMutableProperty
|
import kotlin.reflect.KMutableProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
import kotlin.reflect.jvm.internal.KCallableImpl
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a way to suppress JVM access checks for a callable.
|
* Provides a way to suppress JVM access checks for a callable.
|
||||||
@@ -50,6 +52,7 @@ public var KCallable<*>.isAccessible: Boolean
|
|||||||
javaMethod?.isAccessible ?: true
|
javaMethod?.isAccessible ?: true
|
||||||
is KFunction ->
|
is KFunction ->
|
||||||
javaMethod?.isAccessible ?: true &&
|
javaMethod?.isAccessible ?: true &&
|
||||||
|
((this as KCallableImpl<*>).defaultCaller?.member as? AccessibleObject)?.isAccessible ?: true &&
|
||||||
this.javaConstructor?.isAccessible ?: true
|
this.javaConstructor?.isAccessible ?: true
|
||||||
else -> throw UnsupportedOperationException("Unknown callable: $this ($javaClass)")
|
else -> throw UnsupportedOperationException("Unknown callable: $this ($javaClass)")
|
||||||
}
|
}
|
||||||
@@ -75,6 +78,7 @@ public var KCallable<*>.isAccessible: Boolean
|
|||||||
}
|
}
|
||||||
is KFunction -> {
|
is KFunction -> {
|
||||||
javaMethod?.isAccessible = value
|
javaMethod?.isAccessible = value
|
||||||
|
((this as KCallableImpl<*>).defaultCaller?.member as? AccessibleObject)?.isAccessible = true
|
||||||
this.javaConstructor?.isAccessible = value
|
this.javaConstructor?.isAccessible = value
|
||||||
}
|
}
|
||||||
else -> throw UnsupportedOperationException("Unknown callable: $this ($javaClass)")
|
else -> throw UnsupportedOperationException("Unknown callable: $this ($javaClass)")
|
||||||
|
|||||||
@@ -18,20 +18,26 @@ package kotlin.reflect.jvm.internal
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||||
import java.util.ArrayList
|
import java.lang.reflect.Type
|
||||||
|
import java.util.*
|
||||||
import kotlin.reflect.KCallable
|
import kotlin.reflect.KCallable
|
||||||
import kotlin.reflect.KParameter
|
import kotlin.reflect.KParameter
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.KotlinReflectionInternalError
|
||||||
|
import kotlin.reflect.jvm.javaType
|
||||||
|
|
||||||
interface KCallableImpl<out R> : KCallable<R>, KAnnotatedElementImpl {
|
interface KCallableImpl<out R> : KCallable<R>, KAnnotatedElementImpl {
|
||||||
val descriptor: CallableMemberDescriptor
|
val descriptor: CallableMemberDescriptor
|
||||||
|
|
||||||
val caller: FunctionCaller<*>
|
val caller: FunctionCaller<*>
|
||||||
|
|
||||||
|
val defaultCaller: FunctionCaller<*>?
|
||||||
|
|
||||||
override val annotated: Annotated get() = descriptor
|
override val annotated: Annotated get() = descriptor
|
||||||
|
|
||||||
override val parameters: List<KParameter>
|
override val parameters: List<KParameter>
|
||||||
get() {
|
get() {
|
||||||
|
val descriptor = descriptor
|
||||||
val result = ArrayList<KParameter>()
|
val result = ArrayList<KParameter>()
|
||||||
var index = 0
|
var index = 0
|
||||||
|
|
||||||
@@ -58,4 +64,74 @@ interface KCallableImpl<out R> : KCallable<R>, KAnnotatedElementImpl {
|
|||||||
override fun call(vararg args: Any?): R = reflectionCall {
|
override fun call(vararg args: Any?): R = reflectionCall {
|
||||||
return caller.call(args) as R
|
return caller.call(args) as R
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See ArgumentGenerator#generate
|
||||||
|
override fun callBy(args: Map<KParameter, Any?>): R {
|
||||||
|
val parameters = parameters
|
||||||
|
val arguments = ArrayList<Any?>(parameters.size())
|
||||||
|
var mask = 0
|
||||||
|
val masks = ArrayList<Int>(1)
|
||||||
|
var index = 0
|
||||||
|
|
||||||
|
for (parameter in parameters) {
|
||||||
|
if (index != 0 && index % Integer.SIZE == 0) {
|
||||||
|
masks.add(mask)
|
||||||
|
mask = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
when {
|
||||||
|
args.containsKey(parameter) -> {
|
||||||
|
arguments.add(args[parameter])
|
||||||
|
}
|
||||||
|
parameter.isOptional -> {
|
||||||
|
arguments.add(defaultPrimitiveValue(parameter.type.javaType))
|
||||||
|
mask = mask or (1 shl (index % Integer.SIZE))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw IllegalArgumentException("No argument provided for a required parameter: $parameter")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameter.kind == KParameter.Kind.VALUE) {
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask == 0 && masks.isEmpty()) {
|
||||||
|
return call(*arguments.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
masks.add(mask)
|
||||||
|
|
||||||
|
val caller = defaultCaller ?: throw KotlinReflectionInternalError("This callable does not support a default call: $descriptor")
|
||||||
|
|
||||||
|
arguments.addAll(masks)
|
||||||
|
|
||||||
|
if (caller is FunctionCaller.Constructor) {
|
||||||
|
// DefaultConstructorMarker
|
||||||
|
arguments.add(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@suppress("UNCHECKED_CAST")
|
||||||
|
return reflectionCall {
|
||||||
|
caller.call(arguments.toTypedArray()) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun defaultPrimitiveValue(type: Type): Any? =
|
||||||
|
if (type is Class<*> && type.isPrimitive) {
|
||||||
|
when (type) {
|
||||||
|
java.lang.Boolean.TYPE -> false
|
||||||
|
java.lang.Character.TYPE -> 0.toChar()
|
||||||
|
java.lang.Byte.TYPE -> 0.toByte()
|
||||||
|
java.lang.Short.TYPE -> 0.toShort()
|
||||||
|
java.lang.Integer.TYPE -> 0
|
||||||
|
java.lang.Float.TYPE -> 0f
|
||||||
|
java.lang.Long.TYPE -> 0L
|
||||||
|
java.lang.Double.TYPE -> 0.0
|
||||||
|
java.lang.Void.TYPE -> throw IllegalStateException("Parameter with void type is illegal")
|
||||||
|
else -> throw UnsupportedOperationException("Unknown primitive: $type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package kotlin.reflect.jvm.internal
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
|
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
||||||
import org.jetbrains.kotlin.load.java.structure.reflect.createArrayType
|
import org.jetbrains.kotlin.load.java.structure.reflect.createArrayType
|
||||||
import org.jetbrains.kotlin.load.java.structure.reflect.safeClassLoader
|
import org.jetbrains.kotlin.load.java.structure.reflect.safeClassLoader
|
||||||
@@ -137,6 +138,24 @@ abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer {
|
|||||||
return functions.single()
|
return functions.single()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Class<*>.tryGetMethod(name: String, parameterTypes: List<Class<*>>, declared: Boolean) =
|
||||||
|
try {
|
||||||
|
if (declared) getDeclaredMethod(name, *parameterTypes.toTypedArray())
|
||||||
|
else getMethod(name, *parameterTypes.toTypedArray())
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Class<*>.tryGetConstructor(parameterTypes: List<Class<*>>, declared: Boolean) =
|
||||||
|
try {
|
||||||
|
if (declared) getDeclaredConstructor(*parameterTypes.toTypedArray())
|
||||||
|
else getConstructor(*parameterTypes.toTypedArray())
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: check resulting method's return type
|
// TODO: check resulting method's return type
|
||||||
fun findMethodBySignature(
|
fun findMethodBySignature(
|
||||||
@suppress("UNUSED_PARAMETER") proto: ProtoBuf.Callable,
|
@suppress("UNUSED_PARAMETER") proto: ProtoBuf.Callable,
|
||||||
@@ -144,7 +163,7 @@ abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer {
|
|||||||
nameResolver: NameResolver,
|
nameResolver: NameResolver,
|
||||||
declared: Boolean
|
declared: Boolean
|
||||||
): Method? {
|
): Method? {
|
||||||
val name = nameResolver.getString(signature.getName())
|
val name = nameResolver.getString(signature.name)
|
||||||
if (name == "<init>") return null
|
if (name == "<init>") return null
|
||||||
|
|
||||||
val parameterTypes = loadParameterTypes(nameResolver, signature)
|
val parameterTypes = loadParameterTypes(nameResolver, signature)
|
||||||
@@ -153,13 +172,25 @@ abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer {
|
|||||||
// This is likely to change after the package part reform.
|
// This is likely to change after the package part reform.
|
||||||
val owner = jClass
|
val owner = jClass
|
||||||
|
|
||||||
return try {
|
return owner.tryGetMethod(name, parameterTypes, declared)
|
||||||
if (declared) owner.getDeclaredMethod(name, *parameterTypes)
|
}
|
||||||
else owner.getMethod(name, *parameterTypes)
|
|
||||||
}
|
fun findDefaultMethod(
|
||||||
catch (e: NoSuchMethodException) {
|
signature: JvmProtoBuf.JvmMethodSignature,
|
||||||
null
|
nameResolver: NameResolver,
|
||||||
|
isMember: Boolean,
|
||||||
|
declared: Boolean
|
||||||
|
): Method? {
|
||||||
|
val name = nameResolver.getString(signature.name)
|
||||||
|
if (name == "<init>") return null
|
||||||
|
|
||||||
|
val parameterTypes = arrayListOf<Class<*>>()
|
||||||
|
if (isMember) {
|
||||||
|
parameterTypes.add(jClass)
|
||||||
}
|
}
|
||||||
|
addParametersAndMasks(parameterTypes, nameResolver, signature)
|
||||||
|
|
||||||
|
return jClass.tryGetMethod(name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, parameterTypes, declared)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findConstructorBySignature(
|
fun findConstructorBySignature(
|
||||||
@@ -167,24 +198,40 @@ abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer {
|
|||||||
nameResolver: NameResolver,
|
nameResolver: NameResolver,
|
||||||
declared: Boolean
|
declared: Boolean
|
||||||
): Constructor<*>? {
|
): Constructor<*>? {
|
||||||
if (nameResolver.getString(signature.getName()) != "<init>") return null
|
if (nameResolver.getString(signature.name) != "<init>") return null
|
||||||
|
|
||||||
val parameterTypes = loadParameterTypes(nameResolver, signature)
|
return jClass.tryGetConstructor(loadParameterTypes(nameResolver, signature), declared)
|
||||||
|
}
|
||||||
|
|
||||||
return try {
|
fun findDefaultConstructor(
|
||||||
if (declared) jClass.getDeclaredConstructor(*parameterTypes)
|
signature: JvmProtoBuf.JvmMethodSignature,
|
||||||
else jClass.getConstructor(*parameterTypes)
|
nameResolver: NameResolver,
|
||||||
}
|
declared: Boolean
|
||||||
catch (e: NoSuchMethodException) {
|
): Constructor<*>? {
|
||||||
null
|
if (nameResolver.getString(signature.name) != "<init>") return null
|
||||||
|
|
||||||
|
val parameterTypes = arrayListOf<Class<*>>()
|
||||||
|
addParametersAndMasks(parameterTypes, nameResolver, signature)
|
||||||
|
parameterTypes.add(DEFAULT_CONSTRUCTOR_MARKER)
|
||||||
|
|
||||||
|
return jClass.tryGetConstructor(parameterTypes, declared)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addParametersAndMasks(
|
||||||
|
result: MutableList<Class<*>>, nameResolver: NameResolver, signature: JvmProtoBuf.JvmMethodSignature
|
||||||
|
) {
|
||||||
|
val valueParameters = loadParameterTypes(nameResolver, signature)
|
||||||
|
result.addAll(valueParameters)
|
||||||
|
repeat((valueParameters.size() + Integer.SIZE - 1) / Integer.SIZE) {
|
||||||
|
result.add(Integer.TYPE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadParameterTypes(nameResolver: NameResolver, signature: JvmProtoBuf.JvmMethodSignature): Array<Class<*>> {
|
private fun loadParameterTypes(nameResolver: NameResolver, signature: JvmProtoBuf.JvmMethodSignature): List<Class<*>> {
|
||||||
val classLoader = jClass.safeClassLoader
|
val classLoader = jClass.safeClassLoader
|
||||||
return signature.getParameterTypeList().map { jvmType ->
|
return signature.parameterTypeList.map { jvmType ->
|
||||||
loadJvmType(jvmType, nameResolver, classLoader)
|
loadJvmType(jvmType, nameResolver, classLoader)
|
||||||
}.toTypedArray()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check resulting field's type
|
// TODO: check resulting field's type
|
||||||
@@ -256,5 +303,7 @@ abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer {
|
|||||||
LONG to java.lang.Long.TYPE,
|
LONG to java.lang.Long.TYPE,
|
||||||
DOUBLE to java.lang.Double.TYPE
|
DOUBLE to java.lang.Double.TYPE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val DEFAULT_CONSTRUCTOR_MARKER = Class.forName("kotlin.jvm.internal.DefaultConstructorMarker")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,14 +49,14 @@ open class KFunctionImpl protected constructor(
|
|||||||
|
|
||||||
override val name: String get() = descriptor.name.asString()
|
override val name: String get() = descriptor.name.asString()
|
||||||
|
|
||||||
|
private fun isDeclared(): Boolean = Visibilities.isPrivate(descriptor.visibility)
|
||||||
|
|
||||||
override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {
|
override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {
|
||||||
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
||||||
val member: Member? = when (jvmSignature) {
|
val member: Member? = when (jvmSignature) {
|
||||||
is KotlinFunction ->
|
is KotlinFunction ->
|
||||||
if (name == "<init>") container.findConstructorBySignature(jvmSignature.signature, jvmSignature.nameResolver,
|
if (name == "<init>") container.findConstructorBySignature(jvmSignature.signature, jvmSignature.nameResolver, isDeclared())
|
||||||
Visibilities.isPrivate(descriptor.visibility))
|
else container.findMethodBySignature(jvmSignature.proto, jvmSignature.signature, jvmSignature.nameResolver, isDeclared())
|
||||||
else container.findMethodBySignature(jvmSignature.proto, jvmSignature.signature, jvmSignature.nameResolver,
|
|
||||||
Visibilities.isPrivate(descriptor.visibility))
|
|
||||||
is JavaMethod -> jvmSignature.method
|
is JavaMethod -> jvmSignature.method
|
||||||
is JavaConstructor -> jvmSignature.constructor
|
is JavaConstructor -> jvmSignature.constructor
|
||||||
is BuiltInFunction -> jvmSignature.getMember(container)
|
is BuiltInFunction -> jvmSignature.getMember(container)
|
||||||
@@ -68,12 +68,43 @@ open class KFunctionImpl protected constructor(
|
|||||||
!Modifier.isStatic(member.modifiers) -> FunctionCaller.InstanceMethod(member)
|
!Modifier.isStatic(member.modifiers) -> FunctionCaller.InstanceMethod(member)
|
||||||
|
|
||||||
descriptor.annotations.findAnnotation(PLATFORM_STATIC) != null,
|
descriptor.annotations.findAnnotation(PLATFORM_STATIC) != null,
|
||||||
descriptor.annotations.findAnnotation(JVM_STATIC) != null->
|
descriptor.annotations.findAnnotation(JVM_STATIC) != null ->
|
||||||
FunctionCaller.PlatformStaticInObject(member)
|
FunctionCaller.PlatformStaticInObject(member)
|
||||||
|
|
||||||
else -> FunctionCaller.StaticMethod(member)
|
else -> FunctionCaller.StaticMethod(member)
|
||||||
}
|
}
|
||||||
else -> throw KotlinReflectionInternalError("Call is not yet supported for this function: $descriptor")
|
else -> throw KotlinReflectionInternalError("Call is not yet supported for this function: $descriptor (member = $member)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultCaller: FunctionCaller<*>? by ReflectProperties.lazySoft {
|
||||||
|
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
||||||
|
val member: Member? = when (jvmSignature) {
|
||||||
|
is KotlinFunction -> {
|
||||||
|
if (name == "<init>") {
|
||||||
|
container.findDefaultConstructor(jvmSignature.signature, jvmSignature.nameResolver, isDeclared())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val isMember = !Modifier.isStatic(caller.member.modifiers)
|
||||||
|
container.findDefaultMethod(jvmSignature.signature, jvmSignature.nameResolver, isMember, isDeclared())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// Java methods, Java constructors and built-ins don't have $default methods
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when (member) {
|
||||||
|
is Constructor<*> -> FunctionCaller.Constructor(member)
|
||||||
|
is Method -> when {
|
||||||
|
descriptor.annotations.findAnnotation(PLATFORM_STATIC) != null,
|
||||||
|
descriptor.annotations.findAnnotation(JVM_STATIC) != null ->
|
||||||
|
FunctionCaller.PlatformStaticInObject(member)
|
||||||
|
|
||||||
|
else -> FunctionCaller.StaticMethod(member)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ interface KPropertyImpl<out R> : KProperty<R>, KCallableImpl<R> {
|
|||||||
|
|
||||||
override val caller: FunctionCaller<*> get() = getter.caller
|
override val caller: FunctionCaller<*> get() = getter.caller
|
||||||
|
|
||||||
|
override val defaultCaller: FunctionCaller<*>? get() = getter.defaultCaller
|
||||||
|
|
||||||
abstract class Accessor<out R> : KProperty.Accessor<R> {
|
abstract class Accessor<out R> : KProperty.Accessor<R> {
|
||||||
abstract override val property: KPropertyImpl<R>
|
abstract override val property: KPropertyImpl<R>
|
||||||
|
|
||||||
@@ -54,6 +56,8 @@ interface KPropertyImpl<out R> : KProperty<R>, KCallableImpl<R> {
|
|||||||
override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {
|
override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {
|
||||||
computeCallerForAccessor(isGetter = true)
|
computeCallerForAccessor(isGetter = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val defaultCaller: FunctionCaller<*>? get() = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +78,8 @@ interface KMutablePropertyImpl<R> : KMutableProperty<R>, KPropertyImpl<R> {
|
|||||||
override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {
|
override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {
|
||||||
computeCallerForAccessor(isGetter = false)
|
computeCallerForAccessor(isGetter = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val defaultCaller: FunctionCaller<*>? get() = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A superclass for all classes generated by Kotlin compiler for callable references.
|
* A superclass for all classes generated by Kotlin compiler for callable references.
|
||||||
@@ -86,6 +87,11 @@ public abstract class CallableReference implements KCallable {
|
|||||||
throw error();
|
throw error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object callBy(@NotNull Map args) {
|
||||||
|
throw error();
|
||||||
|
}
|
||||||
|
|
||||||
protected static Error error() {
|
protected static Error error() {
|
||||||
throw new KotlinReflectionNotSupportedError();
|
throw new KotlinReflectionNotSupportedError();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class FunctionReference
|
public class FunctionReference
|
||||||
@@ -82,6 +83,11 @@ public class FunctionReference
|
|||||||
throw error();
|
throw error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object callBy(@NotNull Map args) {
|
||||||
|
throw error();
|
||||||
|
}
|
||||||
|
|
||||||
protected static Error error() {
|
protected static Error error() {
|
||||||
throw new KotlinReflectionNotSupportedError();
|
throw new KotlinReflectionNotSupportedError();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user