From 6a8d7ed04344216a1ee5b0912f6ad7ca6479c055 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Tue, 5 Jul 2022 12:12:13 +0300 Subject: [PATCH] [K/N] A bit more KDocs in ObjCExport --- .../objcexport/ObjCExportCodeGenerator.kt | 47 +++++++++++++++++++ .../konan/objcexport/ObjCExportMapper.kt | 16 +++++++ 2 files changed, 63 insertions(+) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index 38addde18b0..a40e3f59763 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -386,6 +386,9 @@ internal class ObjCExportCodeGenerator( this.needsRuntimeInit = true } + /** + * Convert [genValue] of Kotlin type from [actualType] to [expectedType] in a bridge method. + */ inline fun ObjCExportFunctionGenerationContext.convertKotlin( genValue: (Lifetime) -> LLVMValueRef, actualType: IrType, @@ -1451,6 +1454,28 @@ private fun MethodBridge.ReturnValue.isAutoreleasedObjCReference(): Boolean = wh is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.isAutoreleasedObjCReference() } +/** + * Reverse adapters are required when Kotlin code invokes virtual method which might be overriden on Objective-C side. + * Example: + * + * ```kotlin + * interface I { + * fun foo() + * } + * + * fun usage(i: I) { + * i.foo() // Here we invoke + * } + * ``` + * + * ```swift + * class C : I { + * override func foo() { ... } + * } + * + * FileKt.usage(C()) // C.foo is invoked via reverse method adapter. + * ``` + */ private fun ObjCExportCodeGenerator.createReverseAdapter( irFunction: IrFunction, baseMethod: ObjCMethodSpec.BaseMethod, @@ -1471,6 +1496,28 @@ private fun ObjCExportCodeGenerator.createReverseAdapter( kotlinToObjC) } +/** + * We need to generate indirect version of a method for a cases + * when it is called on an object of non-exported type. + * + * Consider the following example: + * file.kt: + * ``` + * open class Foo { + * open fun foo() {} + * } + * private class Bar : Foo() { + * override fun foo() {} + * } + * + * fun createBar(): Foo = Bar() + * ``` + * file.swift: + * ``` + * FileKt.createBar().foo() + * ``` + * There is no Objective-C typeinfo for `Bar`, thus `foo` will be called via method lookup. + */ private fun ObjCExportCodeGenerator.createMethodVirtualAdapter( baseMethod: ObjCMethodSpec.BaseMethod ): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt index f8444074328..10d70bfdcc3 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt @@ -151,6 +151,22 @@ private fun ObjCExportMapper.isBase(descriptor: CallableMemberDescriptor): Boole descriptor.overriddenDescriptors.all { !shouldBeExposed(it) } // e.g. it is not `override`, or overrides only unexposed methods. +/** + * Check that given [descriptor] is a so-called "base method", i.e. method + * that doesn't override anything in a generated Objective-C interface. + * Note that it does not mean that it has no "override" keyword. + * Consider example: + * ```kotlin + * private interface I { + * fun f() + * } + * + * class C : I { + * override fun f() {} + * } + * ``` + * Interface `I` is not exposed to the generated header, so C#f is considered to be a base method even though it has an "override" keyword. + */ internal fun ObjCExportMapper.isBaseMethod(descriptor: FunctionDescriptor) = this.isBase(descriptor)