[Reflection] Fix parsing JVM function descriptors

#KT-60708
This commit is contained in:
Evgeniy.Zhelenskiy
2023-07-26 09:04:02 +02:00
committed by Space Team
parent df14f044cd
commit b89d8a65a1
8 changed files with 66 additions and 13 deletions
@@ -45870,6 +45870,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/reflection/functions/javaMethodsSmokeTest.kt");
}
@Test
@TestMetadata("parentheses.kt")
public void testParentheses() throws Exception {
runTest("compiler/testData/codegen/box/reflection/functions/parentheses.kt");
}
@Test
@TestMetadata("platformName.kt")
public void testPlatformName() throws Exception {
@@ -45870,6 +45870,12 @@ public class FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated
runTest("compiler/testData/codegen/box/reflection/functions/javaMethodsSmokeTest.kt");
}
@Test
@TestMetadata("parentheses.kt")
public void testParentheses() throws Exception {
runTest("compiler/testData/codegen/box/reflection/functions/parentheses.kt");
}
@Test
@TestMetadata("platformName.kt")
public void testPlatformName() throws Exception {
@@ -45870,6 +45870,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/reflection/functions/javaMethodsSmokeTest.kt");
}
@Test
@TestMetadata("parentheses.kt")
public void testParentheses() throws Exception {
runTest("compiler/testData/codegen/box/reflection/functions/parentheses.kt");
}
@Test
@TestMetadata("platformName.kt")
public void testPlatformName() throws Exception {
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
// IGNORE_DEXING
// WITH_REFLECT
data class `)))`(val value: Int)
interface `)` {
fun f(i1: `)))` = `)))`(1)): Int
}
data class `))`(val x: Int): `)` {
override fun f(i1: `)))`) = x + i1.value
}
fun box(): String = if (`))`(2)::f.callBy(mapOf()) == 3) "OK" else "NOT OK"
@@ -45870,6 +45870,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/functions/javaMethodsSmokeTest.kt");
}
@Test
@TestMetadata("parentheses.kt")
public void testParentheses() throws Exception {
runTest("compiler/testData/codegen/box/reflection/functions/parentheses.kt");
}
@Test
@TestMetadata("platformName.kt")
public void testPlatformName() throws Exception {
@@ -45870,6 +45870,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
runTest("compiler/testData/codegen/box/reflection/functions/javaMethodsSmokeTest.kt");
}
@Test
@TestMetadata("parentheses.kt")
public void testParentheses() throws Exception {
runTest("compiler/testData/codegen/box/reflection/functions/parentheses.kt");
}
@Test
@TestMetadata("platformName.kt")
public void testPlatformName() throws Exception {
@@ -36502,6 +36502,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/functions/javaMethodsSmokeTest.kt");
}
@TestMetadata("parentheses.kt")
public void testParentheses() throws Exception {
runTest("compiler/testData/codegen/box/reflection/functions/parentheses.kt");
}
@TestMetadata("platformName.kt")
public void testPlatformName() throws Exception {
runTest("compiler/testData/codegen/box/reflection/functions/platformName.kt");
@@ -212,8 +212,9 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
fun findMethodBySignature(name: String, desc: String): Method? {
if (name == "<init>") return null
val parameterTypes = loadParameterTypes(desc).toTypedArray()
val returnType = loadReturnType(desc)
val functionJvmDescriptor = parseJvmDescriptor(desc, parseReturnType = true)
val parameterTypes = functionJvmDescriptor.parameters.toTypedArray()
val returnType = functionJvmDescriptor.returnType!!
methodOwner.lookupMethod(name, parameterTypes, returnType, false)?.let { return it }
// Methods from java.lang.Object (equals, hashCode, toString) cannot be found in the interface via
@@ -233,23 +234,24 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
// Note that this value is replaced inside the lookupMethod call below, for each class/interface in the hierarchy.
parameterTypes.add(jClass)
}
addParametersAndMasks(parameterTypes, desc, false)
val jvmDescriptor = parseJvmDescriptor(desc, parseReturnType = true)
addParametersAndMasks(parameterTypes, jvmDescriptor.parameters, isConstructor = false)
return methodOwner.lookupMethod(
name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, parameterTypes.toTypedArray(), loadReturnType(desc), isStaticDefault = isMember
name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, parameterTypes.toTypedArray(), jvmDescriptor.returnType!!, isStaticDefault = isMember
)
}
fun findConstructorBySignature(desc: String): Constructor<*>? =
jClass.tryGetConstructor(loadParameterTypes(desc))
jClass.tryGetConstructor(parseJvmDescriptor(desc, parseReturnType = false).parameters)
fun findDefaultConstructor(desc: String): Constructor<*>? =
jClass.tryGetConstructor(arrayListOf<Class<*>>().also { parameterTypes ->
addParametersAndMasks(parameterTypes, desc, true)
val parsedParameters = parseJvmDescriptor(desc, parseReturnType = false).parameters
addParametersAndMasks(parameterTypes, parsedParameters, isConstructor = true)
})
private fun addParametersAndMasks(result: MutableList<Class<*>>, desc: String, isConstructor: Boolean) {
val valueParameters = loadParameterTypes(desc)
private fun addParametersAndMasks(result: MutableList<Class<*>>, valueParameters: List<Class<*>>, isConstructor: Boolean) {
result.addAll(valueParameters)
repeat((valueParameters.size + Integer.SIZE - 1) / Integer.SIZE) {
result.add(Integer.TYPE)
@@ -265,7 +267,9 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
} else result.add(Any::class.java)
}
private fun loadParameterTypes(desc: String): List<Class<*>> {
private class FunctionJvmDescriptor(val parameters: List<Class<*>>, val returnType: Class<*>?)
private fun parseJvmDescriptor(desc: String, parseReturnType: Boolean): FunctionJvmDescriptor {
val result = arrayListOf<Class<*>>()
var begin = 1
@@ -283,7 +287,9 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
begin = end
}
return result
val returnType = if (parseReturnType) parseType(desc, begin = begin + 1, end = desc.length) else null
return FunctionJvmDescriptor(result, returnType)
}
private fun parseType(desc: String, begin: Int, end: Int): Class<*> =
@@ -302,9 +308,6 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
else -> throw KotlinReflectionInternalError("Unknown type prefix in the method signature: $desc")
}
private fun loadReturnType(desc: String): Class<*> =
parseType(desc, desc.indexOf(')') + 1, desc.length)
companion object {
private val DEFAULT_CONSTRUCTOR_MARKER = Class.forName("kotlin.jvm.internal.DefaultConstructorMarker")