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");
|
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")
|
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
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");
|
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")
|
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
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");
|
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")
|
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
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");
|
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")
|
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
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])
|
arguments.add(args[parameter])
|
||||||
}
|
}
|
||||||
parameter.isOptional -> {
|
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))
|
mask = mask or (1 shl (index % Integer.SIZE))
|
||||||
anyOptional = true
|
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 =
|
private fun defaultEmptyArray(type: KType): Any =
|
||||||
type.jvmErasure.java.run {
|
type.jvmErasure.java.run {
|
||||||
if (isArray) ReflectArray.newInstance(componentType, 0)
|
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.Method
|
||||||
import java.lang.reflect.Type
|
import java.lang.reflect.Type
|
||||||
import kotlin.reflect.jvm.internal.KotlinReflectionInternalError
|
import kotlin.reflect.jvm.internal.KotlinReflectionInternalError
|
||||||
|
import kotlin.reflect.jvm.internal.defaultPrimitiveValue
|
||||||
import kotlin.reflect.jvm.internal.toJavaClass
|
import kotlin.reflect.jvm.internal.toJavaClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,9 +128,15 @@ internal class InlineClassAwareCaller<out M : Member?>(
|
|||||||
val method = unbox[index]
|
val method = unbox[index]
|
||||||
val arg = args[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
|
// 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] =
|
unboxed[index] = if (method != null) {
|
||||||
if (method != null && arg != null) method.invoke(arg)
|
if (arg != null) {
|
||||||
else arg
|
method.invoke(arg)
|
||||||
|
} else {
|
||||||
|
defaultPrimitiveValue(method.returnType)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
arg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = caller.call(unboxed)
|
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.ReflectJavaAnnotation
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaClass
|
import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaClass
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.safeClassLoader
|
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")
|
internal val JVM_STATIC = FqName("kotlin.jvm.JvmStatic")
|
||||||
|
|
||||||
@@ -195,3 +198,22 @@ internal fun <M : MessageLite, D : CallableDescriptor> deserializeToDescriptor(
|
|||||||
)
|
)
|
||||||
return MemberDeserializer(context).createDescriptor(proto)
|
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");
|
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")
|
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
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");
|
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")
|
@TestMetadata("inlineClassFunctionsAndConstructors.kt")
|
||||||
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
public void testInlineClassFunctionsAndConstructors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user