Support Kotlin annotation constructors in reflection
#KT-13106 In Progress
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
annotation class A1
|
||||
|
||||
annotation class A2(val k: KClass<*>, val s: A1)
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(1, A1::class.constructors.size)
|
||||
assertEquals(A1::class.primaryConstructor, A1::class.constructors.single())
|
||||
|
||||
val cs = A2::class.constructors
|
||||
assertEquals(1, cs.size)
|
||||
assertEquals(A2::class.primaryConstructor, cs.single())
|
||||
val params = cs.single().parameters
|
||||
assertEquals(listOf("k", "s"), params.map { it.name })
|
||||
|
||||
return "OK"
|
||||
}
|
||||
-3
@@ -1,10 +1,8 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.*
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
interface Interface
|
||||
annotation class Anno(val x: Int)
|
||||
object Obj
|
||||
|
||||
class C {
|
||||
@@ -13,7 +11,6 @@ class C {
|
||||
|
||||
fun box(): String {
|
||||
assertTrue(Interface::class.constructors.isEmpty())
|
||||
assertTrue(Anno::class.constructors.isEmpty())
|
||||
assertTrue(Obj::class.constructors.isEmpty())
|
||||
assertTrue(C.Companion::class.constructors.isEmpty())
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
annotation class Anno(val klasses: Array<KClass<*>> = arrayOf(String::class, Int::class))
|
||||
|
||||
fun box(): String {
|
||||
val anno = Anno::class.constructors.single().callBy(emptyMap())
|
||||
assertEquals(listOf(String::class, Int::class), (anno.klasses as Array<KClass<*>>).toList() /* TODO: KT-9453 */)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.primaryConstructor
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFails
|
||||
|
||||
annotation class NoParams
|
||||
annotation class OneDefault(val s: String = "OK")
|
||||
annotation class OneNonDefault(val s: String)
|
||||
annotation class TwoParamsOneDefault(val s: String, val x: Int = 42)
|
||||
annotation class TwoParamsOneDefaultKClass(val string: String, val klass: KClass<*> = Number::class)
|
||||
annotation class TwoNonDefaults(val string: String, val klass: KClass<*>)
|
||||
|
||||
|
||||
inline fun <reified T : Annotation> create(args: Map<String, Any?>): T {
|
||||
val ctor = T::class.constructors.single()
|
||||
return ctor.callBy(args.mapKeys { entry -> ctor.parameters.single { it.name == entry.key } })
|
||||
}
|
||||
|
||||
inline fun <reified T : Annotation> create(): T = create(emptyMap())
|
||||
|
||||
fun box(): String {
|
||||
create<NoParams>()
|
||||
|
||||
val t1 = create<OneDefault>()
|
||||
assertEquals("OK", t1.s)
|
||||
assertFails { create<OneDefault>(mapOf("s" to 42)) }
|
||||
|
||||
val t2 = create<OneNonDefault>(mapOf("s" to "OK"))
|
||||
assertEquals("OK", t2.s)
|
||||
assertFails { create<OneNonDefault>() }
|
||||
|
||||
val t3 = create<TwoParamsOneDefault>(mapOf("s" to "OK"))
|
||||
assertEquals("OK", t3.s)
|
||||
assertEquals(42, t3.x)
|
||||
val t4 = create<TwoParamsOneDefault>(mapOf("s" to "OK", "x" to 239))
|
||||
assertEquals(239, t4.x)
|
||||
assertFails { create<TwoParamsOneDefault>(mapOf("s" to "Fail", "x" to "Fail")) }
|
||||
|
||||
val t5 = create<TwoParamsOneDefaultKClass>(mapOf("string" to "OK"))
|
||||
assertEquals(Number::class, t5.klass as KClass<*> /* TODO: KT-9453 */)
|
||||
|
||||
assertFails("KClass (not Class) instances should be passed as arguments") {
|
||||
create<TwoNonDefaults>(mapOf("klass" to String::class.java, "string" to "Fail"))
|
||||
}
|
||||
|
||||
val t6 = create<TwoNonDefaults>(mapOf("klass" to String::class, "string" to "OK"))
|
||||
return t6.string
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.primaryConstructor
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFails
|
||||
|
||||
annotation class NoParams
|
||||
annotation class OneDefault(val s: String = "Fail")
|
||||
annotation class TwoNonDefaults(val string: String, val klass: KClass<*>)
|
||||
|
||||
inline fun <reified T : Annotation> create(vararg args: Any?): T =
|
||||
T::class.constructors.single().call(*args)
|
||||
|
||||
fun box(): String {
|
||||
create<NoParams>()
|
||||
assertFails { create<NoParams>("Fail") }
|
||||
|
||||
assertFails { create<OneDefault>() }
|
||||
assertFails { create<OneDefault>(42) }
|
||||
val o = create<OneDefault>("OK")
|
||||
assertEquals("OK", o.s)
|
||||
|
||||
assertFails("call() should fail because arguments were passed in an incorrect order") {
|
||||
create<TwoNonDefaults>(Any::class, "Fail")
|
||||
}
|
||||
assertFails("call() should fail because KClass (not Class) instances should be passed as arguments") {
|
||||
create<TwoNonDefaults>("Fail", Any::class.java)
|
||||
}
|
||||
|
||||
val k = create<TwoNonDefaults>("OK", Int::class)
|
||||
assertEquals(Int::class, k.klass as KClass<*> /* TODO: KT-9453 */)
|
||||
|
||||
return k.string
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// WITH_REFLECT
|
||||
// FULL_JDK
|
||||
|
||||
import java.lang.reflect.GenericArrayType
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.jvm.javaType
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
annotation class Z
|
||||
enum class E
|
||||
|
||||
annotation class Anno(
|
||||
val b: Byte,
|
||||
val s: String,
|
||||
val ss: Array<String>,
|
||||
val z: Z,
|
||||
val zs: Array<Z>,
|
||||
val e: E,
|
||||
val es: Array<E>,
|
||||
val k: KClass<*>,
|
||||
val ka: Array<KClass<*>>
|
||||
)
|
||||
|
||||
fun tmp(): Array<Class<*>> = null!!
|
||||
|
||||
fun box(): String {
|
||||
val t = Anno::class.constructors.single().parameters.map { it.type.javaType }
|
||||
|
||||
assertEquals(Byte::class.java, t[0])
|
||||
assertEquals(String::class.java, t[1])
|
||||
assertEquals(Array<String>::class.java, t[2])
|
||||
assertEquals(Z::class.java, t[3])
|
||||
assertEquals(Array<Z>::class.java, t[4])
|
||||
assertEquals(E::class.java, t[5])
|
||||
assertEquals(Array<E>::class.java, t[6])
|
||||
|
||||
assertTrue(t[7] is ParameterizedType)
|
||||
assertEquals(Class::class.java, (t[7] as ParameterizedType).rawType)
|
||||
|
||||
assertTrue(t[8] is GenericArrayType)
|
||||
val e = (t[8] as GenericArrayType).genericComponentType
|
||||
assertTrue(e is ParameterizedType)
|
||||
assertEquals(Class::class.java, (e as ParameterizedType).rawType)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -12111,6 +12111,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/constructors"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationClass.kt")
|
||||
public void testAnnotationClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/constructors/annotationClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classesWithoutConstructors.kt")
|
||||
public void testClassesWithoutConstructors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/constructors/classesWithoutConstructors.kt");
|
||||
@@ -12136,6 +12142,33 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/createAnnotation")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class CreateAnnotation extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInCreateAnnotation() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/createAnnotation"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayOfKClasses.kt")
|
||||
public void testArrayOfKClasses() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/createAnnotation/arrayOfKClasses.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("callByKotlin.kt")
|
||||
public void testCallByKotlin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/createAnnotation/callByKotlin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("callKotlin.kt")
|
||||
public void testCallKotlin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/createAnnotation/callKotlin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/enclosing")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -12614,6 +12647,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationConstructorParameters.kt")
|
||||
public void testAnnotationConstructorParameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/types/annotationConstructorParameters.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("array.kt")
|
||||
public void testArray() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/types/array.kt");
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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 org.jetbrains.kotlin.load.java.structure.reflect.wrapperByPrimitive
|
||||
import java.lang.reflect.Proxy
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
import java.lang.reflect.Method as ReflectMethod
|
||||
|
||||
internal class AnnotationConstructorCaller(
|
||||
private val jClass: Class<*>,
|
||||
private val parameterNames: List<String>,
|
||||
private val callMode: CallMode,
|
||||
methods: List<ReflectMethod> = parameterNames.map { name -> jClass.getDeclaredMethod(name) }
|
||||
) : FunctionCaller<Nothing?>(
|
||||
null, jClass, null, methods.map { it.genericReturnType }.toTypedArray()
|
||||
) {
|
||||
enum class CallMode { CALL_BY_NAME, POSITIONAL_CALL }
|
||||
|
||||
// Transform primitive int to java.lang.Integer because actual arguments passed here will be boxed and Class#isInstance should succeed
|
||||
private val erasedParameterTypes: List<Class<*>> = methods.map { method -> method.returnType.let { it.wrapperByPrimitive ?: it } }
|
||||
|
||||
private val defaultValues: List<Any?> = methods.map { method -> method.defaultValue }
|
||||
|
||||
override fun call(args: Array<*>): Any? {
|
||||
checkArguments(args)
|
||||
|
||||
val values = args.mapIndexed { index, arg ->
|
||||
val value =
|
||||
if (arg == null && callMode == CallMode.CALL_BY_NAME) defaultValues[index]
|
||||
else arg.transformKotlinToJvm(erasedParameterTypes[index])
|
||||
value ?: throwIllegalArgumentType(index, parameterNames[index], erasedParameterTypes[index])
|
||||
}
|
||||
|
||||
return createAnnotationInstance(jClass, parameterNames.zip(values).toMap())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a Kotlin value to the one required by the JVM, e.g. KClass<*> -> Class<*> or Array<KClass<*>> -> Array<Class<*>>.
|
||||
* Returns `null` in case when no transformation is possible (an argument of an incorrect type was passed).
|
||||
*/
|
||||
private fun Any?.transformKotlinToJvm(expectedType: Class<*>): Any? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val result = when (this) {
|
||||
is Class<*> -> return null
|
||||
is KClass<*> -> this.java
|
||||
is Array<*> -> when {
|
||||
this.isArrayOf<Class<*>>() -> return null
|
||||
this.isArrayOf<KClass<*>>() -> (this as Array<KClass<*>>).map(KClass<*>::java).toTypedArray()
|
||||
else -> this
|
||||
}
|
||||
else -> this
|
||||
}
|
||||
|
||||
return if (expectedType.isInstance(result)) result else null
|
||||
}
|
||||
|
||||
private fun throwIllegalArgumentType(index: Int, name: String, expectedJvmType: Class<*>): Nothing {
|
||||
val kotlinClass = when {
|
||||
expectedJvmType == Class::class.java -> KClass::class
|
||||
expectedJvmType.isArray && expectedJvmType.componentType == Class::class.java ->
|
||||
@Suppress("CLASS_LITERAL_LHS_NOT_A_CLASS") Array<KClass<*>>::class // Workaround KT-13924
|
||||
else -> expectedJvmType.kotlin
|
||||
}
|
||||
// For arrays, also render the type argument in the message, e.g. "... not of the required type kotlin.Array<kotlin.reflect.KClass>"
|
||||
val typeString = when {
|
||||
kotlinClass.qualifiedName == Array<Any>::class.qualifiedName ->
|
||||
"${kotlinClass.qualifiedName}<${kotlinClass.java.componentType.kotlin.qualifiedName}>"
|
||||
else -> kotlinClass.qualifiedName
|
||||
}
|
||||
throw IllegalArgumentException("Argument #$index $name is not of the required type $typeString")
|
||||
}
|
||||
|
||||
private fun createAnnotationInstance(annotationClass: Class<*>, values: Map<String, Any>): Any {
|
||||
return Proxy.newProxyInstance(annotationClass.classLoader, arrayOf(annotationClass)) { proxy, method, args ->
|
||||
// TODO: support equals, hashCode, toString, annotationType
|
||||
values[method.name] ?: throw KotlinReflectionInternalError("Method is not supported: $method (args: ${args.orEmpty().toList()})")
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import java.lang.reflect.Constructor as ReflectConstructor
|
||||
import java.lang.reflect.Field as ReflectField
|
||||
import java.lang.reflect.Method as ReflectMethod
|
||||
|
||||
internal abstract class FunctionCaller<out M : Member>(
|
||||
internal abstract class FunctionCaller<out M : Member?>(
|
||||
internal val member: M,
|
||||
internal val returnType: Type,
|
||||
internal val instanceClass: Class<*>?,
|
||||
@@ -45,7 +45,7 @@ internal abstract class FunctionCaller<out M : Member>(
|
||||
}
|
||||
|
||||
protected fun checkObjectInstance(obj: Any?) {
|
||||
if (obj == null || !member.declaringClass.isInstance(obj)) {
|
||||
if (obj == null || !member!!.declaringClass.isInstance(obj)) {
|
||||
throw IllegalArgumentException("An object member requires the object instance passed as the first argument.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,10 @@ import kotlin.reflect.jvm.javaType
|
||||
internal abstract class KCallableImpl<out R> : KCallable<R> {
|
||||
abstract val descriptor: CallableMemberDescriptor
|
||||
|
||||
// The instance which is used to perform a positional call, i.e. `call`
|
||||
abstract val caller: FunctionCaller<*>
|
||||
|
||||
// The instance which is used to perform a call "by name", i.e. `callBy`
|
||||
abstract val defaultCaller: FunctionCaller<*>?
|
||||
|
||||
abstract val container: KDeclarationContainerImpl
|
||||
@@ -94,7 +96,7 @@ internal abstract class KCallableImpl<out R> : KCallable<R> {
|
||||
override val isAbstract: Boolean
|
||||
get() = descriptor.modality == Modality.ABSTRACT
|
||||
|
||||
private val isAnnotationConstructor: Boolean
|
||||
protected val isAnnotationConstructor: Boolean
|
||||
get() = name == "<init>" && container.jClass.isAnnotation
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -102,8 +104,12 @@ internal abstract class KCallableImpl<out R> : KCallable<R> {
|
||||
return caller.call(args) as R
|
||||
}
|
||||
|
||||
// See ArgumentGenerator#generate
|
||||
override fun callBy(args: Map<KParameter, Any?>): R {
|
||||
return if (isAnnotationConstructor) callAnnotationConstructor(args) else callDefaultMethod(args)
|
||||
}
|
||||
|
||||
// See ArgumentGenerator#generate
|
||||
private fun callDefaultMethod(args: Map<KParameter, Any?>): R {
|
||||
val parameters = parameters
|
||||
val arguments = ArrayList<Any?>(parameters.size)
|
||||
var mask = 0
|
||||
@@ -153,6 +159,25 @@ internal abstract class KCallableImpl<out R> : KCallable<R> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun callAnnotationConstructor(args: Map<KParameter, Any?>): R {
|
||||
val arguments = parameters.map { parameter ->
|
||||
when {
|
||||
args.containsKey(parameter) -> {
|
||||
args[parameter] ?: throw IllegalArgumentException("Annotation argument value cannot be null ($parameter)")
|
||||
}
|
||||
parameter.isOptional -> null
|
||||
else -> throw IllegalArgumentException("No argument provided for a required parameter: $parameter")
|
||||
}
|
||||
}
|
||||
|
||||
val caller = defaultCaller ?: throw KotlinReflectionInternalError("This callable does not support a default call: $descriptor")
|
||||
|
||||
@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) {
|
||||
|
||||
@@ -170,10 +170,10 @@ internal class KClassImpl<T : Any>(override val jClass: Class<T>) : KDeclaration
|
||||
override val constructorDescriptors: Collection<ConstructorDescriptor>
|
||||
get() {
|
||||
val descriptor = descriptor
|
||||
if (descriptor.kind == ClassKind.CLASS || descriptor.kind == ClassKind.ENUM_CLASS) {
|
||||
return descriptor.constructors
|
||||
if (descriptor.kind == ClassKind.INTERFACE || descriptor.kind == ClassKind.OBJECT) {
|
||||
return emptyList()
|
||||
}
|
||||
return emptyList()
|
||||
return descriptor.constructors
|
||||
}
|
||||
|
||||
override fun getProperties(name: Name): Collection<PropertyDescriptor> =
|
||||
|
||||
@@ -26,6 +26,8 @@ import java.lang.reflect.Modifier
|
||||
import kotlin.jvm.internal.FunctionImpl
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
import kotlin.reflect.jvm.internal.AnnotationConstructorCaller.CallMode.CALL_BY_NAME
|
||||
import kotlin.reflect.jvm.internal.AnnotationConstructorCaller.CallMode.POSITIONAL_CALL
|
||||
import kotlin.reflect.jvm.internal.JvmFunctionSignature.*
|
||||
|
||||
internal class KFunctionImpl private constructor(
|
||||
@@ -48,10 +50,14 @@ internal class KFunctionImpl private constructor(
|
||||
|
||||
private fun isDeclared(): Boolean = Visibilities.isPrivate(descriptor.visibility)
|
||||
|
||||
override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {
|
||||
override val caller: FunctionCaller<*> by ReflectProperties.lazySoft caller@ {
|
||||
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
||||
val member: Member? = when (jvmSignature) {
|
||||
is KotlinConstructor -> container.findConstructorBySignature(jvmSignature.constructorDesc, isDeclared())
|
||||
is KotlinConstructor -> {
|
||||
if (isAnnotationConstructor)
|
||||
return@caller AnnotationConstructorCaller(container.jClass, parameters.map { it.name!! }, POSITIONAL_CALL)
|
||||
container.findConstructorBySignature(jvmSignature.constructorDesc, isDeclared())
|
||||
}
|
||||
is KotlinFunction -> container.findMethodBySignature(jvmSignature.methodName, jvmSignature.methodDesc, isDeclared())
|
||||
is JavaMethod -> jvmSignature.method
|
||||
is JavaConstructor -> jvmSignature.constructor
|
||||
@@ -71,14 +77,16 @@ internal class KFunctionImpl private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override val defaultCaller: FunctionCaller<*>? by ReflectProperties.lazySoft {
|
||||
override val defaultCaller: FunctionCaller<*>? by ReflectProperties.lazySoft defaultCaller@ {
|
||||
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
||||
val member: Member? = when (jvmSignature) {
|
||||
is KotlinFunction -> {
|
||||
container.findDefaultMethod(jvmSignature.methodName, jvmSignature.methodDesc,
|
||||
!Modifier.isStatic(caller.member.modifiers), isDeclared())
|
||||
!Modifier.isStatic(caller.member!!.modifiers), isDeclared())
|
||||
}
|
||||
is KotlinConstructor -> {
|
||||
if (isAnnotationConstructor)
|
||||
return@defaultCaller AnnotationConstructorCaller(container.jClass, parameters.map { it.name!! }, CALL_BY_NAME)
|
||||
container.findDefaultConstructor(jvmSignature.constructorDesc, isDeclared())
|
||||
}
|
||||
else -> {
|
||||
|
||||
Reference in New Issue
Block a user