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:
Ilmir Usmanov
2018-05-29 13:17:53 +03:00
parent 5869274ff1
commit f94b579d19
82 changed files with 5393 additions and 41 deletions
@@ -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
@@ -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)
@@ -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()