Skip to content

Commit

Permalink
Fix crash caused by returning a flow from a suspend function.
Browse files Browse the repository at this point in the history
  • Loading branch information
FilipDolnik committed Nov 20, 2023
1 parent ff48e3a commit eb51780
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 11 deletions.
2 changes: 1 addition & 1 deletion SKIE/acceptance-tests
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ enum class SupportedFlow(private val directParent: SupportedFlow?) {

sealed interface Variant {

val owner: SupportedFlow
val kind: SupportedFlow

fun getKotlinKirClass(kirProvider: KirProvider): KirClass

Expand All @@ -46,31 +46,31 @@ enum class SupportedFlow(private val directParent: SupportedFlow?) {

fun isCastableTo(variant: Variant): Boolean

class Required(override val owner: SupportedFlow) : Variant {
class Required(override val kind: SupportedFlow) : Variant {

override fun getKotlinKirClass(kirProvider: KirProvider): KirClass =
kirProvider.getClassByFqName("co.touchlab.skie.runtime.coroutines.flow.SkieKotlin${owner.name}")
kirProvider.getClassByFqName("co.touchlab.skie.runtime.coroutines.flow.SkieKotlin${kind.name}")

override fun getSwiftClass(sirProvider: SirProvider): SirClass =
sirProvider.getClassByFqName(SirFqName(sirProvider.skieModule, "SkieSwift${owner.name}"))
sirProvider.getClassByFqName(SirFqName(sirProvider.skieModule, "SkieSwift${kind.name}"))

override fun isCastableTo(variant: Variant): Boolean {
return owner.isSelfOrChildOf(variant.owner)
return kind.isSelfOrChildOf(variant.kind)
}
}

class Optional(override val owner: SupportedFlow) : Variant {
class Optional(override val kind: SupportedFlow) : Variant {

override fun getKotlinKirClass(kirProvider: KirProvider): KirClass =
kirProvider.getClassByFqName("co.touchlab.skie.runtime.coroutines.flow.SkieKotlinOptional${owner.name}")
kirProvider.getClassByFqName("co.touchlab.skie.runtime.coroutines.flow.SkieKotlinOptional${kind.name}")

override fun getSwiftClass(sirProvider: SirProvider): SirClass =
sirProvider.getClassByFqName(SirFqName(sirProvider.skieModule, "SkieSwiftOptional${owner.name}"))
sirProvider.getClassByFqName(SirFqName(sirProvider.skieModule, "SkieSwiftOptional${kind.name}"))

override fun isCastableTo(variant: Variant): Boolean {
if (variant is Required) return false

return owner.isSelfOrChildOf(variant.owner)
return kind.isSelfOrChildOf(variant.kind)
}
}
}
Expand All @@ -80,6 +80,8 @@ enum class SupportedFlow(private val directParent: SupportedFlow?) {

companion object {

val allVariants: List<Variant> = values().flatMap { it.variants }.toList()

fun from(type: KotlinType): SupportedFlow? =
(type.constructor.declarationDescriptor as? ClassDescriptor)?.let { from(it) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import co.touchlab.skie.kir.element.KirSimpleFunction
import co.touchlab.skie.kir.element.forEachAssociatedExportedSirDeclaration
import co.touchlab.skie.phases.DescriptorModificationPhase
import co.touchlab.skie.phases.SirPhase
import co.touchlab.skie.phases.features.flow.SupportedFlow
import co.touchlab.skie.phases.util.doInPhase
import co.touchlab.skie.sir.element.SirClass
import co.touchlab.skie.sir.element.SirExtension
Expand All @@ -15,12 +16,14 @@ import co.touchlab.skie.sir.element.applyToEntireOverrideHierarchy
import co.touchlab.skie.sir.element.copyValueParametersFrom
import co.touchlab.skie.sir.element.shallowCopy
import co.touchlab.skie.sir.element.toSwiftVisibility
import co.touchlab.skie.sir.type.NullableSirType
import co.touchlab.skie.sir.type.OirDeclaredSirType
import co.touchlab.skie.sir.type.SirType
import co.touchlab.skie.util.swift.addFunctionDeclarationBodyWithErrorTypeHandling
import io.outfoxx.swiftpoet.AttributeSpec
import io.outfoxx.swiftpoet.CodeBlock
import io.outfoxx.swiftpoet.FunctionTypeName
import io.outfoxx.swiftpoet.TypeName
import io.outfoxx.swiftpoet.joinToCode
import org.jetbrains.kotlin.descriptors.FunctionDescriptor

class SwiftSuspendGeneratorDelegate(
Expand Down Expand Up @@ -72,18 +75,33 @@ class SwiftSuspendGeneratorDelegate(
}
}

context(SirPhase.Context)
private fun SirExtension.createSwiftBridgingFunction(bridgeModel: BridgeModel): SirSimpleFunction =
bridgeModel.originalFunction.shallowCopy(
parent = this,
isAsync = true,
throws = true,
visibility = bridgeModel.originalFunction.visibility.toSwiftVisibility(),
returnType = bridgeModel.originalFunction.returnType.revertFlowMappingIfNeeded(),
).apply {
copyValueParametersFrom(bridgeModel.originalFunction)

addSwiftBridgingFunctionBody(bridgeModel)
}

context(SirPhase.Context)
private fun SirType.revertFlowMappingIfNeeded(): SirType {
when (this) {
is OirDeclaredSirType -> {
val flowVariant = SupportedFlow.allVariants.firstOrNull { declaration == it.getKotlinKirClass().oirClass } ?: return this

return flowVariant.kind.getCoroutinesKirClass().originalSirClass.toType()
}
is NullableSirType -> return copy(type = type.revertFlowMappingIfNeeded())
else -> return this
}
}

private fun SirSimpleFunction.addSwiftBridgingFunctionBody(bridgeModel: BridgeModel) {
addFunctionDeclarationBodyWithErrorTypeHandling(bridgeModel.kotlinBridgingFunction) {
addCode(
Expand Down

0 comments on commit eb51780

Please sign in to comment.