Refactor KFunctionImpl internals, get rid of unwrapFakeOverride

This commit is contained in:
Alexander Udalov
2015-07-22 23:21:26 +03:00
parent 4c0caad79a
commit 681c45ef61
3 changed files with 43 additions and 82 deletions
@@ -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<FunctionDescriptor>(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 == "<init>") 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 == "<init>"
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 =
@@ -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 =
"<init>" +
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) ?:
@@ -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 <T> KFunction<T>.javaConstructor: Constructor<T>?
get() = (this as? KFunctionImpl)?.javaConstructor as Constructor<T>?
get() = ((this as? KFunctionImpl)?.caller as? FunctionCaller.Constructor)?.constructor as? Constructor<T>