diff --git a/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts b/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts index 979440f0b0e..6a28f49298b 100644 --- a/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts +++ b/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts @@ -15,6 +15,7 @@ dependencies { api(project(":compiler:psi")) api(project(":native:objcexport-header-generator")) implementation(project(":core:compiler.common.native")) + implementation(project(":kotlin-util-klib")) testImplementation(projectTests(":native:objcexport-header-generator")) testApi(project(":analysis:analysis-api-standalone")) diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportConfiguration.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportConfiguration.kt index a6d3dd2629f..9743174fc63 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportConfiguration.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportConfiguration.kt @@ -5,6 +5,9 @@ package org.jetbrains.kotlin.objcexport +import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule +import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule + data class KtObjCExportConfiguration( /** * Also used as top level prefix for declarations if present @@ -28,4 +31,16 @@ data class KtObjCExportConfiguration( * (see [org.jetbrains.kotlin.objcexport.objCBaseDeclarations]). */ val generateBaseDeclarationStubs: Boolean = true, + + /** + * The name of modules that are to be exported in this session. + * An exported library shall be read, and its entire API surface shall be translated and presented in the + * objc header at the end. + * + * Libraries/Modules that are not listed in this [exportedModuleNames] will only export types that are used in either source code + * or other exported libraries public surface + * (see [KtLibraryModule.libraryName], [KtSourceModule.moduleName]) + */ + val exportedModuleNames: Set = emptySet(), ) + diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportModuleNaming.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportModuleNaming.kt new file mode 100644 index 00000000000..b31e67a7068 --- /dev/null +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportModuleNaming.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.objcexport + +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule +import org.jetbrains.kotlin.library.ToolingSingleFileKlibResolveStrategy +import org.jetbrains.kotlin.library.shortName +import org.jetbrains.kotlin.library.uniqueName +import org.jetbrains.kotlin.util.DummyLogger +import kotlin.io.path.extension +import kotlin.io.path.isDirectory +import org.jetbrains.kotlin.konan.file.File as KonanFile + +interface KtObjCExportModuleNaming { + context(KtAnalysisSession) + fun getModuleName(module: KtModule): String? + + companion object { + val default = KtObjCExportModuleNaming(listOf(KtKlibObjCExportModuleNaming, KtSimpleObjCExportModuleNaming)) + } +} + +context(KtAnalysisSession, KtObjCExportSession) +internal fun KtModule.getObjCKotlinModuleName(): String? { + return cached(GetObjCKotlinModuleNameCacheKey(this)) { + internal.moduleNaming.getModuleName(this) + } +} + +private class GetObjCKotlinModuleNameCacheKey(private val module: KtModule) { + override fun equals(other: Any?): Boolean { + if (other === this) return true + if (other !is GetObjCKotlinModuleNameCacheKey) return false + return this.module == other.module + } + + override fun hashCode(): Int { + return module.hashCode() + } +} + +/** + * Combines several [implementations] to a single [KtObjCExportModuleNaming]. + * The order of [implementations] matters: The first implementation to resopnd with a module name will win. + */ +fun KtObjCExportModuleNaming(implementations: List): KtObjCExportModuleNaming { + return KtCompositeObjCExportModuleNaming(implementations) +} + +internal object KtKlibObjCExportModuleNaming : KtObjCExportModuleNaming { + context(KtAnalysisSession) + override fun getModuleName(module: KtModule): String? { + /* + In this implementation, we're actually looking into the klib file, trying to resolve + the contained manifest to get the 'shortName' or 'uniqueName'. + + This information is theoretically available already (as also used by the Analysis Api), but not yet accessible. + */ + if (module !is KtLibraryModule) return null + val binaryRoot = module.getBinaryRoots().singleOrNull() ?: return null + if (!binaryRoot.isDirectory() && binaryRoot.extension != "klib") return null + val library = runCatching { ToolingSingleFileKlibResolveStrategy.tryResolve(KonanFile(binaryRoot), DummyLogger) } + .getOrElse { error -> error.printStackTrace(); return null } ?: return null + return library.shortName ?: library.uniqueName + } +} + +internal object KtSimpleObjCExportModuleNaming : KtObjCExportModuleNaming { + context(KtAnalysisSession) + override fun getModuleName(module: KtModule): String? { + return when (module) { + is KtSourceModule -> module.stableModuleName ?: module.moduleName + is KtLibraryModule -> module.libraryName + else -> null + } + } +} + +internal class KtCompositeObjCExportModuleNaming(private val implementations: List) : KtObjCExportModuleNaming { + context(KtAnalysisSession) override fun getModuleName(module: KtModule): String? { + return implementations.firstNotNullOfOrNull { implementation -> implementation.getModuleName(module) } + } +} diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportSession.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportSession.kt index e693adb7cdc..d104a4e71ef 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportSession.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportSession.kt @@ -12,25 +12,46 @@ sealed interface KtObjCExportSession { val configuration: KtObjCExportConfiguration } +/** + * Internal representation of [KtObjCExportSession]. + * All *internal* accessible services shall be added here. + */ +internal sealed interface KtObjCExportSessionInternal : KtObjCExportSession { + val moduleNaming: KtObjCExportModuleNaming +} + +internal val KtObjCExportSession.internal: KtObjCExportSessionInternal + get() = when (this) { + is KtObjCExportSessionInternal -> this + } + +/** + * Private representation of [KtObjCExportSession]. + * All *private* accessible data shall only be added here and potentially + * exposed as functions within this source file + */ +private interface KtObjCExportSessionPrivate : KtObjCExportSessionInternal { + val cache: MutableMap +} + private val KtObjCExportSession.private: KtObjCExportSessionPrivate get() = when (this) { is KtObjCExportSessionPrivate -> this } -private interface KtObjCExportSessionPrivate : KtObjCExportSession { - val cache: MutableMap -} inline fun KtObjCExportSession( configuration: KtObjCExportConfiguration, + moduleNaming: KtObjCExportModuleNaming = KtObjCExportModuleNaming.default, block: KtObjCExportSession.() -> T, ): T { - return KtObjCExportSessionImpl(configuration, hashMapOf()).block() + return KtObjCExportSessionImpl(configuration, moduleNaming, hashMapOf()).block() } @PublishedApi internal class KtObjCExportSessionImpl( override val configuration: KtObjCExportConfiguration, + override val moduleNaming: KtObjCExportModuleNaming, override val cache: MutableMap, ) : KtObjCExportSessionPrivate diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/getObjCClassOrProtocolName.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/getObjCClassOrProtocolName.kt index 6dc012621bf..47fe1ceaf3d 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/getObjCClassOrProtocolName.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/getObjCClassOrProtocolName.kt @@ -6,10 +6,7 @@ package org.jetbrains.kotlin.objcexport import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind -import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol -import org.jetbrains.kotlin.analysis.api.symbols.nameOrAnonymous +import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportClassOrProtocolName import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly @@ -37,8 +34,11 @@ private fun KtClassLikeSymbol.getObjCName( return containingClass.getObjCName() + objCName.capitalizeAsciiOnly() } - // KT-65670: Append module specific prefixes? - return configuration.frameworkName.orEmpty() + objCName + return buildString { + configuration.frameworkName?.let(::append) + getObjCModuleNamePrefix()?.let(::append) + append(objCName) + } } context(KtAnalysisSession, KtObjCExportSession) @@ -71,9 +71,10 @@ private fun KtClassLikeSymbol.getSwiftName( } } - // KT-65670: Append module specific prefixes? - return swiftName - + return buildString { + getObjCModuleNamePrefix()?.let(::append) + append(swiftName) + } } context(KtAnalysisSession, KtObjCExportSession) @@ -111,4 +112,28 @@ private fun KtClassLikeSymbol.canBeOuterSwift(): Boolean { private fun mangleSwiftNestedClassName(name: String): String = when (name) { "Type" -> "${name}_" // See https://github.com/JetBrains/kotlin-native/issues/3167 else -> name +} + +context(KtAnalysisSession, KtObjCExportSession) +private fun KtSymbol.getObjCModuleNamePrefix(): String? { + val module = getContainingModule() + val moduleName = module.getObjCKotlinModuleName() ?: return null + if(moduleName == "stdlib" || moduleName == "kotlin-stdlib-common") return "Kotlin" + if (moduleName in configuration.exportedModuleNames) return null + return abbreviateModuleName(moduleName) +} + +/** + * 'MyModuleName' -> 'MMN' + * 'someLibraryFoo' -> 'SLF' + */ +internal fun abbreviateModuleName(name: String): String { + val normalizedName = name + .capitalizeAsciiOnly() + .replace("[-.]".toRegex(), "_") + + val uppers = normalizedName.filter { character -> character.isUpperCase() } + if (uppers.length >= 3) return uppers + + return normalizedName } \ No newline at end of file diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/getTopLevelFacade.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/getTopLevelFacade.kt index bd887722f81..891b32345a1 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/getTopLevelFacade.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/getTopLevelFacade.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol import org.jetbrains.kotlin.backend.konan.objcexport.ObjCInterface import org.jetbrains.kotlin.backend.konan.objcexport.ObjCInterfaceImpl +import org.jetbrains.kotlin.backend.konan.objcexport.toNameAttributes import org.jetbrains.kotlin.objcexport.analysisApiUtils.getDefaultSuperClassOrProtocolName @@ -59,7 +60,7 @@ fun KtFileSymbol.getTopLevelFacade(): ObjCInterface? { name = fileName.objCName, comment = null, origin = null, - attributes = listOf(OBJC_SUBCLASSING_RESTRICTED), + attributes = listOf(OBJC_SUBCLASSING_RESTRICTED) + fileName.toNameAttributes(), superProtocols = emptyList(), members = extensions.mapNotNull { it.translateToObjCExportStub() }, categoryName = null, diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/AnalysisApiHeaderGenerator.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/AnalysisApiHeaderGenerator.kt index c97fb99ec97..ef34d4f3c69 100644 --- a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/AnalysisApiHeaderGenerator.kt +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/AnalysisApiHeaderGenerator.kt @@ -30,6 +30,7 @@ class AnalysisApiHeaderGeneratorExtension : ParameterResolver { object AnalysisApiHeaderGenerator : HeaderGenerator { override fun generateHeaders(root: File, configuration: HeaderGenerator.Configuration): ObjCHeader { val session = createStandaloneAnalysisApiSession( + kotlinSourceModuleName = defaultKotlinSourceModuleName, kotlinFiles = root.listFiles().orEmpty().filter { it.extension == "kt" }, dependencyKlibs = configuration.dependencies ) @@ -39,7 +40,8 @@ object AnalysisApiHeaderGenerator : HeaderGenerator { KtObjCExportSession( KtObjCExportConfiguration( frameworkName = configuration.frameworkName, - generateBaseDeclarationStubs = configuration.generateBaseDeclarationStubs + generateBaseDeclarationStubs = configuration.generateBaseDeclarationStubs, + exportedModuleNames = setOf(defaultKotlinSourceModuleName) ) ) { translateToObjCHeader(files.map { it as KtFile }) diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/InlineSourceCodeAnalysisExtension.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/InlineSourceCodeAnalysisExtension.kt index f479e4204f2..493998e15d9 100644 --- a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/InlineSourceCodeAnalysisExtension.kt +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/InlineSourceCodeAnalysisExtension.kt @@ -77,14 +77,14 @@ class InlineSourceCodeAnalysisExtension : ParameterResolver, AfterEachCallback { */ private class InlineSourceCodeAnalysisImpl(private val tempDir: File) : InlineSourceCodeAnalysis { override fun createKtFile(@Language("kotlin") sourceCode: String): KtFile { - return createStandaloneAnalysisApiSession(tempDir, mapOf("TestSources.kt" to sourceCode)) + return createStandaloneAnalysisApiSession(tempDir = tempDir, kotlinSources = mapOf("TestSources.kt" to sourceCode)) .modulesWithFiles.entries.single() .value.single() as KtFile } override fun createKtFiles(builder: InlineSourceCodeAnalysis.KtModuleBuilder.() -> Unit): Map { val sources = KtModuleBuilderImpl().also(builder).sources.toMap() - return createStandaloneAnalysisApiSession(tempDir, sources) + return createStandaloneAnalysisApiSession(tempDir = tempDir, kotlinSources = sources) .modulesWithFiles.entries.single() .value.map { it as KtFile } .associateBy { it.name } diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/ObjCExportSessionUtil.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/ObjCExportSessionUtil.kt index 92db97d1bd2..e51c287d6d8 100644 --- a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/ObjCExportSessionUtil.kt +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/ObjCExportSessionUtil.kt @@ -13,7 +13,9 @@ import org.jetbrains.kotlin.psi.KtElement inline fun analyzeWithObjCExport( useSiteKtElement: KtElement, - configuration: KtObjCExportConfiguration = KtObjCExportConfiguration(), + configuration: KtObjCExportConfiguration = KtObjCExportConfiguration( + exportedModuleNames = setOf(defaultKotlinSourceModuleName) + ), action: context(KtAnalysisSession, KtObjCExportSession) () -> T, ): T = analyze(useSiteKtElement) { KtObjCExportSession(configuration) { diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/createAnalysisSession.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/createAnalysisSession.kt index 88f46d02510..f87043cafa5 100644 --- a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/createAnalysisSession.kt +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/createAnalysisSession.kt @@ -20,11 +20,14 @@ import java.nio.file.Path import kotlin.io.path.Path import kotlin.io.path.nameWithoutExtension +const val defaultKotlinSourceModuleName = "testModule" + /** * Creates a standalone analysis session from Kotlin source code passed as [kotlinSources] */ fun createStandaloneAnalysisApiSession( tempDir: File, + kotlinSourceModuleName: String = defaultKotlinSourceModuleName, kotlinSources: Map, dependencyKlibs: List = emptyList(), ): StandaloneAnalysisAPISession { @@ -36,14 +39,18 @@ fun createStandaloneAnalysisApiSession( writeText(sourceCode) } } - return createStandaloneAnalysisApiSession(listOf(testModuleRoot), dependencyKlibs) + return createStandaloneAnalysisApiSession(kotlinSourceModuleName, listOf(testModuleRoot), dependencyKlibs) } /** * Creates a standalone analysis session from [kotlinFiles] on disk. * The Kotlin/Native stdlib will be provided as dependency */ -fun createStandaloneAnalysisApiSession(kotlinFiles: List, dependencyKlibs: List = emptyList()): StandaloneAnalysisAPISession { +fun createStandaloneAnalysisApiSession( + kotlinSourceModuleName: String = defaultKotlinSourceModuleName, + kotlinFiles: List, + dependencyKlibs: List = emptyList(), +): StandaloneAnalysisAPISession { val currentArchitectureTarget = HostManager.host val nativePlatform = NativePlatforms.nativePlatformByTargets(listOf(currentArchitectureTarget)) return buildStandaloneAnalysisAPISession { @@ -77,7 +84,7 @@ fun createStandaloneAnalysisApiSession(kotlinFiles: List, dependencyKlibs: addRegularDependency(dependencyKlibModule) } platform = nativePlatform - moduleName = "source" + moduleName = kotlinSourceModuleName } ) } diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/AbbreviateModuleNameTest.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/AbbreviateModuleNameTest.kt new file mode 100644 index 00000000000..14ac0fcfc11 --- /dev/null +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/AbbreviateModuleNameTest.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.objcexport.tests + +import org.jetbrains.kotlin.objcexport.abbreviateModuleName +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class AbbreviateModuleNameTest { + @Test + fun `test - empty string`() { + assertEquals("", abbreviateModuleName("")) + } + + @Test + fun `test - simple name`() { + assertEquals("Foo", abbreviateModuleName("Foo")) + } + + @Test + fun `test - simple lowercase name`() { + assertEquals("Foo", abbreviateModuleName("foo")) + } + + @Test + fun `test - longer module name`() { + assertEquals("LMN", abbreviateModuleName("LongModuleName")) + } + + @Test + fun `test - longer module name - starting lowercase`() { + assertEquals("LMN", abbreviateModuleName("longModuleName")) + } + + @Test + fun `test - very long module name`() { + assertEquals("TIAVLMN", abbreviateModuleName("thisIsAVeryLongModuleName")) + } +} \ No newline at end of file diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/ForwardedClassesAndProtocolsDependenciesTest.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/ForwardedClassesAndProtocolsDependenciesTest.kt index 6e6a0c4b14b..5eb94b45e21 100644 --- a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/ForwardedClassesAndProtocolsDependenciesTest.kt +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/ForwardedClassesAndProtocolsDependenciesTest.kt @@ -6,6 +6,7 @@ import org.jetbrains.kotlin.backend.konan.objcexport.ObjCHeader import org.jetbrains.kotlin.objcexport.KtObjCExportConfiguration import org.jetbrains.kotlin.objcexport.KtObjCExportSession import org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysis +import org.jetbrains.kotlin.objcexport.testUtils.defaultKotlinSourceModuleName import org.jetbrains.kotlin.objcexport.translateToObjCHeader import org.jetbrains.kotlin.psi.KtFile import org.junit.jupiter.api.Test @@ -24,7 +25,7 @@ class ForwardedClassesAndProtocolsDependenciesTest( code = """ val i: Iterator """, - protocols = setOf("Iterator"), + protocols = setOf("KotlinIterator"), classes = emptySet() ) } @@ -35,8 +36,8 @@ class ForwardedClassesAndProtocolsDependenciesTest( code = """ val i: Array """, - protocols = setOf("Iterator"), - classes = setOf("Array") + protocols = setOf("KotlinIterator"), + classes = setOf("KotlinArray") ) } @@ -46,8 +47,8 @@ class ForwardedClassesAndProtocolsDependenciesTest( code = """ val i: StringBuilder """, - protocols = setOf("CharSequence", "Appendable", "Iterator"), - classes = setOf("StringBuilder", "CharArray", "CharIterator") + protocols = setOf("KotlinCharSequence", "KotlinAppendable", "KotlinIterator"), + classes = setOf("KotlinStringBuilder", "KotlinCharArray", "KotlinCharIterator") ) } @@ -81,7 +82,7 @@ class ForwardedClassesAndProtocolsDependenciesTest( private fun translateClassesAndProtocols(file: KtFile): ObjCHeader { return analyze(file) { - KtObjCExportSession(KtObjCExportConfiguration()) { + KtObjCExportSession(KtObjCExportConfiguration(exportedModuleNames = setOf(defaultKotlinSourceModuleName))) { translateToObjCHeader(listOf(file)) } } diff --git a/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportName.kt b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportName.kt index aa0b74c55f8..8122553c288 100644 --- a/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportName.kt +++ b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportName.kt @@ -83,6 +83,10 @@ fun ObjCExportClassOrProtocolName.toNameAttributes(): List = listOfNotNu swiftName.takeIf { it != objCName }?.let { swiftNameAttribute(it) } ) +fun ObjCExportFileName.toNameAttributes(): List = listOfNotNull( + swiftName.takeIf { it != objCName }?.let { swiftNameAttribute(it) } +) + @InternalKotlinNativeApi fun swiftNameAttribute(swiftName: String) = "swift_name(\"$swiftName\")" diff --git a/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportHeaderGeneratorTest.kt b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportHeaderGeneratorTest.kt index ac5ecacdee5..2b88bdfe06a 100644 --- a/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportHeaderGeneratorTest.kt +++ b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportHeaderGeneratorTest.kt @@ -148,7 +148,6 @@ class ObjCExportHeaderGeneratorTest(private val generator: HeaderGenerator) { } @Test - @TodoAnalysisApi fun `test - functionWithErrorTypeAndFrameworkName`() { doTest(headersTestDataDir.resolve("functionWithErrorTypeAndFrameworkName"), Configuration(frameworkName = "shared")) }