Simplify calling primitive and nullable @Throws from Swift
Prefer Swift code simplicity over following Obj-C conventions
This commit is contained in:
committed by
SvyatoslavScherbina
parent
cd9812b504
commit
537188fce8
+21
-41
@@ -755,8 +755,6 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var errorOutPtr: LLVMValueRef? = null
|
var errorOutPtr: LLVMValueRef? = null
|
||||||
var kotlinResultOutPtr: LLVMValueRef? = null
|
|
||||||
lateinit var kotlinResultOutBridge: TypeBridge
|
|
||||||
|
|
||||||
val kotlinArgs = methodBridge.paramBridges.mapIndexedNotNull { index, paramBridge ->
|
val kotlinArgs = methodBridge.paramBridges.mapIndexedNotNull { index, paramBridge ->
|
||||||
val parameter = param(index)
|
val parameter = param(index)
|
||||||
@@ -774,13 +772,6 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
|||||||
errorOutPtr = parameter
|
errorOutPtr = parameter
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter -> {
|
|
||||||
assert(kotlinResultOutPtr == null)
|
|
||||||
kotlinResultOutPtr = parameter
|
|
||||||
kotlinResultOutBridge = paramBridge.bridge
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -803,12 +794,12 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
|||||||
|
|
||||||
MethodBridge.ReturnValue.WithError.Success -> Int8(0).llvm // false
|
MethodBridge.ReturnValue.WithError.Success -> Int8(0).llvm // false
|
||||||
|
|
||||||
is MethodBridge.ReturnValue.WithError.RefOrNull -> {
|
is MethodBridge.ReturnValue.WithError.ZeroForError -> {
|
||||||
if (returnType.successBridge == MethodBridge.ReturnValue.Instance.InitResult) {
|
if (returnType.successBridge == MethodBridge.ReturnValue.Instance.InitResult) {
|
||||||
// Release init receiver, as required by convention.
|
// Release init receiver, as required by convention.
|
||||||
callFromBridge(objcRelease, listOf(param(0)))
|
callFromBridge(objcRelease, listOf(param(0)))
|
||||||
}
|
}
|
||||||
kNullInt8Ptr
|
Zero(returnType.objCType(context)).llvm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -818,13 +809,6 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
|||||||
|
|
||||||
val targetResult = callKotlin(kotlinArgs, Lifetime.ARGUMENT, exceptionHandler)
|
val targetResult = callKotlin(kotlinArgs, Lifetime.ARGUMENT, exceptionHandler)
|
||||||
|
|
||||||
kotlinResultOutPtr?.let {
|
|
||||||
ifThen(icmpNe(it, LLVMConstNull(it.type)!!)) {
|
|
||||||
val objCResult = kotlinToObjC(targetResult!!, kotlinResultOutBridge)
|
|
||||||
store(objCResult, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec fun genReturnValueOnSuccess(returnBridge: MethodBridge.ReturnValue): LLVMValueRef? = when (returnBridge) {
|
tailrec fun genReturnValueOnSuccess(returnBridge: MethodBridge.ReturnValue): LLVMValueRef? = when (returnBridge) {
|
||||||
MethodBridge.ReturnValue.Void -> null
|
MethodBridge.ReturnValue.Void -> null
|
||||||
MethodBridge.ReturnValue.HashCode -> {
|
MethodBridge.ReturnValue.HashCode -> {
|
||||||
@@ -833,7 +817,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
|||||||
}
|
}
|
||||||
is MethodBridge.ReturnValue.Mapped -> kotlinToObjC(targetResult!!, returnBridge.bridge)
|
is MethodBridge.ReturnValue.Mapped -> kotlinToObjC(targetResult!!, returnBridge.bridge)
|
||||||
MethodBridge.ReturnValue.WithError.Success -> Int8(1).llvm // true
|
MethodBridge.ReturnValue.WithError.Success -> Int8(1).llvm // true
|
||||||
is MethodBridge.ReturnValue.WithError.RefOrNull -> genReturnValueOnSuccess(returnBridge.successBridge)
|
is MethodBridge.ReturnValue.WithError.ZeroForError -> genReturnValueOnSuccess(returnBridge.successBridge)
|
||||||
MethodBridge.ReturnValue.Instance.InitResult -> param(0)
|
MethodBridge.ReturnValue.Instance.InitResult -> param(0)
|
||||||
MethodBridge.ReturnValue.Instance.FactoryResult -> kotlinReferenceToObjC(targetResult!!) // provided by [callKotlin]
|
MethodBridge.ReturnValue.Instance.FactoryResult -> kotlinReferenceToObjC(targetResult!!) // provided by [callKotlin]
|
||||||
}
|
}
|
||||||
@@ -904,8 +888,6 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
|||||||
|
|
||||||
val result = generateFunction(codegen, functionType, "kotlin2objc") {
|
val result = generateFunction(codegen, functionType, "kotlin2objc") {
|
||||||
var errorOutPtr: LLVMValueRef? = null
|
var errorOutPtr: LLVMValueRef? = null
|
||||||
var kotlinResultOutPtr: LLVMValueRef? = null
|
|
||||||
lateinit var kotlinResultOutBridge: TypeBridge
|
|
||||||
|
|
||||||
val parameters = irFunction.allParameters.mapIndexed { index, parameterDescriptor ->
|
val parameters = irFunction.allParameters.mapIndexed { index, parameterDescriptor ->
|
||||||
parameterDescriptor to param(index)
|
parameterDescriptor to param(index)
|
||||||
@@ -937,12 +919,9 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
|||||||
error("Method is not instance and thus can't have bridge for overriding: $baseMethod")
|
error("Method is not instance and thus can't have bridge for overriding: $baseMethod")
|
||||||
|
|
||||||
MethodBridgeValueParameter.ErrorOutParameter ->
|
MethodBridgeValueParameter.ErrorOutParameter ->
|
||||||
alloca(int8TypePtr).also { errorOutPtr = it }
|
alloca(int8TypePtr).also {
|
||||||
|
store(kNullInt8Ptr, it)
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter ->
|
errorOutPtr = it
|
||||||
alloca(bridge.bridge.objCType).also {
|
|
||||||
kotlinResultOutPtr = it
|
|
||||||
kotlinResultOutBridge = bridge.bridge
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -981,17 +960,20 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
|||||||
ifThen(icmpEq(targetResult, Int8(0).llvm)) {
|
ifThen(icmpEq(targetResult, Int8(0).llvm)) {
|
||||||
rethrow()
|
rethrow()
|
||||||
}
|
}
|
||||||
|
null
|
||||||
kotlinResultOutPtr?.let {
|
|
||||||
objCToKotlin(load(it), kotlinResultOutBridge, lifetime)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is MethodBridge.ReturnValue.WithError.RefOrNull -> {
|
is MethodBridge.ReturnValue.WithError.ZeroForError -> {
|
||||||
ifThen(icmpEq(targetResult, kNullInt8Ptr)) {
|
if (returnBridge.successMayBeZero) {
|
||||||
rethrow()
|
val error = load(errorOutPtr!!)
|
||||||
|
ifThen(icmpNe(error, kNullInt8Ptr)) {
|
||||||
|
rethrow()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ifThen(icmpEq(targetResult, kNullInt8Ptr)) {
|
||||||
|
rethrow()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert(kotlinResultOutPtr == null)
|
|
||||||
genKotlinBaseMethodResult(lifetime, returnBridge.successBridge)
|
genKotlinBaseMethodResult(lifetime, returnBridge.successBridge)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1446,7 +1428,6 @@ private val MethodBridgeParameter.objCType: LLVMTypeRef get() = when (this) {
|
|||||||
is MethodBridgeReceiver -> ReferenceBridge.objCType
|
is MethodBridgeReceiver -> ReferenceBridge.objCType
|
||||||
MethodBridgeSelector -> int8TypePtr
|
MethodBridgeSelector -> int8TypePtr
|
||||||
MethodBridgeValueParameter.ErrorOutParameter -> pointerType(ReferenceBridge.objCType)
|
MethodBridgeValueParameter.ErrorOutParameter -> pointerType(ReferenceBridge.objCType)
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter -> pointerType(this.bridge.objCType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MethodBridge.ReturnValue.objCType(context: Context): LLVMTypeRef {
|
private fun MethodBridge.ReturnValue.objCType(context: Context): LLVMTypeRef {
|
||||||
@@ -1457,8 +1438,8 @@ private fun MethodBridge.ReturnValue.objCType(context: Context): LLVMTypeRef {
|
|||||||
MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.llvmType
|
MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.llvmType
|
||||||
|
|
||||||
MethodBridge.ReturnValue.Instance.InitResult,
|
MethodBridge.ReturnValue.Instance.InitResult,
|
||||||
MethodBridge.ReturnValue.Instance.FactoryResult,
|
MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.objCType
|
||||||
is MethodBridge.ReturnValue.WithError.RefOrNull -> ReferenceBridge.objCType
|
is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.objCType(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1503,8 +1484,8 @@ private fun MethodBridge.ReturnValue.getObjCEncoding(targetFamily: Family): Stri
|
|||||||
MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.encoding
|
MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.encoding
|
||||||
|
|
||||||
MethodBridge.ReturnValue.Instance.InitResult,
|
MethodBridge.ReturnValue.Instance.InitResult,
|
||||||
MethodBridge.ReturnValue.Instance.FactoryResult,
|
MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.objCEncoding
|
||||||
is MethodBridge.ReturnValue.WithError.RefOrNull -> ReferenceBridge.objCEncoding
|
is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.getObjCEncoding(targetFamily)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val MethodBridgeParameter.objCEncoding: String get() = when (this) {
|
private val MethodBridgeParameter.objCEncoding: String get() = when (this) {
|
||||||
@@ -1512,7 +1493,6 @@ private val MethodBridgeParameter.objCEncoding: String get() = when (this) {
|
|||||||
is MethodBridgeReceiver -> ReferenceBridge.objCEncoding
|
is MethodBridgeReceiver -> ReferenceBridge.objCEncoding
|
||||||
MethodBridgeSelector -> ":"
|
MethodBridgeSelector -> ":"
|
||||||
MethodBridgeValueParameter.ErrorOutParameter -> "^${ReferenceBridge.objCEncoding}"
|
MethodBridgeValueParameter.ErrorOutParameter -> "^${ReferenceBridge.objCEncoding}"
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter -> "^${this.bridge.objCEncoding}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val TypeBridge.objCEncoding: String get() = when (this) {
|
private val TypeBridge.objCEncoding: String get() = when (this) {
|
||||||
|
|||||||
+3
-6
@@ -35,7 +35,6 @@ internal object MethodBridgeSelector : MethodBridgeParameter()
|
|||||||
internal sealed class MethodBridgeValueParameter : MethodBridgeParameter() {
|
internal sealed class MethodBridgeValueParameter : MethodBridgeParameter() {
|
||||||
data class Mapped(val bridge: TypeBridge) : MethodBridgeValueParameter()
|
data class Mapped(val bridge: TypeBridge) : MethodBridgeValueParameter()
|
||||||
object ErrorOutParameter : MethodBridgeValueParameter()
|
object ErrorOutParameter : MethodBridgeValueParameter()
|
||||||
data class KotlinResultOutParameter(val bridge: TypeBridge) : MethodBridgeValueParameter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal data class MethodBridge(
|
internal data class MethodBridge(
|
||||||
@@ -55,7 +54,7 @@ internal data class MethodBridge(
|
|||||||
|
|
||||||
sealed class WithError : ReturnValue() {
|
sealed class WithError : ReturnValue() {
|
||||||
object Success : WithError()
|
object Success : WithError()
|
||||||
data class RefOrNull(val successBridge: ReturnValue) : WithError()
|
data class ZeroForError(val successBridge: ReturnValue, val successMayBeZero: Boolean) : WithError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,8 +86,7 @@ internal fun MethodBridge.valueParametersAssociated(
|
|||||||
when (it) {
|
when (it) {
|
||||||
is MethodBridgeValueParameter.Mapped -> it to kotlinParameters.next()
|
is MethodBridgeValueParameter.Mapped -> it to kotlinParameters.next()
|
||||||
|
|
||||||
is MethodBridgeValueParameter.ErrorOutParameter,
|
is MethodBridgeValueParameter.ErrorOutParameter -> it to null
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter -> it to null
|
|
||||||
}
|
}
|
||||||
}.also { assert(!kotlinParameters.hasNext()) }
|
}.also { assert(!kotlinParameters.hasNext()) }
|
||||||
}
|
}
|
||||||
@@ -103,8 +101,7 @@ internal fun MethodBridge.parametersAssociated(
|
|||||||
is MethodBridgeValueParameter.Mapped, MethodBridgeReceiver.Instance ->
|
is MethodBridgeValueParameter.Mapped, MethodBridgeReceiver.Instance ->
|
||||||
it to kotlinParameters.next()
|
it to kotlinParameters.next()
|
||||||
|
|
||||||
MethodBridgeReceiver.Static, MethodBridgeSelector, MethodBridgeValueParameter.ErrorOutParameter,
|
MethodBridgeReceiver.Static, MethodBridgeSelector, MethodBridgeValueParameter.ErrorOutParameter ->
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter ->
|
|
||||||
it to null
|
it to null
|
||||||
|
|
||||||
MethodBridgeReceiver.Factory -> {
|
MethodBridgeReceiver.Factory -> {
|
||||||
|
|||||||
+18
-15
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
|||||||
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
||||||
import org.jetbrains.kotlin.resolve.deprecation.Deprecation
|
import org.jetbrains.kotlin.resolve.deprecation.Deprecation
|
||||||
@@ -582,7 +581,6 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
MethodBridgeValueParameter.ErrorOutParameter -> "error"
|
MethodBridgeValueParameter.ErrorOutParameter -> "error"
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter -> "result"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val uniqueName = unifyName(candidateName, usedNames)
|
val uniqueName = unifyName(candidateName, usedNames)
|
||||||
@@ -592,15 +590,6 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
is MethodBridgeValueParameter.Mapped -> mapType(p!!.type, bridge.bridge, objCExportScope)
|
is MethodBridgeValueParameter.Mapped -> mapType(p!!.type, bridge.bridge, objCExportScope)
|
||||||
MethodBridgeValueParameter.ErrorOutParameter ->
|
MethodBridgeValueParameter.ErrorOutParameter ->
|
||||||
ObjCPointerType(ObjCNullableReferenceType(ObjCClassType("NSError")), nullable = true)
|
ObjCPointerType(ObjCNullableReferenceType(ObjCClassType("NSError")), nullable = true)
|
||||||
|
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter -> {
|
|
||||||
val resultType = mapType(method.returnType!!, bridge.bridge, objCExportScope)
|
|
||||||
// Note: non-nullable reference or pointer type is unusable here
|
|
||||||
// when passing reference to local variable from Swift because it
|
|
||||||
// would require a non-null initializer then.
|
|
||||||
val pointeeType = resultType.makeNullableIfReferenceOrPointer()
|
|
||||||
ObjCPointerType(pointeeType, nullable = true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parameters += ObjCParameter(uniqueName, p, type)
|
parameters += ObjCParameter(uniqueName, p, type)
|
||||||
@@ -621,6 +610,14 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
val attributes = mutableListOf<String>()
|
val attributes = mutableListOf<String>()
|
||||||
|
|
||||||
attributes += swiftNameAttribute(swiftName)
|
attributes += swiftNameAttribute(swiftName)
|
||||||
|
if (baseMethodBridge.returnBridge is MethodBridge.ReturnValue.WithError.ZeroForError
|
||||||
|
&& baseMethodBridge.returnBridge.successMayBeZero) {
|
||||||
|
|
||||||
|
// Method may return zero on success, but
|
||||||
|
// standard Objective-C convention doesn't suppose this happening.
|
||||||
|
// Add non-standard convention hint for Swift:
|
||||||
|
attributes += "swift_error(nonnull_error)" // Means "failure <=> (error != nil)".
|
||||||
|
}
|
||||||
|
|
||||||
if (method is ConstructorDescriptor && !method.constructedClass.isArray) { // TODO: check methodBridge instead.
|
if (method is ConstructorDescriptor && !method.constructedClass.isArray) { // TODO: check methodBridge instead.
|
||||||
attributes += "objc_designated_initializer"
|
attributes += "objc_designated_initializer"
|
||||||
@@ -659,11 +656,17 @@ internal class ObjCExportTranslatorImpl(
|
|||||||
MethodBridge.ReturnValue.HashCode -> ObjCPrimitiveType.NSUInteger
|
MethodBridge.ReturnValue.HashCode -> ObjCPrimitiveType.NSUInteger
|
||||||
is MethodBridge.ReturnValue.Mapped -> mapType(method.returnType!!, returnBridge.bridge, objCExportScope)
|
is MethodBridge.ReturnValue.Mapped -> mapType(method.returnType!!, returnBridge.bridge, objCExportScope)
|
||||||
MethodBridge.ReturnValue.WithError.Success -> ObjCPrimitiveType.BOOL
|
MethodBridge.ReturnValue.WithError.Success -> ObjCPrimitiveType.BOOL
|
||||||
is MethodBridge.ReturnValue.WithError.RefOrNull -> {
|
is MethodBridge.ReturnValue.WithError.ZeroForError -> {
|
||||||
val successReturnType = mapReturnType(returnBridge.successBridge, method, objCExportScope) as? ObjCNonNullReferenceType
|
val successReturnType = mapReturnType(returnBridge.successBridge, method, objCExportScope)
|
||||||
?: error("Function is expected to have non-null return type: $method")
|
|
||||||
|
|
||||||
ObjCNullableReferenceType(successReturnType)
|
if (!returnBridge.successMayBeZero) {
|
||||||
|
check(successReturnType is ObjCNonNullReferenceType
|
||||||
|
|| (successReturnType is ObjCPointerType && !successReturnType.nullable)) {
|
||||||
|
"Unexpected return type: $successReturnType in $method"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
successReturnType.makeNullableIfReferenceOrPointer()
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodBridge.ReturnValue.Instance.InitResult,
|
MethodBridge.ReturnValue.Instance.InitResult,
|
||||||
|
|||||||
+18
-10
@@ -237,7 +237,6 @@ private fun ObjCExportMapper.bridgeParameter(parameter: ParameterDescriptor): Me
|
|||||||
|
|
||||||
private fun ObjCExportMapper.bridgeReturnType(
|
private fun ObjCExportMapper.bridgeReturnType(
|
||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
valueParameters: MutableList<MethodBridgeValueParameter>,
|
|
||||||
convertExceptionsToErrors: Boolean
|
convertExceptionsToErrors: Boolean
|
||||||
): MethodBridge.ReturnValue {
|
): MethodBridge.ReturnValue {
|
||||||
val returnType = descriptor.returnType!!
|
val returnType = descriptor.returnType!!
|
||||||
@@ -247,7 +246,11 @@ private fun ObjCExportMapper.bridgeReturnType(
|
|||||||
} else {
|
} else {
|
||||||
MethodBridge.ReturnValue.Instance.InitResult
|
MethodBridge.ReturnValue.Instance.InitResult
|
||||||
}.let {
|
}.let {
|
||||||
if (convertExceptionsToErrors) MethodBridge.ReturnValue.WithError.RefOrNull(it) else it
|
if (convertExceptionsToErrors) {
|
||||||
|
MethodBridge.ReturnValue.WithError.ZeroForError(it, successMayBeZero = false)
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor.containingDeclaration == descriptor.builtIns.any && descriptor.name.asString() == "hashCode" -> {
|
descriptor.containingDeclaration == descriptor.builtIns.any && descriptor.name.asString() == "hashCode" -> {
|
||||||
@@ -268,20 +271,25 @@ private fun ObjCExportMapper.bridgeReturnType(
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val returnTypeBridge = bridgeType(returnType)
|
val returnTypeBridge = bridgeType(returnType)
|
||||||
|
val successReturnValueBridge = MethodBridge.ReturnValue.Mapped(returnTypeBridge)
|
||||||
if (convertExceptionsToErrors) {
|
if (convertExceptionsToErrors) {
|
||||||
if (returnTypeBridge is ReferenceBridge && !TypeUtils.isNullableType(returnType)) {
|
val canReturnZero = !returnTypeBridge.isReferenceOrPointer() || TypeUtils.isNullableType(returnType)
|
||||||
MethodBridge.ReturnValue.WithError.RefOrNull(MethodBridge.ReturnValue.Mapped(returnTypeBridge))
|
MethodBridge.ReturnValue.WithError.ZeroForError(
|
||||||
} else {
|
successReturnValueBridge,
|
||||||
valueParameters += MethodBridgeValueParameter.KotlinResultOutParameter(returnTypeBridge)
|
successMayBeZero = canReturnZero
|
||||||
MethodBridge.ReturnValue.WithError.Success
|
)
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
MethodBridge.ReturnValue.Mapped(returnTypeBridge)
|
successReturnValueBridge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun TypeBridge.isReferenceOrPointer(): Boolean = when (this) {
|
||||||
|
ReferenceBridge, is BlockPointerBridge -> true
|
||||||
|
is ValueTypeBridge -> this.objCValueType == ObjCValueType.POINTER
|
||||||
|
}
|
||||||
|
|
||||||
private fun ObjCExportMapper.bridgeMethodImpl(descriptor: FunctionDescriptor): MethodBridge {
|
private fun ObjCExportMapper.bridgeMethodImpl(descriptor: FunctionDescriptor): MethodBridge {
|
||||||
assert(isBaseMethod(descriptor))
|
assert(isBaseMethod(descriptor))
|
||||||
|
|
||||||
@@ -306,7 +314,7 @@ private fun ObjCExportMapper.bridgeMethodImpl(descriptor: FunctionDescriptor): M
|
|||||||
valueParameters += bridgeParameter(it)
|
valueParameters += bridgeParameter(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
val returnBridge = bridgeReturnType(descriptor, valueParameters, convertExceptionsToErrors)
|
val returnBridge = bridgeReturnType(descriptor, convertExceptionsToErrors)
|
||||||
if (convertExceptionsToErrors) {
|
if (convertExceptionsToErrors) {
|
||||||
valueParameters += MethodBridgeValueParameter.ErrorOutParameter
|
valueParameters += MethodBridgeValueParameter.ErrorOutParameter
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-4
@@ -453,13 +453,11 @@ internal class ObjCExportNamerImpl(
|
|||||||
else -> it!!.name.asString().toIdentifier()
|
else -> it!!.name.asString().toIdentifier()
|
||||||
}
|
}
|
||||||
MethodBridgeValueParameter.ErrorOutParameter -> "error"
|
MethodBridgeValueParameter.ErrorOutParameter -> "error"
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter -> "result"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
append(when {
|
append(when {
|
||||||
bridge is MethodBridgeValueParameter.ErrorOutParameter ||
|
bridge is MethodBridgeValueParameter.ErrorOutParameter -> "AndReturn"
|
||||||
bridge is MethodBridgeValueParameter.KotlinResultOutParameter -> "AndReturn"
|
|
||||||
|
|
||||||
method is ConstructorDescriptor -> "With"
|
method is ConstructorDescriptor -> "With"
|
||||||
else -> ""
|
else -> ""
|
||||||
@@ -504,7 +502,6 @@ internal class ObjCExportNamerImpl(
|
|||||||
else -> it!!.name.asString().toIdentifier()
|
else -> it!!.name.asString().toIdentifier()
|
||||||
}
|
}
|
||||||
MethodBridgeValueParameter.ErrorOutParameter -> continue@parameters
|
MethodBridgeValueParameter.ErrorOutParameter -> continue@parameters
|
||||||
is MethodBridgeValueParameter.KotlinResultOutParameter -> "result"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
append(label)
|
append(label)
|
||||||
|
|||||||
@@ -270,9 +270,9 @@ __attribute__((swift_name("BridgeBase")))
|
|||||||
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||||
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||||
- (id _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()")));
|
- (id _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()")));
|
||||||
- (BOOL)foo2AndReturnResult:(int32_t * _Nullable)result error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2(result:)")));
|
- (int32_t)foo2AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2()"))) __attribute__((swift_error(nonnull_error)));
|
||||||
- (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()")));
|
- (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()")));
|
||||||
- (BOOL)foo4AndReturnResult:(ValuesKotlinNothing * _Nullable * _Nullable)result error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4(result:)")));
|
- (ValuesKotlinNothing * _Nullable)foo4AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4()"))) __attribute__((swift_error(nonnull_error)));
|
||||||
@end;
|
@end;
|
||||||
|
|
||||||
__attribute__((objc_subclassing_restricted))
|
__attribute__((objc_subclassing_restricted))
|
||||||
@@ -281,9 +281,9 @@ __attribute__((swift_name("Bridge")))
|
|||||||
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||||
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||||
- (ValuesKotlinNothing * _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()")));
|
- (ValuesKotlinNothing * _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()")));
|
||||||
- (BOOL)foo2AndReturnResult:(int32_t * _Nullable)result error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2(result:)")));
|
- (int32_t)foo2AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2()"))) __attribute__((swift_error(nonnull_error)));
|
||||||
- (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()")));
|
- (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()")));
|
||||||
- (BOOL)foo4AndReturnResult:(ValuesKotlinNothing * _Nullable * _Nullable)result error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4(result:)")));
|
- (ValuesKotlinNothing *)foo4AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4()"))) __attribute__((swift_error(nonnull_error)));
|
||||||
@end;
|
@end;
|
||||||
|
|
||||||
__attribute__((objc_subclassing_restricted))
|
__attribute__((objc_subclassing_restricted))
|
||||||
|
|||||||
@@ -291,8 +291,7 @@ func testExceptions() throws {
|
|||||||
try assertTrue(error.kotlinException is MyException)
|
try assertTrue(error.kotlinException is MyException)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
var result: Int32 = 0
|
try bridge.foo2()
|
||||||
try bridge.foo2(result: &result)
|
|
||||||
} catch let error as NSError {
|
} catch let error as NSError {
|
||||||
try assertTrue(error.kotlinException is MyException)
|
try assertTrue(error.kotlinException is MyException)
|
||||||
}
|
}
|
||||||
@@ -302,8 +301,7 @@ func testExceptions() throws {
|
|||||||
try assertTrue(error.kotlinException is MyException)
|
try assertTrue(error.kotlinException is MyException)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
var result: KotlinNothing? = nil
|
try bridge.foo4()
|
||||||
try bridge.foo4(result: &result)
|
|
||||||
} catch let error as NSError {
|
} catch let error as NSError {
|
||||||
try assertTrue(error.kotlinException is MyException)
|
try assertTrue(error.kotlinException is MyException)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user