diff --git a/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt index c0c886d86a1..31cdbd4d3e7 100644 --- a/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt +++ b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt @@ -988,6 +988,13 @@ public open class NativeIndexImpl(val library: NativeLibrary, val verbose: Boole getObjCProtocolAt(cursor) } } + + fun indexObjCCategory(cursor: CValue) { + if (isAvailable(cursor)) { + getObjCCategoryAt(cursor) + } + } + protected open fun String.isUnknownTemplate() = false private fun getParentName(cursor: CValue, pkg: List = emptyList()) : String? { @@ -1225,6 +1232,13 @@ private fun indexDeclarations(nativeIndex: NativeIndexImpl): CompilationWithPCH when (cursor.kind) { CXCursorKind.CXCursor_ObjCInterfaceDecl -> nativeIndex.indexObjCClass(cursor) CXCursorKind.CXCursor_ObjCProtocolDecl -> nativeIndex.indexObjCProtocol(cursor) + CXCursorKind.CXCursor_ObjCCategoryDecl -> { + // This fixes https://youtrack.jetbrains.com/issue/KT-49455, which effectively seems to be a bug in libclang: + // the libclang indexer doesn't properly index categories with + // `__attribute__((external_source_symbol(language="Swift",...)))`. + // As a workaround, additionally enumerate all the categories explicitly. + nativeIndex.indexObjCCategory(cursor) + } else -> {} } } diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/kt49455.h b/kotlin-native/backend.native/tests/interop/objc/tests/kt49455.h new file mode 100644 index 00000000000..faae9d01ce7 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/kt49455.h @@ -0,0 +1,17 @@ +#import + +// https://youtrack.jetbrains.com/issue/KT-49455 + +@interface KT49455 : NSObject +@end; + +__attribute__((external_source_symbol(language="Swift", defined_in="sample",generated_declaration))) +@interface KT49455 (KT49455Ext) +- (int)extensionFunction; +@end + +// Just to ensure that unavailable categories don't break anything. +__attribute__((unavailable("unavailableExtensionFunction is unavailable"))) +@interface KT49455 (KT49455UnavailableExt) +- (int)unavailableExtensionFunction; +@end diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/kt49455.kt b/kotlin-native/backend.native/tests/interop/objc/tests/kt49455.kt new file mode 100644 index 00000000000..88fb3cecdf4 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/kt49455.kt @@ -0,0 +1,7 @@ +import kotlin.test.* +import objcTests.* + +@Test +fun testKT49455() { + assertEquals(111, KT49455().extensionFunction()) +} diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/kt49455.m b/kotlin-native/backend.native/tests/interop/objc/tests/kt49455.m new file mode 100644 index 00000000000..54e2d743b07 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/kt49455.m @@ -0,0 +1,10 @@ +#import "kt49455.h" + +@implementation KT49455 +@end; + +@implementation KT49455 (KT49455Ext) +- (int)extensionFunction { + return 111; +} +@end