From 681c45ef616daefa7d3102cde73a0ecf536f7e10 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 22 Jul 2015 23:21:26 +0300 Subject: [PATCH] Refactor KFunctionImpl internals, get rid of unwrapFakeOverride --- .../reflect/jvm/internal/KFunctionImpl.kt | 99 ++++++------------- .../reflect/jvm/internal/RuntimeTypeMapper.kt | 22 +++-- .../src/kotlin/reflect/jvm/mapping.kt | 4 +- 3 files changed, 43 insertions(+), 82 deletions(-) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt index 77abb1ee8a4..44bb7650c43 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt @@ -19,23 +19,20 @@ package kotlin.reflect.jvm.internal import org.jetbrains.kotlin.descriptors.FunctionDescriptor 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 -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor -import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf import java.lang.reflect.Constructor +import java.lang.reflect.Member import java.lang.reflect.Method import java.lang.reflect.Modifier import kotlin.jvm.internal.FunctionImpl import kotlin.reflect.* +import kotlin.reflect.jvm.internal.JvmFunctionSignature.BuiltInFunction +import kotlin.reflect.jvm.internal.JvmFunctionSignature.JavaConstructor +import kotlin.reflect.jvm.internal.JvmFunctionSignature.JavaMethod +import kotlin.reflect.jvm.internal.JvmFunctionSignature.KotlinFunction open class KFunctionImpl protected constructor( - container: KCallableContainerImpl, + private val container: KCallableContainerImpl, name: String, signature: String, descriptorInitialValue: FunctionDescriptor? @@ -47,80 +44,42 @@ open class KFunctionImpl protected constructor( container, descriptor.name.asString(), RuntimeTypeMapper.mapSignature(descriptor).asString(), descriptor ) - private data class FunctionProtoData( - val proto: ProtoBuf.Callable, - val nameResolver: NameResolver, - val signature: JvmProtoBuf.JvmMethodSignature - ) - override val descriptor: FunctionDescriptor by ReflectProperties.lazySoft(descriptorInitialValue) { container.findFunctionDescriptor(name, signature) } - // null if this is a function declared in a foreign (Java) class - private val protoData: FunctionProtoData? by ReflectProperties.lazyWeak { - val function = DescriptorUtils.unwrapFakeOverride(descriptor) as? DeserializedCallableMemberDescriptor - if (function != null) { - val proto = function.proto - if (proto.hasExtension(JvmProtoBuf.methodSignature)) { - return@lazyWeak FunctionProtoData(proto, function.nameResolver, proto.getExtension(JvmProtoBuf.methodSignature)) - } + override val name: String get() = descriptor.name.asString() + + internal val caller: FunctionCaller by ReflectProperties.lazySoft { + val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor) + val member: Member? = when (jvmSignature) { + is KotlinFunction -> + if (name == "") container.findConstructorBySignature(jvmSignature.signature, jvmSignature.nameResolver, + Visibilities.isPrivate(descriptor.visibility)) + else container.findMethodBySignature(jvmSignature.proto, jvmSignature.signature, jvmSignature.nameResolver, + Visibilities.isPrivate(descriptor.visibility)) + is JavaMethod -> jvmSignature.method + is JavaConstructor -> jvmSignature.constructor + is BuiltInFunction -> throw KotlinReflectionInternalError("Built-in functions are not fully supported yet: $descriptor") } - null - } - internal val javaMethod: Method? by ReflectProperties.lazySoft { - if (!isConstructor) { - val proto = protoData - if (proto != null) { - container.findMethodBySignature(proto.proto, proto.signature, proto.nameResolver, - Visibilities.isPrivate(descriptor.getVisibility())) - } - else { - ((descriptor.getOriginal().getSource() as? JavaSourceElement)?.javaElement as? ReflectJavaMethod)?.member + when (member) { + is Constructor<*> -> FunctionCaller.Constructor(member) + is Method -> when { + !Modifier.isStatic(member.modifiers) -> FunctionCaller.InstanceMethod(member) + descriptor.annotations.findAnnotation(PLATFORM_STATIC) != null -> FunctionCaller.PlatformStaticInObject(member) + else -> FunctionCaller.StaticMethod(member) } + else -> throw KotlinReflectionInternalError("Call is not yet supported for this function: $descriptor") } - else null - } - - internal val javaConstructor: Constructor<*>? by ReflectProperties.lazySoft { - if (isConstructor) { - val proto = protoData - if (proto != null) { - return@lazySoft container.findConstructorBySignature( - proto.signature, proto.nameResolver, Visibilities.isPrivate(descriptor.getVisibility()) - ) - } - else { - ((descriptor.getOriginal().getSource() as? JavaSourceElement)?.javaElement as? ReflectJavaConstructor)?.member - } - } - else null - } - - 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 == "" - override fun getArity(): Int { - // TODO: test? - return descriptor.getValueParameters().size() + - (if (descriptor.getDispatchReceiverParameter() != null) 1 else 0) + - (if (descriptor.getExtensionReceiverParameter() != null) 1 else 0) + return descriptor.valueParameters.size() + + (if (descriptor.dispatchReceiverParameter != null) 1 else 0) + + (if (descriptor.extensionReceiverParameter != null) 1 else 0) } override fun equals(other: Any?): Boolean = diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt index 545c08a4c39..5cd175e55b0 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType +import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.deserialization.NameResolver import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor @@ -40,32 +41,33 @@ import java.lang.reflect.Field import java.lang.reflect.Method import kotlin.reflect.KotlinReflectionInternalError -interface JvmFunctionSignature { - fun asString(): String +sealed class JvmFunctionSignature { + abstract fun asString(): String class KotlinFunction( - private val signature: JvmProtoBuf.JvmMethodSignature, - private val nameResolver: NameResolver - ) : JvmFunctionSignature { + val proto: ProtoBuf.Callable, + val signature: JvmProtoBuf.JvmMethodSignature, + val nameResolver: NameResolver + ) : JvmFunctionSignature() { override fun asString(): String = SignatureDeserializer(nameResolver).methodSignatureString(signature) } - class JavaMethod(private val method: Method) : JvmFunctionSignature { + class JavaMethod(val method: Method) : JvmFunctionSignature() { override fun asString(): String = method.name + method.parameterTypes.joinToString(separator = "", prefix = "(", postfix = ")") { it.desc } + method.returnType.desc } - class JavaConstructor(private val constructor: Constructor<*>) : JvmFunctionSignature { + class JavaConstructor(val constructor: Constructor<*>) : JvmFunctionSignature() { override fun asString(): String = "" + constructor.parameterTypes.joinToString(separator = "", prefix = "(", postfix = ")") { it.desc } + "V" } - class BuiltInFunction(private val signature: String) : JvmFunctionSignature { + class BuiltInFunction(private val signature: String) : JvmFunctionSignature() { override fun asString(): String = signature } } @@ -85,7 +87,7 @@ interface JvmPropertySignature { init { if (signature.hasGetter()) { - string = JvmFunctionSignature.KotlinFunction(signature.getter, nameResolver).asString() + string = SignatureDeserializer(nameResolver).methodSignatureString(signature.getter) } else { string = JvmAbi.getterName(nameResolver.getString(signature.field.name)) + @@ -114,7 +116,7 @@ object RuntimeTypeMapper { val proto = function.proto if (proto.hasExtension(JvmProtoBuf.methodSignature)) { val signature = proto.getExtension(JvmProtoBuf.methodSignature) - return JvmFunctionSignature.KotlinFunction(signature, function.nameResolver) + return JvmFunctionSignature.KotlinFunction(proto, signature, function.nameResolver) } // If it's a deserialized function but has no JVM signature, it must be from built-ins return mapIntrinsicFunctionSignature(function) ?: diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt index 931b75109c6..3697b1ac756 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt @@ -68,7 +68,7 @@ public val KMutableProperty<*>.javaSetter: Method? * or `null` if this function is a constructor or cannot be represented by a Java [Method]. */ public val KFunction<*>.javaMethod: Method? - get() = (this as? KFunctionImpl)?.javaMethod + get() = ((this as? KFunctionImpl)?.caller as? FunctionCaller.Method)?.method /** * Returns a Java [Constructor] instance corresponding to the given Kotlin function, @@ -76,7 +76,7 @@ public val KFunction<*>.javaMethod: Method? */ @suppress("UNCHECKED_CAST") public val KFunction.javaConstructor: Constructor? - get() = (this as? KFunctionImpl)?.javaConstructor as Constructor? + get() = ((this as? KFunctionImpl)?.caller as? FunctionCaller.Constructor)?.constructor as? Constructor