Implement callable references to suspend functions
In FE they have type KSuspendFunctionN In BE they are treated like normal callable references with additional parameter in invoke function.
This commit is contained in:
@@ -96,6 +96,13 @@ object JavaToKotlinClassMap : PlatformToKotlinClassMap {
|
||||
val kFun = kFunction.packageFqName.toString() + "." + kFunction.classNamePrefix
|
||||
addKotlinToJava(FqName(kFun + i), ClassId.topLevel(FqName(kFun)))
|
||||
}
|
||||
for (i in 0 until 22) {
|
||||
val kSuspendFunction = FunctionClassDescriptor.Kind.KSuspendFunction
|
||||
val kFunction = FunctionClassDescriptor.Kind.KFunction
|
||||
val kSuspendFun = kSuspendFunction.packageFqName.toString() + "." + kSuspendFunction.classNamePrefix
|
||||
val kFun = kFunction.packageFqName.toString() + "." + kFunction.classNamePrefix
|
||||
addKotlinToJava(FqName(kSuspendFun + i), ClassId.topLevel(FqName(kFun)))
|
||||
}
|
||||
|
||||
addKotlinToJava(FQ_NAMES.nothing.toSafe(), classId(Void::class.java))
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import kotlin.reflect.KProperty
|
||||
|
||||
val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect")
|
||||
val K_FUNCTION_PREFIX = "KFunction"
|
||||
val K_SUSPEND_FUNCTION_PREFIX = "KSuspendFunction"
|
||||
|
||||
class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: NotFoundClasses) {
|
||||
private val kotlinReflectScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
@@ -49,6 +50,7 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not
|
||||
}
|
||||
|
||||
fun getKFunction(n: Int): ClassDescriptor = find("$K_FUNCTION_PREFIX$n", n + 1)
|
||||
fun getKSuspendFunction(n: Int): ClassDescriptor = find("$K_SUSPEND_FUNCTION_PREFIX$n", n + 1)
|
||||
|
||||
val kClass: ClassDescriptor by ClassLookup(1)
|
||||
val kProperty0: ClassDescriptor by ClassLookup(1)
|
||||
@@ -74,6 +76,19 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not
|
||||
return KotlinTypeFactory.simpleNotNullType(annotations, classDescriptor, arguments)
|
||||
}
|
||||
|
||||
fun getKSuspendFunctionType(
|
||||
annotations: Annotations,
|
||||
receiverType: KotlinType?,
|
||||
parameterTypes: List<KotlinType>,
|
||||
parameterNames: List<Name>?,
|
||||
returnType: KotlinType,
|
||||
builtIns: KotlinBuiltIns
|
||||
): SimpleType {
|
||||
val arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, parameterNames, returnType, builtIns)
|
||||
val classDescriptor = getKSuspendFunction(arguments.size - 1 /* return type */)
|
||||
return KotlinTypeFactory.simpleNotNullType(annotations, classDescriptor, arguments)
|
||||
}
|
||||
|
||||
fun getKPropertyType(annotations: Annotations, receiverTypes: List<KotlinType>, returnType: KotlinType, mutable: Boolean): SimpleType {
|
||||
val classDescriptor = when (receiverTypes.size) {
|
||||
0 -> when {
|
||||
@@ -102,7 +117,7 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not
|
||||
}
|
||||
|
||||
fun isCallableType(type: KotlinType): Boolean =
|
||||
type.isFunctionTypeOrSubtype || isKCallableType(type)
|
||||
type.isFunctionTypeOrSubtype || type.isSuspendFunctionType || isKCallableType(type)
|
||||
|
||||
@JvmStatic
|
||||
fun isNumberedKPropertyOrKMutablePropertyType(type: KotlinType): Boolean =
|
||||
@@ -130,9 +145,14 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not
|
||||
val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
val shortName = descriptor.name.asString()
|
||||
|
||||
return shortName.length > K_FUNCTION_PREFIX.length &&
|
||||
shortName.startsWith(K_FUNCTION_PREFIX) &&
|
||||
DescriptorUtils.getFqName(descriptor).parent().toSafe() == KOTLIN_REFLECT_FQ_NAME
|
||||
return (shortName.length > K_FUNCTION_PREFIX.length && shortName.startsWith(K_FUNCTION_PREFIX) || isKSuspendFunction(type)) &&
|
||||
DescriptorUtils.getFqName(descriptor).parent().toSafe() == KOTLIN_REFLECT_FQ_NAME
|
||||
}
|
||||
|
||||
fun isKSuspendFunction(type: KotlinType): Boolean {
|
||||
val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
val shortName = descriptor.name.asString()
|
||||
return shortName.length > K_SUSPEND_FUNCTION_PREFIX.length && shortName.startsWith(K_SUSPEND_FUNCTION_PREFIX)
|
||||
}
|
||||
|
||||
private fun hasFqName(typeConstructor: TypeConstructor, fqName: FqNameUnsafe): Boolean {
|
||||
@@ -162,6 +182,7 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not
|
||||
val packageName = fqName.parent().toSafe()
|
||||
if (packageName == KOTLIN_REFLECT_FQ_NAME) {
|
||||
return shortName.startsWith("KFunction") // KFunctionN, KFunction
|
||||
|| shortName.startsWith("KSuspendFunction") // KPropertyN, KProperty
|
||||
|| shortName.startsWith("KProperty") // KPropertyN, KProperty
|
||||
|| shortName.startsWith("KMutableProperty") // KMutablePropertyN, KMutableProperty
|
||||
|| shortName == "KCallable" || shortName == "KAnnotatedElement"
|
||||
@@ -169,6 +190,7 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not
|
||||
}
|
||||
if (packageName == KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME) {
|
||||
return shortName.startsWith("Function") // FunctionN, Function
|
||||
|| shortName.startsWith("SuspendFunction")
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
+2
-4
@@ -67,7 +67,8 @@ class BuiltInFictitiousFunctionClassFactory(
|
||||
|
||||
override fun shouldCreateClass(packageFqName: FqName, name: Name): Boolean {
|
||||
val string = name.asString()
|
||||
return (string.startsWith("Function") || string.startsWith("KFunction")) // an optimization
|
||||
return (string.startsWith("Function") || string.startsWith("KFunction") ||
|
||||
string.startsWith("SuspendFunction") || string.startsWith("KSuspendFunction")) // an optimization
|
||||
&& parseClassName(string, packageFqName) != null
|
||||
}
|
||||
|
||||
@@ -80,9 +81,6 @@ class BuiltInFictitiousFunctionClassFactory(
|
||||
val packageFqName = classId.packageFqName
|
||||
val (kind, arity) = parseClassName(className, packageFqName) ?: return null
|
||||
|
||||
// SuspendFunction$n can't be created by classId
|
||||
if (kind == Kind.SuspendFunction) return null
|
||||
|
||||
val containingPackageFragment = module.getPackage(packageFqName).fragments.filterIsInstance<BuiltInsPackageFragment>().first()
|
||||
|
||||
return FunctionClassDescriptor(storageManager, containingPackageFragment, kind, arity)
|
||||
|
||||
+14
-8
@@ -39,7 +39,8 @@ class FunctionClassDescriptor(
|
||||
enum class Kind(val packageFqName: FqName, val classNamePrefix: String) {
|
||||
Function(BUILT_INS_PACKAGE_FQ_NAME, "Function"),
|
||||
SuspendFunction(BUILT_INS_PACKAGE_FQ_NAME, "SuspendFunction"),
|
||||
KFunction(KOTLIN_REFLECT_FQ_NAME, "KFunction");
|
||||
KFunction(KOTLIN_REFLECT_FQ_NAME, "KFunction"),
|
||||
KSuspendFunction(KOTLIN_REFLECT_FQ_NAME, "KSuspendFunction");
|
||||
|
||||
fun numberedClassName(arity: Int) = Name.identifier("$classNamePrefix$arity")
|
||||
|
||||
@@ -118,13 +119,13 @@ class FunctionClassDescriptor(
|
||||
}
|
||||
|
||||
|
||||
if (functionKind == Kind.SuspendFunction) {
|
||||
// SuspendFunction$N<...> <: Any
|
||||
result.add(containingDeclaration.builtIns.anyType)
|
||||
}
|
||||
else {
|
||||
// Add unnumbered base class, e.g. Function for Function{n}, KFunction for KFunction{n}
|
||||
add(containingDeclaration, Name.identifier(functionKind.classNamePrefix))
|
||||
when (functionKind) {
|
||||
Kind.SuspendFunction -> // SuspendFunction$N<...> <: Function
|
||||
add(containingDeclaration, Name.identifier("Function"))
|
||||
Kind.KSuspendFunction -> // KSuspendFunction$N<...> <: KFunction
|
||||
add(containingDeclaration, Name.identifier("KFunction"))
|
||||
else -> // Add unnumbered base class, e.g. Function for Function{n}, KFunction for KFunction{n}
|
||||
add(containingDeclaration, Name.identifier(functionKind.classNamePrefix))
|
||||
}
|
||||
|
||||
// For KFunction{n}, add corresponding numbered Function{n} class, e.g. Function2 for KFunction2
|
||||
@@ -133,6 +134,11 @@ class FunctionClassDescriptor(
|
||||
val kotlinPackageFragment = packageView.fragments.filterIsInstance<BuiltInsPackageFragment>().first()
|
||||
|
||||
add(kotlinPackageFragment, Kind.Function.numberedClassName(arity))
|
||||
} else if (functionKind == Kind.KSuspendFunction) {
|
||||
val packageView = containingDeclaration.containingDeclaration.getPackage(BUILT_INS_PACKAGE_FQ_NAME)
|
||||
val kotlinPackageFragment = packageView.fragments.filterIsInstance<BuiltInsPackageFragment>().first()
|
||||
|
||||
add(kotlinPackageFragment, Kind.SuspendFunction.numberedClassName(arity))
|
||||
}
|
||||
|
||||
return result.toList()
|
||||
|
||||
Reference in New Issue
Block a user