Refactoring. Move transformRuntimeFunctionTypeToSuspendFunction to TypeDeserializer

This commit is contained in:
Ilmir Usmanov
2018-07-24 20:03:39 +03:00
parent 533dd44668
commit a10bd9f5a3
2 changed files with 40 additions and 43 deletions
@@ -79,37 +79,6 @@ fun transformSuspendFunctionToRuntimeFunctionType(suspendFunType: KotlinType, is
).makeNullableAsSpecified(suspendFunType.isMarkedNullable) ).makeNullableAsSpecified(suspendFunType.isMarkedNullable)
} }
fun transformRuntimeFunctionTypeToSuspendFunction(funType: KotlinType, isReleaseCoroutines: Boolean): Pair<SimpleType?, Boolean> {
assert(funType.isFunctionType) {
"This type should be function type: $funType"
}
val continuationArgumentType = funType.getValueParameterTypesFromFunctionType().lastOrNull()?.type ?: return null to false
val continuationArgumentFqName = continuationArgumentType.constructor.declarationDescriptor?.fqNameSafe
if (continuationArgumentType.arguments.size != 1 ||
(!isContinuation(continuationArgumentFqName, isReleaseCoroutines) &&
(!isReleaseCoroutines || !isContinuation(continuationArgumentFqName, !isReleaseCoroutines)))
) {
return funType as? SimpleType to false
}
val suspendReturnType = continuationArgumentType.arguments.single().type
// Load experimental suspend function type as suspend function type
return createFunctionType(
funType.builtIns,
funType.annotations,
funType.getReceiverTypeFromFunctionType(),
funType.getValueParameterTypesFromFunctionType().dropLast(1).map(TypeProjection::getType),
// TODO: names
null,
suspendReturnType,
suspendFunction = true
).makeNullableAsSpecified(funType.isMarkedNullable) to
(isReleaseCoroutines && isContinuation(continuationArgumentFqName, !isReleaseCoroutines))
}
fun isContinuation(name: FqName?, isReleaseCoroutines: Boolean): Boolean { fun isContinuation(name: FqName?, isReleaseCoroutines: Boolean): Boolean {
return if (isReleaseCoroutines) name == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_RELEASE return if (isReleaseCoroutines) name == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_RELEASE
else name == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL else name == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL
@@ -13,9 +13,11 @@ import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.* import org.jetbrains.kotlin.metadata.deserialization.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedAnnotationsWithPossibleTargets import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedAnnotationsWithPossibleTargets
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedTypeParameterDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedTypeParameterDescriptor
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.* import java.util.*
@@ -163,23 +165,49 @@ class TypeDeserializer(
nullable: Boolean nullable: Boolean
): SimpleType? { ): SimpleType? {
val functionType = KotlinTypeFactory.simpleType(annotations, functionTypeConstructor, arguments, nullable) val functionType = KotlinTypeFactory.simpleType(annotations, functionTypeConstructor, arguments, nullable)
if (!functionType.isFunctionType) return null return if (!functionType.isFunctionType) null
else transformRuntimeFunctionTypeToSuspendFunction(functionType)
}
// kotlin.suspend is still built with LV=1.2, thus it references old Continuation private fun transformRuntimeFunctionTypeToSuspendFunction(funType: KotlinType): SimpleType? {
// And otherwise, once stdlib is compiled with 1.3 one may want to stay at LV=1.2 val isReleaseCoroutines = c.components.configuration.releaseCoroutines
if (c.containingDeclaration.safeAs<CallableDescriptor>()?.fqNameOrNull() == KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME) {
val (suspendFun, experimental) = transformRuntimeFunctionTypeToSuspendFunction(functionType, true) val continuationArgumentType = funType.getValueParameterTypesFromFunctionType().lastOrNull()?.type ?: return null
if (experimental) val continuationArgumentFqName = continuationArgumentType.constructor.declarationDescriptor?.fqNameSafe
transformRuntimeFunctionTypeToSuspendFunction(functionType, false).first?.let { return it } if (continuationArgumentType.arguments.size != 1 || !(isContinuation(continuationArgumentFqName, true) ||
else isContinuation(continuationArgumentFqName, false))
return suspendFun ) {
return funType as SimpleType?
} }
val (type, experimental) = transformRuntimeFunctionTypeToSuspendFunction(functionType, c.components.configuration.releaseCoroutines) val suspendReturnType = continuationArgumentType.arguments.single().type
experimentalSuspendFunctionTypeEncountered = experimental || experimentalSuspendFunctionTypeEncountered // Load kotlin.suspend as accepting and returning suspend function type independent of its version requirement
if (c.containingDeclaration.safeAs<CallableDescriptor>()?.fqNameOrNull() == KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME) {
return createSimpleSuspendFunctionType(funType, suspendReturnType)
}
return type // Load experimental suspend function type as suspend function type
experimentalSuspendFunctionTypeEncountered = experimentalSuspendFunctionTypeEncountered ||
(isReleaseCoroutines && isContinuation(continuationArgumentFqName, !isReleaseCoroutines))
return createSimpleSuspendFunctionType(funType, suspendReturnType)
}
private fun createSimpleSuspendFunctionType(
funType: KotlinType,
suspendReturnType: KotlinType
): SimpleType {
return createFunctionType(
funType.builtIns,
funType.annotations,
funType.getReceiverTypeFromFunctionType(),
funType.getValueParameterTypesFromFunctionType().dropLast(1).map(TypeProjection::getType),
// TODO: names
null,
suspendReturnType,
suspendFunction = true
).makeNullableAsSpecified(funType.isMarkedNullable)
} }
private fun typeParameterTypeConstructor(typeParameterId: Int): TypeConstructor? = private fun typeParameterTypeConstructor(typeParameterId: Int): TypeConstructor? =