Support mapping of KType to j.l.reflect.Type
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
|||||||
|
public class J {
|
||||||
|
private final int param;
|
||||||
|
|
||||||
|
public J(int param) {
|
||||||
|
this.param = param;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String foo(int[] arr, Object[] arr2, Integer y) {
|
||||||
|
return "" + param + arr[0] + arr2[0] + y;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val f = J::foo
|
||||||
|
assertEquals(
|
||||||
|
listOf(javaClass<J>(), javaClass<IntArray>(), javaClass<Array<Any>>(), javaClass<Integer>()),
|
||||||
|
f.parameters.map { it.type.javaType }
|
||||||
|
)
|
||||||
|
assertEquals(javaClass<String>(), f.returnType.javaType)
|
||||||
|
|
||||||
|
assertEquals("01A2", f.call(J(0), intArrayOf(1), arrayOf("A"), 2))
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
public class J {
|
||||||
|
public static String foo(int x, int[] arr, Object[] arr2) {
|
||||||
|
return "" + x + arr[0] + arr2[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val f = J::foo
|
||||||
|
assertEquals(listOf(Integer.TYPE, javaClass<IntArray>(), javaClass<Array<Any>>()), f.parameters.map { it.type.javaType })
|
||||||
|
assertEquals(javaClass<String>(), f.returnType.javaType)
|
||||||
|
|
||||||
|
assertEquals("01A", f.call(0, intArrayOf(1), arrayOf("A")))
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
import java.lang.reflect.GenericArrayType
|
||||||
|
import java.lang.reflect.TypeVariable
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun foo(strings: Array<String>, integers: Array<Int>, objectArrays: Array<Array<Any>>) {}
|
||||||
|
|
||||||
|
fun bar(): Array<List<String>> = null!!
|
||||||
|
class A<T> {
|
||||||
|
fun baz(): Array<T> = null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(javaClass<Array<String>>(), ::foo.parameters[0].type.javaType)
|
||||||
|
assertEquals(javaClass<Array<Int>>(), ::foo.parameters[1].type.javaType)
|
||||||
|
assertEquals(javaClass<Array<Array<Any>>>(), ::foo.parameters[2].type.javaType)
|
||||||
|
|
||||||
|
val g = ::bar.returnType.javaType
|
||||||
|
if (g !is GenericArrayType || g.genericComponentType !is ParameterizedType)
|
||||||
|
return "Fail: should be array of parameterized type, but was $g (${g.javaClass})"
|
||||||
|
|
||||||
|
val h = A<String>::baz.returnType.javaType
|
||||||
|
if (h !is GenericArrayType || h.genericComponentType !is TypeVariable<*>)
|
||||||
|
return "Fail: should be array of type variable, but was $h (${h.javaClass})"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
import kotlin.reflect.*
|
||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class A(d: Double, s: String, parent: A?) {
|
||||||
|
class Nested(a: A)
|
||||||
|
inner class Inner(nested: Nested)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(listOf(java.lang.Double.TYPE, javaClass<String>(), javaClass<A>()), ::A.parameters.map { it.type.javaType })
|
||||||
|
assertEquals(listOf(javaClass<A>()), A::Nested.parameters.map { it.type.javaType })
|
||||||
|
assertEquals(listOf(javaClass<A>(), javaClass<A.Nested>()), A::Inner.parameters.map { it.type.javaType })
|
||||||
|
|
||||||
|
assertEquals(javaClass<A>(), ::A.returnType.javaType)
|
||||||
|
assertEquals(javaClass<A.Nested>(), A::Nested.returnType.javaType)
|
||||||
|
assertEquals(javaClass<A.Inner>(), A::Inner.returnType.javaType)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
import kotlin.platform.platformStatic as static
|
||||||
|
import kotlin.reflect.jvm.javaType
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class A {
|
||||||
|
fun foo(t: Long?): Long = t!!
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
static fun bar(a: A): String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(listOf(javaClass<A>(), javaClass<java.lang.Long>()), A::foo.parameters.map { it.type.javaType })
|
||||||
|
assertEquals(listOf(javaClass<O>(), javaClass<A>()), O::bar.parameters.map { it.type.javaType })
|
||||||
|
|
||||||
|
assertEquals(java.lang.Long.TYPE, A::foo.returnType.javaType)
|
||||||
|
assertEquals(javaClass<String>(), O::bar.returnType.javaType)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
fun foo(): Any
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : I {
|
||||||
|
override fun foo(): Int = 0
|
||||||
|
fun bar(x: Long): Int = x.toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(javaClass<Integer>(), A::foo.returnType.javaType)
|
||||||
|
assertNotEquals(Integer.TYPE, A::foo.returnType.javaType)
|
||||||
|
|
||||||
|
assertNotEquals(javaClass<Integer>(), A::bar.returnType.javaType)
|
||||||
|
assertEquals(Integer.TYPE, A::bar.returnType.javaType)
|
||||||
|
|
||||||
|
assertEquals(java.lang.Long.TYPE, A::bar.parameters.last().type.javaType)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import kotlin.platform.platformStatic as static
|
||||||
|
import kotlin.reflect.*
|
||||||
|
import kotlin.reflect.jvm.javaType
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class A(private var foo: List<String>)
|
||||||
|
|
||||||
|
object O {
|
||||||
|
private static var bar: List<String> = listOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun topLevel(): List<String> = listOf()
|
||||||
|
fun Any.extension(): List<String> = listOf()
|
||||||
|
|
||||||
|
fun assertGenericType(type: KType) {
|
||||||
|
val javaType = type.javaType
|
||||||
|
if (javaType !is ParameterizedType) {
|
||||||
|
throw AssertionError("Type should be a parameterized type, but was $javaType (${javaType.javaClass})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val foo = A::class.members.single { it.name == "foo" } as KMutableProperty<*>
|
||||||
|
assertGenericType(foo.returnType)
|
||||||
|
assertGenericType(foo.getter.returnType)
|
||||||
|
assertGenericType(foo.setter.parameters.last().type)
|
||||||
|
|
||||||
|
val bar = O::class.members.single { it.name == "bar" } as KMutableProperty<*>
|
||||||
|
assertGenericType(bar.returnType)
|
||||||
|
assertGenericType(bar.getter.returnType)
|
||||||
|
assertGenericType(bar.setter.parameters.last().type)
|
||||||
|
|
||||||
|
assertGenericType(::topLevel.returnType)
|
||||||
|
assertGenericType(Any::extension.returnType)
|
||||||
|
assertGenericType(::A.parameters.single().type)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
import kotlin.platform.platformStatic as static
|
||||||
|
import kotlin.reflect.KMutableProperty
|
||||||
|
import kotlin.reflect.jvm.javaType
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class A(private var foo: String)
|
||||||
|
|
||||||
|
object O {
|
||||||
|
private static var bar: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val foo = A::class.members.single { it.name == "foo" } as KMutableProperty<*>
|
||||||
|
assertEquals(listOf(javaClass<A>()), foo.parameters.map { it.type.javaType })
|
||||||
|
assertEquals(listOf(javaClass<A>()), foo.getter.parameters.map { it.type.javaType })
|
||||||
|
assertEquals(listOf(javaClass<A>(), javaClass<String>()), foo.setter.parameters.map { it.type.javaType })
|
||||||
|
|
||||||
|
val bar = O::class.members.single { it.name == "bar" } as KMutableProperty<*>
|
||||||
|
assertEquals(listOf(javaClass<O>()), bar.parameters.map { it.type.javaType })
|
||||||
|
assertEquals(listOf(javaClass<O>()), bar.getter.parameters.map { it.type.javaType })
|
||||||
|
assertEquals(listOf(javaClass<O>(), javaClass<String>()), bar.setter.parameters.map { it.type.javaType })
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun free(s: String): Int = s.length()
|
||||||
|
|
||||||
|
fun Any.extension() {}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(java.lang.Integer.TYPE, ::free.returnType.javaType)
|
||||||
|
assertEquals(javaClass<String>(), ::free.parameters.single().type.javaType)
|
||||||
|
|
||||||
|
assertEquals(javaClass<Any>(), Any::extension.parameters.single().type.javaType)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
import java.lang.reflect.TypeVariable
|
||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class A<T> {
|
||||||
|
fun foo(t: T) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val f = A<String>::foo
|
||||||
|
val t = f.parameters.last().type.javaType
|
||||||
|
if (t !is TypeVariable<*>) return "Fail, t should be a type variable: $t"
|
||||||
|
|
||||||
|
assertEquals("T", t.name)
|
||||||
|
assertEquals("A", (t.genericDeclaration as Class<*>).name)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun foo(unitParam: Unit, nullableUnitParam: Unit?): Unit {}
|
||||||
|
|
||||||
|
var bar: Unit = Unit
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assert(javaClass<Unit>() != java.lang.Void.TYPE)
|
||||||
|
|
||||||
|
assertEquals(javaClass<Unit>(), ::foo.parameters[0].type.javaType)
|
||||||
|
assertEquals(javaClass<Unit>(), ::foo.parameters[1].type.javaType)
|
||||||
|
assertEquals(java.lang.Void.TYPE, ::foo.returnType.javaType)
|
||||||
|
|
||||||
|
assertEquals(javaClass<Unit>(), ::bar.returnType.javaType)
|
||||||
|
assertEquals(javaClass<Unit>(), ::bar.getter.returnType.javaType)
|
||||||
|
assertEquals(javaClass<Unit>(), ::bar.setter.parameters.single().type.javaType)
|
||||||
|
assertEquals(java.lang.Void.TYPE, ::bar.setter.returnType.javaType)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+12
@@ -267,6 +267,18 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithJava/reflection"), Pattern.compile("^([^\\.]+)$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithJava/reflection"), Pattern.compile("^([^\\.]+)$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("callInstanceJavaMethod")
|
||||||
|
public void testCallInstanceJavaMethod() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/reflection/callInstanceJavaMethod/");
|
||||||
|
doTestWithJava(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("callStaticJavaMethod")
|
||||||
|
public void testCallStaticJavaMethod() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/reflection/callStaticJavaMethod/");
|
||||||
|
doTestWithJava(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("functionReferenceErasedToKFunction")
|
@TestMetadata("functionReferenceErasedToKFunction")
|
||||||
public void testFunctionReferenceErasedToKFunction() throws Exception {
|
public void testFunctionReferenceErasedToKFunction() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/reflection/functionReferenceErasedToKFunction/");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/reflection/functionReferenceErasedToKFunction/");
|
||||||
|
|||||||
+63
@@ -3359,6 +3359,69 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/topLevelProperty.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/topLevelProperty.kt");
|
||||||
doTestWithStdlib(fileName);
|
doTestWithStdlib(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Types extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInTypes() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("array.kt")
|
||||||
|
public void testArray() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types/array.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("constructors.kt")
|
||||||
|
public void testConstructors() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types/constructors.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("memberFunctions.kt")
|
||||||
|
public void testMemberFunctions() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types/memberFunctions.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideAnyWithPrimitive.kt")
|
||||||
|
public void testOverrideAnyWithPrimitive() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types/overrideAnyWithPrimitive.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("parameterizedTypes.kt")
|
||||||
|
public void testParameterizedTypes() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types/parameterizedTypes.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyAccessors.kt")
|
||||||
|
public void testPropertyAccessors() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types/propertyAccessors.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevelFunctions.kt")
|
||||||
|
public void testTopLevelFunctions() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types/topLevelFunctions.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParameters.kt")
|
||||||
|
public void testTypeParameters() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types/typeParameters.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unit.kt")
|
||||||
|
public void testUnit() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/types/unit.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/methodsFromAny")
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/methodsFromAny")
|
||||||
|
|||||||
@@ -17,20 +17,23 @@
|
|||||||
package kotlin.reflect.jvm.internal
|
package kotlin.reflect.jvm.internal
|
||||||
|
|
||||||
import java.lang.reflect.Member
|
import java.lang.reflect.Member
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
import java.lang.reflect.Type
|
||||||
import java.lang.reflect.Constructor as ReflectConstructor
|
import java.lang.reflect.Constructor as ReflectConstructor
|
||||||
import java.lang.reflect.Field as ReflectField
|
import java.lang.reflect.Field as ReflectField
|
||||||
import java.lang.reflect.Method as ReflectMethod
|
import java.lang.reflect.Method as ReflectMethod
|
||||||
|
|
||||||
internal sealed class FunctionCaller(
|
internal abstract class FunctionCaller {
|
||||||
private val expectedArgumentNumber: Int
|
|
||||||
) {
|
|
||||||
abstract val member: Member
|
abstract val member: Member
|
||||||
|
|
||||||
|
abstract val returnType: Type
|
||||||
|
abstract val parameterTypes: List<Type>
|
||||||
|
|
||||||
abstract fun call(args: Array<*>): Any?
|
abstract fun call(args: Array<*>): Any?
|
||||||
|
|
||||||
protected open fun checkArguments(args: Array<*>) {
|
protected open fun checkArguments(args: Array<*>) {
|
||||||
if (expectedArgumentNumber != args.size()) {
|
if (parameterTypes.size() != args.size()) {
|
||||||
throw IllegalArgumentException("Callable expects $expectedArgumentNumber arguments, but ${args.size()} were provided.")
|
throw IllegalArgumentException("Callable expects ${parameterTypes.size()} arguments, but ${args.size()} were provided.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,9 +43,16 @@ internal sealed class FunctionCaller(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Constructor(val constructor: ReflectConstructor<*>) : FunctionCaller(constructor.parameterTypes.size()) {
|
class Constructor(val constructor: ReflectConstructor<*>) : FunctionCaller() {
|
||||||
override val member: Member get() = constructor
|
override val member: Member get() = constructor
|
||||||
|
|
||||||
|
override val returnType = constructor.declaringClass
|
||||||
|
|
||||||
|
override val parameterTypes =
|
||||||
|
if (returnType.declaringClass == null || Modifier.isStatic(returnType.modifiers))
|
||||||
|
constructor.genericParameterTypes.toList()
|
||||||
|
else listOf(returnType.declaringClass, *constructor.genericParameterTypes)
|
||||||
|
|
||||||
override fun call(args: Array<*>): Any? {
|
override fun call(args: Array<*>): Any? {
|
||||||
checkArguments(args)
|
checkArguments(args)
|
||||||
return constructor.newInstance(*args)
|
return constructor.newInstance(*args)
|
||||||
@@ -51,10 +61,17 @@ internal sealed class FunctionCaller(
|
|||||||
|
|
||||||
abstract class Method(
|
abstract class Method(
|
||||||
val method: ReflectMethod,
|
val method: ReflectMethod,
|
||||||
requiresInstance: Boolean
|
private val requiresInstance: Boolean
|
||||||
) : FunctionCaller(method.parameterTypes.size() + (if (requiresInstance) 1 else 0)) {
|
) : FunctionCaller() {
|
||||||
override val member: Member get() = method
|
override val member: Member get() = method
|
||||||
private val isVoidMethod = method.returnType == Void.TYPE
|
|
||||||
|
override val returnType = method.genericReturnType
|
||||||
|
|
||||||
|
override val parameterTypes =
|
||||||
|
if (requiresInstance) listOf(method.declaringClass, *method.genericParameterTypes)
|
||||||
|
else method.genericParameterTypes.toList()
|
||||||
|
|
||||||
|
private val isVoidMethod = returnType == Void.TYPE
|
||||||
|
|
||||||
protected fun callMethod(instance: Any?, args: Array<*>): Any? {
|
protected fun callMethod(instance: Any?, args: Array<*>): Any? {
|
||||||
val result = method.invoke(instance, *args)
|
val result = method.invoke(instance, *args)
|
||||||
@@ -86,14 +103,19 @@ internal sealed class FunctionCaller(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class FieldAccessor(val field: ReflectField, expectedArgumentNumber: Int) : FunctionCaller(expectedArgumentNumber) {
|
abstract class FieldAccessor(val field: ReflectField) : FunctionCaller() {
|
||||||
override val member: Member get() = field
|
override val member: Member get() = field
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class FieldGetter(
|
abstract class FieldGetter(
|
||||||
field: ReflectField,
|
field: ReflectField,
|
||||||
private val requiresInstance: Boolean
|
private val requiresInstance: Boolean
|
||||||
) : FieldAccessor(field, if (requiresInstance) 1 else 0) {
|
) : FieldAccessor(field) {
|
||||||
|
override val returnType = field.genericType
|
||||||
|
|
||||||
|
override val parameterTypes =
|
||||||
|
if (requiresInstance) listOf(field.declaringClass) else listOf()
|
||||||
|
|
||||||
override fun call(args: Array<*>): Any? {
|
override fun call(args: Array<*>): Any? {
|
||||||
checkArguments(args)
|
checkArguments(args)
|
||||||
return field.get(if (requiresInstance) args.first() else null)
|
return field.get(if (requiresInstance) args.first() else null)
|
||||||
@@ -104,7 +126,13 @@ internal sealed class FunctionCaller(
|
|||||||
field: ReflectField,
|
field: ReflectField,
|
||||||
private val notNull: Boolean,
|
private val notNull: Boolean,
|
||||||
private val requiresInstance: Boolean
|
private val requiresInstance: Boolean
|
||||||
) : FieldAccessor(field, if (requiresInstance) 2 else 1) {
|
) : FieldAccessor(field) {
|
||||||
|
override val returnType: Type get() = Void.TYPE
|
||||||
|
|
||||||
|
override val parameterTypes =
|
||||||
|
if (requiresInstance) listOf(field.declaringClass, field.genericType)
|
||||||
|
else listOf(field.genericType)
|
||||||
|
|
||||||
override fun checkArguments(args: Array<*>) {
|
override fun checkArguments(args: Array<*>) {
|
||||||
super.checkArguments(args)
|
super.checkArguments(args)
|
||||||
if (notNull && args.last() == null) {
|
if (notNull && args.last() == null) {
|
||||||
|
|||||||
@@ -36,15 +36,15 @@ interface KCallableImpl<out R> : KCallable<R>, KAnnotatedElementImpl {
|
|||||||
var index = 0
|
var index = 0
|
||||||
|
|
||||||
if (descriptor.dispatchReceiverParameter != null) {
|
if (descriptor.dispatchReceiverParameter != null) {
|
||||||
result.add(KParameterImpl(index++) { descriptor.dispatchReceiverParameter!! })
|
result.add(KParameterImpl(this, index++) { descriptor.dispatchReceiverParameter!! })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor.extensionReceiverParameter != null) {
|
if (descriptor.extensionReceiverParameter != null) {
|
||||||
result.add(KParameterImpl(index++) { descriptor.extensionReceiverParameter!! })
|
result.add(KParameterImpl(this, index++) { descriptor.extensionReceiverParameter!! })
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in descriptor.valueParameters.indices) {
|
for (i in descriptor.valueParameters.indices) {
|
||||||
result.add(KParameterImpl(index++) { descriptor.valueParameters[i] })
|
result.add(KParameterImpl(this, index++) { descriptor.valueParameters[i] })
|
||||||
}
|
}
|
||||||
|
|
||||||
result.trimToSize()
|
result.trimToSize()
|
||||||
@@ -52,7 +52,7 @@ interface KCallableImpl<out R> : KCallable<R>, KAnnotatedElementImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val returnType: KType
|
override val returnType: KType
|
||||||
get() = KTypeImpl(descriptor.returnType!!)
|
get() = KTypeImpl(descriptor.returnType!!) { caller.returnType }
|
||||||
|
|
||||||
@suppress("UNCHECKED_CAST")
|
@suppress("UNCHECKED_CAST")
|
||||||
override fun call(vararg args: Any?): R = reflectionCall {
|
override fun call(vararg args: Any?): R = reflectionCall {
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ import kotlin.reflect.KParameter
|
|||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
class KParameterImpl(
|
class KParameterImpl(
|
||||||
|
val callable: KCallableImpl<*>,
|
||||||
override val index: Int,
|
override val index: Int,
|
||||||
private val computeDescriptor: () -> ParameterDescriptor
|
computeDescriptor: () -> ParameterDescriptor
|
||||||
) : KParameter, KAnnotatedElementImpl {
|
) : KParameter, KAnnotatedElementImpl {
|
||||||
private val descriptor: ParameterDescriptor by ReflectProperties.lazySoft(computeDescriptor)
|
private val descriptor: ParameterDescriptor by ReflectProperties.lazySoft(computeDescriptor)
|
||||||
|
|
||||||
@@ -38,5 +39,5 @@ class KParameterImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val type: KType
|
override val type: KType
|
||||||
get() = KTypeImpl(descriptor.getType())
|
get() = KTypeImpl(descriptor.type) { callable.caller.parameterTypes[index] }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,15 @@
|
|||||||
package kotlin.reflect.jvm.internal
|
package kotlin.reflect.jvm.internal
|
||||||
|
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
import java.lang.reflect.Type
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
class KTypeImpl(val type: JetType) : KType {
|
class KTypeImpl(
|
||||||
|
val type: JetType,
|
||||||
|
computeJavaType: () -> Type
|
||||||
|
) : KType {
|
||||||
|
internal val javaType: Type by ReflectProperties.lazySoft(computeJavaType)
|
||||||
|
|
||||||
override val isMarkedNullable: Boolean
|
override val isMarkedNullable: Boolean
|
||||||
get() = type.isMarkedNullable
|
get() = type.isMarkedNullable
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,7 @@
|
|||||||
|
|
||||||
package kotlin.reflect.jvm
|
package kotlin.reflect.jvm
|
||||||
|
|
||||||
import java.lang.reflect.Constructor
|
import java.lang.reflect.*
|
||||||
import java.lang.reflect.Field
|
|
||||||
import java.lang.reflect.Method
|
|
||||||
import java.lang.reflect.Modifier
|
|
||||||
import kotlin.jvm.internal.Intrinsic
|
import kotlin.jvm.internal.Intrinsic
|
||||||
import kotlin.reflect.*
|
import kotlin.reflect.*
|
||||||
import kotlin.reflect.jvm.internal.*
|
import kotlin.reflect.jvm.internal.*
|
||||||
@@ -87,6 +84,15 @@ public val <T> KFunction<T>.javaConstructor: Constructor<T>?
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Java [Type] instance corresponding to the given Kotlin type.
|
||||||
|
* Note that one Kotlin type may correspond to different JVM types depending on where it appears. For example, [Unit] corresponds to
|
||||||
|
* the JVM class [Unit] when it's the type of a parameter, or to `void` when it's the return type of a function.
|
||||||
|
*/
|
||||||
|
public val KType.javaType: Type
|
||||||
|
get() = (this as KTypeImpl).javaType
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Java reflection -> Kotlin reflection
|
// Java reflection -> Kotlin reflection
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user