Reflect: Handle methods with inline class default parameters
This commit is contained in:
committed by
Alexander Udalov
parent
86d6470ced
commit
905a8ca0d0
Generated
+5
@@ -23660,6 +23660,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassDefaultArguments.kt")
|
||||
public void testInlineClassDefaultArguments() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE
|
||||
// WITH_REFLECT
|
||||
|
||||
inline class A(val x: Int)
|
||||
|
||||
fun test(x: A = A(0)) = "OK"
|
||||
|
||||
fun box(): String {
|
||||
return (::test).callBy(mapOf())
|
||||
}
|
||||
+5
@@ -25246,6 +25246,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassDefaultArguments.kt")
|
||||
public void testInlineClassDefaultArguments() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
|
||||
+5
@@ -24063,6 +24063,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassDefaultArguments.kt")
|
||||
public void testInlineClassDefaultArguments() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
|
||||
+5
@@ -23660,6 +23660,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassDefaultArguments.kt")
|
||||
public void testInlineClassDefaultArguments() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
|
||||
@@ -132,7 +132,9 @@ internal abstract class KCallableImpl<out R> : KCallable<R> {
|
||||
arguments.add(args[parameter])
|
||||
}
|
||||
parameter.isOptional -> {
|
||||
arguments.add(defaultPrimitiveValue(parameter.type.javaType))
|
||||
// For inline class types, the javaType refers to the underlying type of the inline class,
|
||||
// but we have to pass null in order to mark the argument as absent for InlineClassAwareCaller.
|
||||
arguments.add(if (parameter.type.isInlineClassType) null else defaultPrimitiveValue(parameter.type.javaType))
|
||||
mask = mask or (1 shl (index % Integer.SIZE))
|
||||
anyOptional = true
|
||||
}
|
||||
@@ -192,22 +194,6 @@ internal abstract class KCallableImpl<out R> : KCallable<R> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun defaultPrimitiveValue(type: Type): Any? =
|
||||
if (type is Class<*> && type.isPrimitive) {
|
||||
when (type) {
|
||||
Boolean::class.java -> false
|
||||
Char::class.java -> 0.toChar()
|
||||
Byte::class.java -> 0.toByte()
|
||||
Short::class.java -> 0.toShort()
|
||||
Int::class.java -> 0
|
||||
Float::class.java -> 0f
|
||||
Long::class.java -> 0L
|
||||
Double::class.java -> 0.0
|
||||
Void.TYPE -> throw IllegalStateException("Parameter with void type is illegal")
|
||||
else -> throw UnsupportedOperationException("Unknown primitive: $type")
|
||||
}
|
||||
} else null
|
||||
|
||||
private fun defaultEmptyArray(type: KType): Any =
|
||||
type.jvmErasure.java.run {
|
||||
if (isArray) ReflectArray.newInstance(componentType, 0)
|
||||
|
||||
+10
-3
@@ -17,6 +17,7 @@ import java.lang.reflect.Member
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.reflect.jvm.internal.KotlinReflectionInternalError
|
||||
import kotlin.reflect.jvm.internal.defaultPrimitiveValue
|
||||
import kotlin.reflect.jvm.internal.toJavaClass
|
||||
|
||||
/**
|
||||
@@ -127,9 +128,15 @@ internal class InlineClassAwareCaller<out M : Member?>(
|
||||
val method = unbox[index]
|
||||
val arg = args[index]
|
||||
// Note that arg may be null in case we're calling a $default method and it's an optional parameter of an inline class type
|
||||
unboxed[index] =
|
||||
if (method != null && arg != null) method.invoke(arg)
|
||||
else arg
|
||||
unboxed[index] = if (method != null) {
|
||||
if (arg != null) {
|
||||
method.invoke(arg)
|
||||
} else {
|
||||
defaultPrimitiveValue(method.returnType)
|
||||
}
|
||||
} else {
|
||||
arg
|
||||
}
|
||||
}
|
||||
|
||||
val result = caller.call(unboxed)
|
||||
|
||||
@@ -46,6 +46,9 @@ import org.jetbrains.kotlin.descriptors.runtime.components.tryLoadClass
|
||||
import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaClass
|
||||
import org.jetbrains.kotlin.descriptors.runtime.structure.safeClassLoader
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.reflect.KType
|
||||
|
||||
internal val JVM_STATIC = FqName("kotlin.jvm.JvmStatic")
|
||||
|
||||
@@ -195,3 +198,22 @@ internal fun <M : MessageLite, D : CallableDescriptor> deserializeToDescriptor(
|
||||
)
|
||||
return MemberDeserializer(context).createDescriptor(proto)
|
||||
}
|
||||
|
||||
internal val KType.isInlineClassType: Boolean
|
||||
get() = (this as? KTypeImpl)?.type?.isInlineClassType() == true
|
||||
|
||||
internal fun defaultPrimitiveValue(type: Type): Any? =
|
||||
if (type is Class<*> && type.isPrimitive) {
|
||||
when (type) {
|
||||
Boolean::class.java -> false
|
||||
Char::class.java -> 0.toChar()
|
||||
Byte::class.java -> 0.toByte()
|
||||
Short::class.java -> 0.toShort()
|
||||
Int::class.java -> 0
|
||||
Float::class.java -> 0f
|
||||
Long::class.java -> 0L
|
||||
Double::class.java -> 0.0
|
||||
Void.TYPE -> throw IllegalStateException("Parameter with void type is illegal")
|
||||
else -> throw UnsupportedOperationException("Unknown primitive: $type")
|
||||
}
|
||||
} else null
|
||||
|
||||
Generated
+5
@@ -19911,6 +19911,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassDefaultArguments.kt")
|
||||
public void testInlineClassDefaultArguments() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
|
||||
+5
@@ -19971,6 +19971,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassDefaultArguments.kt")
|
||||
public void testInlineClassDefaultArguments() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||
|
||||
Reference in New Issue
Block a user