Refactor RuntimeTypeMapper, introduce JVM signature classes
Currently only used to obtain the string identical to the one which would be produced by JetTypeMapper.mapSignature, but soon will be used to obtain corresponding reflection objects from classes
This commit is contained in:
@@ -38,8 +38,8 @@ abstract class DescriptorBasedProperty<out R> protected constructor(
|
|||||||
|
|
||||||
constructor(container: KCallableContainerImpl, descriptor: PropertyDescriptor) : this(
|
constructor(container: KCallableContainerImpl, descriptor: PropertyDescriptor) : this(
|
||||||
container,
|
container,
|
||||||
descriptor.getName().asString(),
|
descriptor.name.asString(),
|
||||||
RuntimeTypeMapper.mapPropertySignature(descriptor),
|
RuntimeTypeMapper.mapPropertySignature(descriptor).asString(),
|
||||||
descriptor
|
descriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ abstract class KCallableContainerImpl : KDeclarationContainer {
|
|||||||
.getProperties(Name.guess(name))
|
.getProperties(Name.guess(name))
|
||||||
.filter { descriptor ->
|
.filter { descriptor ->
|
||||||
descriptor is PropertyDescriptor &&
|
descriptor is PropertyDescriptor &&
|
||||||
RuntimeTypeMapper.mapPropertySignature(descriptor) == signature
|
RuntimeTypeMapper.mapPropertySignature(descriptor).asString() == signature
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties.size() != 1) {
|
if (properties.size() != 1) {
|
||||||
@@ -127,7 +127,7 @@ abstract class KCallableContainerImpl : KDeclarationContainer {
|
|||||||
fun findFunctionDescriptor(name: String, signature: String): FunctionDescriptor {
|
fun findFunctionDescriptor(name: String, signature: String): FunctionDescriptor {
|
||||||
val functions = (if (name == "<init>") constructorDescriptors.toList() else scope.getFunctions(Name.guess(name)))
|
val functions = (if (name == "<init>") constructorDescriptors.toList() else scope.getFunctions(Name.guess(name)))
|
||||||
.filter { descriptor ->
|
.filter { descriptor ->
|
||||||
RuntimeTypeMapper.mapSignature(descriptor) == signature
|
RuntimeTypeMapper.mapSignature(descriptor).asString() == signature
|
||||||
}
|
}
|
||||||
|
|
||||||
if (functions.size() != 1) {
|
if (functions.size() != 1) {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ open class KFunctionImpl protected constructor(
|
|||||||
constructor(container: KCallableContainerImpl, name: String, signature: String) : this(container, name, signature, null)
|
constructor(container: KCallableContainerImpl, name: String, signature: String) : this(container, name, signature, null)
|
||||||
|
|
||||||
constructor(container: KCallableContainerImpl, descriptor: FunctionDescriptor) : this(
|
constructor(container: KCallableContainerImpl, descriptor: FunctionDescriptor) : this(
|
||||||
container, descriptor.getName().asString(), RuntimeTypeMapper.mapSignature(descriptor), descriptor
|
container, descriptor.name.asString(), RuntimeTypeMapper.mapSignature(descriptor).asString(), descriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class FunctionProtoData(
|
private data class FunctionProtoData(
|
||||||
|
|||||||
@@ -31,103 +31,145 @@ import org.jetbrains.kotlin.name.ClassId
|
|||||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
||||||
|
import java.lang.reflect.Constructor
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
import java.lang.reflect.Method
|
||||||
import kotlin.reflect.KotlinReflectionInternalError
|
import kotlin.reflect.KotlinReflectionInternalError
|
||||||
|
|
||||||
object RuntimeTypeMapper {
|
interface JvmFunctionSignature {
|
||||||
fun mapSignature(possiblySubstitutedFunction: FunctionDescriptor): String {
|
fun asString(): String
|
||||||
val function = possiblySubstitutedFunction.getOriginal()
|
|
||||||
|
|
||||||
if (function is DeserializedCallableMemberDescriptor) {
|
class KotlinFunction(
|
||||||
val proto = function.proto
|
private val signature: JvmProtoBuf.JvmMethodSignature,
|
||||||
if (!proto.hasExtension(JvmProtoBuf.methodSignature)) {
|
private val nameResolver: NameResolver
|
||||||
|
) : JvmFunctionSignature {
|
||||||
|
override fun asString(): String =
|
||||||
|
SignatureDeserializer(nameResolver).methodSignatureString(signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
class JavaMethod(private 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 {
|
||||||
|
override fun asString(): String =
|
||||||
|
"<init>" +
|
||||||
|
constructor.parameterTypes.joinToString(separator = "", prefix = "(", postfix = ")") { it.desc } +
|
||||||
|
"V"
|
||||||
|
}
|
||||||
|
|
||||||
|
class BuiltInFunction(private val signature: String) : JvmFunctionSignature {
|
||||||
|
override fun asString(): String = signature
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JvmPropertySignature {
|
||||||
|
/**
|
||||||
|
* Returns the JVM signature of the getter of this property. In case the property doesn't have a getter,
|
||||||
|
* constructs the signature of its imaginary default getter. See CallableReference#getSignature for more information
|
||||||
|
*/
|
||||||
|
fun asString(): String
|
||||||
|
|
||||||
|
class KotlinProperty(
|
||||||
|
private val signature: JvmProtoBuf.JvmPropertySignature,
|
||||||
|
private val nameResolver: NameResolver
|
||||||
|
) : JvmPropertySignature {
|
||||||
|
private val string: String
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (signature.hasGetter()) {
|
||||||
|
string = JvmFunctionSignature.KotlinFunction(signature.getter, nameResolver).asString()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
string = JvmAbi.getterName(nameResolver.getString(signature.field.name)) +
|
||||||
|
"()" +
|
||||||
|
SignatureDeserializer(nameResolver).typeDescriptor(signature.field.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun asString(): String = string
|
||||||
|
}
|
||||||
|
|
||||||
|
class JavaImaginaryFieldGetter(private val field: Field) : JvmPropertySignature {
|
||||||
|
override fun asString(): String =
|
||||||
|
JvmAbi.getterName(field.name) +
|
||||||
|
"()" +
|
||||||
|
field.type.desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object RuntimeTypeMapper {
|
||||||
|
fun mapSignature(possiblySubstitutedFunction: FunctionDescriptor): JvmFunctionSignature {
|
||||||
|
val function = possiblySubstitutedFunction.original
|
||||||
|
|
||||||
|
when (function) {
|
||||||
|
is DeserializedCallableMemberDescriptor -> {
|
||||||
|
val proto = function.proto
|
||||||
|
if (proto.hasExtension(JvmProtoBuf.methodSignature)) {
|
||||||
|
val signature = proto.getExtension(JvmProtoBuf.methodSignature)
|
||||||
|
return JvmFunctionSignature.KotlinFunction(signature, function.nameResolver)
|
||||||
|
}
|
||||||
// If it's a deserialized function but has no JVM signature, it must be from built-ins
|
// If it's a deserialized function but has no JVM signature, it must be from built-ins
|
||||||
return mapIntrinsicFunctionSignature(function) ?:
|
return mapIntrinsicFunctionSignature(function) ?:
|
||||||
throw KotlinReflectionInternalError("No metadata found for $function")
|
throw KotlinReflectionInternalError("No metadata found for $function")
|
||||||
}
|
}
|
||||||
val signature = proto.getExtension(JvmProtoBuf.methodSignature)
|
is JavaMethodDescriptor -> {
|
||||||
return SignatureDeserializer(function.nameResolver).methodSignatureString(signature)
|
val method = ((function.source as? JavaSourceElement)?.javaElement as? ReflectJavaMethod)?.member ?:
|
||||||
}
|
throw KotlinReflectionInternalError("Incorrect resolution sequence for Java method $function")
|
||||||
else if (function is JavaMethodDescriptor) {
|
|
||||||
val method = ((function.source as? JavaSourceElement)?.javaElement as? ReflectJavaMethod)?.member ?:
|
|
||||||
throw KotlinReflectionInternalError("Incorrect resolution sequence for Java method $function")
|
|
||||||
|
|
||||||
return StringBuilder {
|
return JvmFunctionSignature.JavaMethod(method)
|
||||||
append(method.name)
|
}
|
||||||
append("(")
|
is JavaConstructorDescriptor -> {
|
||||||
method.parameterTypes.forEach { append(it.desc) }
|
val constructor = ((function.source as? JavaSourceElement)?.javaElement as? ReflectJavaConstructor)?.member ?:
|
||||||
append(")")
|
throw KotlinReflectionInternalError("Incorrect resolution sequence for Java constructor $function")
|
||||||
append(method.returnType.desc)
|
|
||||||
}.toString()
|
|
||||||
}
|
|
||||||
else if (function is JavaConstructorDescriptor) {
|
|
||||||
val constructor = ((function.source as? JavaSourceElement)?.javaElement as? ReflectJavaConstructor)?.member ?:
|
|
||||||
throw KotlinReflectionInternalError("Incorrect resolution sequence for Java constructor $function")
|
|
||||||
|
|
||||||
return StringBuilder {
|
return JvmFunctionSignature.JavaConstructor(constructor)
|
||||||
append("<init>(")
|
}
|
||||||
constructor.parameterTypes.forEach { append(it.desc) }
|
else -> throw KotlinReflectionInternalError("Unknown origin of $function (${function.javaClass})")
|
||||||
append(")V")
|
|
||||||
}.toString()
|
|
||||||
}
|
}
|
||||||
else throw KotlinReflectionInternalError("Unknown origin of $function (${function.javaClass})")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mapPropertySignature(property: PropertyDescriptor): String {
|
fun mapPropertySignature(property: PropertyDescriptor): JvmPropertySignature {
|
||||||
if (property is DeserializedPropertyDescriptor) {
|
if (property is DeserializedPropertyDescriptor) {
|
||||||
val proto = property.proto
|
val proto = property.proto
|
||||||
val nameResolver = property.nameResolver
|
|
||||||
if (!proto.hasExtension(JvmProtoBuf.propertySignature)) {
|
if (!proto.hasExtension(JvmProtoBuf.propertySignature)) {
|
||||||
throw KotlinReflectionInternalError("No metadata found for $property")
|
throw KotlinReflectionInternalError("No metadata found for $property")
|
||||||
}
|
}
|
||||||
val signature = proto.getExtension(JvmProtoBuf.propertySignature)
|
return JvmPropertySignature.KotlinProperty(proto.getExtension(JvmProtoBuf.propertySignature), property.nameResolver)
|
||||||
val deserializer = SignatureDeserializer(nameResolver)
|
|
||||||
|
|
||||||
if (signature.hasGetter()) {
|
|
||||||
return deserializer.methodSignatureString(signature.getGetter())
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case the property doesn't have a getter, construct the signature of its imaginary default getter.
|
|
||||||
// See PropertyReference#getSignature
|
|
||||||
val field = signature.getField()
|
|
||||||
|
|
||||||
// TODO: some kind of test on the Java Bean convention?
|
|
||||||
return JvmAbi.getterName(nameResolver.getString(field.getName())) +
|
|
||||||
"()" +
|
|
||||||
deserializer.typeDescriptor(field.getType())
|
|
||||||
}
|
}
|
||||||
else if (property is JavaPropertyDescriptor) {
|
else if (property is JavaPropertyDescriptor) {
|
||||||
val field = ((property.source as? JavaSourceElement)?.javaElement as? ReflectJavaField)?.member ?:
|
val field = ((property.source as? JavaSourceElement)?.javaElement as? ReflectJavaField)?.member ?:
|
||||||
throw KotlinReflectionInternalError("Incorrect resolution sequence for Java field $property")
|
throw KotlinReflectionInternalError("Incorrect resolution sequence for Java field $property")
|
||||||
|
|
||||||
return StringBuilder {
|
return JvmPropertySignature.JavaImaginaryFieldGetter(field)
|
||||||
append(JvmAbi.getterName(field.name))
|
|
||||||
append("()")
|
|
||||||
append(field.type.desc)
|
|
||||||
}.toString()
|
|
||||||
}
|
}
|
||||||
else throw KotlinReflectionInternalError("Unknown origin of $property (${property.javaClass})")
|
else throw KotlinReflectionInternalError("Unknown origin of $property (${property.javaClass})")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mapIntrinsicFunctionSignature(function: FunctionDescriptor): String? {
|
private fun mapIntrinsicFunctionSignature(function: FunctionDescriptor): JvmFunctionSignature? {
|
||||||
val parameters = function.getValueParameters()
|
val parameters = function.valueParameters
|
||||||
|
|
||||||
when (function.getName().asString()) {
|
when (function.name.asString()) {
|
||||||
"equals" -> {
|
"equals" -> {
|
||||||
if (parameters.size() == 1 && KotlinBuiltIns.isNullableAny(parameters.single().getType())) {
|
if (parameters.size() == 1 && KotlinBuiltIns.isNullableAny(parameters.single().type)) {
|
||||||
return "equals(Ljava/lang/Object;)Z"
|
return JvmFunctionSignature.BuiltInFunction("equals(Ljava/lang/Object;)Z")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"hashCode" -> {
|
"hashCode" -> {
|
||||||
if (parameters.isEmpty()) {
|
if (parameters.isEmpty()) {
|
||||||
return "hashCode()I"
|
return JvmFunctionSignature.BuiltInFunction("hashCode()I")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"toString" -> {
|
"toString" -> {
|
||||||
if (parameters.isEmpty()) {
|
if (parameters.isEmpty()) {
|
||||||
return "toString()Ljava/lang/String;"
|
return JvmFunctionSignature.BuiltInFunction("toString()Ljava/lang/String;")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: generalize and support other functions from built-ins
|
// TODO: generalize and support other functions from built-ins
|
||||||
|
|||||||
Reference in New Issue
Block a user