diff --git a/.idea/dictionaries/sebastiansellmair.xml b/.idea/dictionaries/sebastiansellmair.xml
index 6185db2e3b8..1aad1b5e75d 100644
--- a/.idea/dictionaries/sebastiansellmair.xml
+++ b/.idea/dictionaries/sebastiansellmair.xml
@@ -7,7 +7,8 @@
instantiator
interops
klibrary
+ namer
undispatched
-
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 11be69ef5cc..89816859c26 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -337,6 +337,8 @@ val projectsUsedInIntelliJKotlinPlugin =
arrayOf(
":native:base",
":native:objcexport-header-generator",
+ ":native:objcexport-header-generator-k1",
+ ":native:objcexport-header-generator-analysis-api",
":compiler:ir.serialization.native"
)
diff --git a/kotlin-native/backend.native/build.gradle b/kotlin-native/backend.native/build.gradle
index 90a3ec607ae..865eba71693 100644
--- a/kotlin-native/backend.native/build.gradle
+++ b/kotlin-native/backend.native/build.gradle
@@ -156,6 +156,7 @@ dependencies {
compilerApi project(":kotlin-native:utilities:basic-utils")
compilerApi project(":native:objcexport-header-generator")
+ compilerApi project(":native:objcexport-header-generator-k1")
compilerApi project(":native:base")
compilerImplementation project(":kotlin-compiler")
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt
index 08d0eec6c9c..93081b79de4 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportProblemCollector
import org.jetbrains.kotlin.backend.konan.objcexport.dumpObjCHeader
import org.jetbrains.kotlin.container.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/ObjCExport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/ObjCExport.kt
index 729841bb95e..4a4a0c9c654 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/ObjCExport.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/ObjCExport.kt
@@ -27,8 +27,8 @@ internal val ProduceObjCExportInterfacePhase = createSimpleNamedCompilerPhase objCReferenceToKotlin(value, resultLifetime)
is BlockPointerBridge -> objCBlockPointerToKotlin(value, typeBridge, resultLifetime)
@@ -894,10 +894,10 @@ private fun ObjCExportFunctionGenerationContextBuilder.setupBridgeDebugInfo() {
}
private inline fun ObjCExportCodeGenerator.generateObjCImpBy(
- methodBridge: MethodBridge,
- debugInfo: Boolean = false,
- suffix: String,
- genBody: ObjCExportFunctionGenerationContext.() -> Unit
+ methodBridge: MethodBridge,
+ debugInfo: Boolean = false,
+ suffix: String,
+ genBody: ObjCExportFunctionGenerationContext.() -> Unit
): LlvmCallable {
val functionType = objCFunctionType(generationState, methodBridge)
val functionName = "objc2kotlin_$suffix"
@@ -923,11 +923,11 @@ private fun ObjCExportCodeGenerator.generateAbstractObjCImp(methodBridge: Method
}
private fun ObjCExportCodeGenerator.generateObjCImp(
- target: IrFunction?,
- baseMethod: IrFunction,
- methodBridge: MethodBridge,
- isVirtual: Boolean = false,
- customBridgeSuffix: String? = null,
+ target: IrFunction?,
+ baseMethod: IrFunction,
+ methodBridge: MethodBridge,
+ isVirtual: Boolean = false,
+ customBridgeSuffix: String? = null,
) = if (target == null) {
generateAbstractObjCImp(methodBridge, baseMethod)
} else {
@@ -953,11 +953,11 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
}
private fun ObjCExportCodeGenerator.generateObjCImp(
- methodBridge: MethodBridge,
- isDirect: Boolean,
- baseMethod: IrFunction? = null,
- bridgeSuffix: String,
- callKotlin: ObjCExportFunctionGenerationContext.(
+ methodBridge: MethodBridge,
+ isDirect: Boolean,
+ baseMethod: IrFunction? = null,
+ bridgeSuffix: String,
+ callKotlin: ObjCExportFunctionGenerationContext.(
args: List,
resultLifetime: Lifetime,
exceptionHandler: ExceptionHandler
@@ -1802,8 +1802,8 @@ private inline fun ObjCExportCodeGenerator.generateObjCToKotlinSyntheticGetter(
): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter {
val methodBridge = MethodBridge(
- MethodBridge.ReturnValue.Mapped(ReferenceBridge),
- MethodBridgeReceiver.Static, valueParameters = emptyList()
+ MethodBridge.ReturnValue.Mapped(ReferenceBridge),
+ MethodBridgeReceiver.Static, valueParameters = emptyList()
)
val functionType = objCFunctionType(generationState, methodBridge)
@@ -1818,9 +1818,9 @@ private inline fun ObjCExportCodeGenerator.generateObjCToKotlinSyntheticGetter(
}
private fun ObjCExportCodeGenerator.objCToKotlinMethodAdapter(
- selector: String,
- methodBridge: MethodBridge,
- imp: LlvmCallable
+ selector: String,
+ methodBridge: MethodBridge,
+ imp: LlvmCallable
): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter {
selectorsToDefine[selector] = methodBridge
@@ -1844,9 +1844,9 @@ private fun ObjCExportCodeGenerator.createObjectInstanceAdapter(
assert(!objectClass.isUnit())
val methodBridge = MethodBridge(
- returnBridge = MethodBridge.ReturnValue.Mapped(ReferenceBridge),
- receiver = MethodBridgeReceiver.Static,
- valueParameters = emptyList()
+ returnBridge = MethodBridge.ReturnValue.Mapped(ReferenceBridge),
+ receiver = MethodBridgeReceiver.Static,
+ valueParameters = emptyList()
)
val function = context.getObjectClassInstanceFunction(objectClass)
@@ -1876,9 +1876,9 @@ private fun ObjCExportCodeGenerator.createEnumValuesOrEntriesAdapter(
selector: String
): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter {
val methodBridge = MethodBridge(
- returnBridge = MethodBridge.ReturnValue.Mapped(ReferenceBridge),
- receiver = MethodBridgeReceiver.Static,
- valueParameters = emptyList()
+ returnBridge = MethodBridge.ReturnValue.Mapped(ReferenceBridge),
+ receiver = MethodBridgeReceiver.Static,
+ valueParameters = emptyList()
)
val imp = generateObjCImp(function, function, methodBridge, isVirtual = false)
@@ -1888,9 +1888,9 @@ private fun ObjCExportCodeGenerator.createEnumValuesOrEntriesAdapter(
private fun ObjCExportCodeGenerator.createThrowableAsErrorAdapter(): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter {
val methodBridge = MethodBridge(
- returnBridge = MethodBridge.ReturnValue.Mapped(ReferenceBridge),
- receiver = MethodBridgeReceiver.Instance,
- valueParameters = emptyList()
+ returnBridge = MethodBridge.ReturnValue.Mapped(ReferenceBridge),
+ receiver = MethodBridgeReceiver.Instance,
+ valueParameters = emptyList()
)
val imp = generateObjCImpBy(methodBridge, suffix = "ThrowableAsError") {
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/BundleBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/BundleBuilder.kt
index 797efb41176..6d3cbf3589d 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/BundleBuilder.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/BundleBuilder.kt
@@ -14,9 +14,9 @@ import org.jetbrains.kotlin.konan.target.Family
* Builds Apple bundle directory.
*/
internal class BundleBuilder(
- private val config: KonanConfig,
- private val infoPListBuilder: InfoPListBuilder,
- private val mainPackageGuesser: MainPackageGuesser,
+ private val config: KonanConfig,
+ private val infoPListBuilder: InfoPListBuilder,
+ private val mainPackageGuesser: MainPackageGuesser,
) {
fun build(
moduleDescriptor: ModuleDescriptor,
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/FrameworkBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/FrameworkBuilder.kt
index 8098723a98e..bc1534ee3a2 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/FrameworkBuilder.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/FrameworkBuilder.kt
@@ -14,11 +14,11 @@ import org.jetbrains.kotlin.konan.target.Family
* Constructs an Apple framework without a binary.
*/
internal class FrameworkBuilder(
- private val config: KonanConfig,
- private val infoPListBuilder: InfoPListBuilder,
- private val moduleMapBuilder: ModuleMapBuilder,
- private val objCHeaderWriter: ObjCHeaderWriter,
- private val mainPackageGuesser: MainPackageGuesser,
+ private val config: KonanConfig,
+ private val infoPListBuilder: InfoPListBuilder,
+ private val moduleMapBuilder: ModuleMapBuilder,
+ private val objCHeaderWriter: ObjCHeaderWriter,
+ private val mainPackageGuesser: MainPackageGuesser,
) {
fun build(
moduleDescriptor: ModuleDescriptor,
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/InfoPListBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/InfoPListBuilder.kt
index 6a75e229716..215826dfc5d 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/InfoPListBuilder.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/InfoPListBuilder.kt
@@ -26,9 +26,9 @@ internal class InfoPListBuilder(
private val configuration = config.configuration
fun build(
- name: String,
- mainPackageGuesser: MainPackageGuesser,
- moduleDescriptor: ModuleDescriptor,
+ name: String,
+ mainPackageGuesser: MainPackageGuesser,
+ moduleDescriptor: ModuleDescriptor,
): String {
val bundleId = computeBundleID(name, mainPackageGuesser, moduleDescriptor)
@@ -124,9 +124,9 @@ internal class InfoPListBuilder(
}
private fun computeBundleID(
- bundleName: String,
- mainPackageGuesser: MainPackageGuesser,
- moduleDescriptor: ModuleDescriptor,
+ bundleName: String,
+ mainPackageGuesser: MainPackageGuesser,
+ moduleDescriptor: ModuleDescriptor,
): String {
val deprecatedBundleIdOption = configuration[KonanConfigKeys.BUNDLE_ID]
val bundleIdOption = configuration[BinaryOptions.bundleId]
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt
index fb70a107aab..381b720b8be 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt
@@ -101,18 +101,18 @@ private class ObjCExportCompilerProblemCollector(val context: PhaseContext) : Ob
* Populate framework directory with headers, module and info.plist.
*/
internal fun createObjCFramework(
- config: KonanConfig,
- moduleDescriptor: ModuleDescriptor,
- exportedInterface: ObjCExportedInterface,
- frameworkDirectory: File
+ config: KonanConfig,
+ moduleDescriptor: ModuleDescriptor,
+ exportedInterface: ObjCExportedInterface,
+ frameworkDirectory: File
) {
val frameworkName = frameworkDirectory.name.removeSuffix(CompilerOutputKind.FRAMEWORK.suffix())
val frameworkBuilder = FrameworkBuilder(
- config,
- infoPListBuilder = InfoPListBuilder(config),
- moduleMapBuilder = ModuleMapBuilder(),
- objCHeaderWriter = ObjCHeaderWriter(),
- mainPackageGuesser = MainPackageGuesser(),
+ config,
+ infoPListBuilder = InfoPListBuilder(config),
+ moduleMapBuilder = ModuleMapBuilder(),
+ objCHeaderWriter = ObjCHeaderWriter(),
+ mainPackageGuesser = MainPackageGuesser(),
)
frameworkBuilder.build(
moduleDescriptor,
@@ -135,10 +135,10 @@ internal fun createTestBundle(
// TODO: No need for such class in dynamic driver.
internal class ObjCExport(
- private val generationState: NativeGenerationState,
- private val moduleDescriptor: ModuleDescriptor,
- private val exportedInterface: ObjCExportedInterface?,
- private val codeSpec: ObjCExportCodeSpec?
+ private val generationState: NativeGenerationState,
+ private val moduleDescriptor: ModuleDescriptor,
+ private val exportedInterface: ObjCExportedInterface?,
+ private val codeSpec: ObjCExportCodeSpec?
) {
private val config = generationState.config
private val target get() = config.target
diff --git a/kotlin-native/build.gradle b/kotlin-native/build.gradle
index eef49bf3515..ee05b6c7c81 100644
--- a/kotlin-native/build.gradle
+++ b/kotlin-native/build.gradle
@@ -164,6 +164,7 @@ dependencies {
distPack project(':kotlin-native:Interop:Skia')
distPack project(':kotlin-native:backend.native')
distPack project(':native:objcexport-header-generator')
+ distPack project(':native:objcexport-header-generator-k1')
distPack project(':native:base')
distPack project(':kotlin-native:utilities:cli-runner')
distPack project(':kotlin-native:utilities:basic-utils')
diff --git a/native/objcexport-header-generator/ReadMe.md b/native/objcexport-header-generator/ReadMe.md
new file mode 100644
index 00000000000..3249b0e7cac
--- /dev/null
+++ b/native/objcexport-header-generator/ReadMe.md
@@ -0,0 +1,61 @@
+# ObjC Export Header generator
+This tool is used for 'translating' Kotlin code into ObjC 'stubs' and ultimately rendering ObjC header files.
+
+## Usage
+
+### CLI: Building .framework files
+The CLI will use this module for building the corresponding .framework binaries from Kotlin. This method will operate on previously
+built .klib binaries (with fully validated frontend). The 'klibs' will be deserialized and headers and bridges between
+Kotlin and ObjC will be built. This mode currently operates on K1 based descriptors
+
+### IDE: Providing Kotlin <-> ObjC/Swift cross language support
+In order for Fleet to provide tooling that is capable of refactoring symbols between Kotlin and ObjC, this tool is used.
+
+Example:
+
+given the following Kotlin code
+
+```kotlin
+@ObjCName("FooObjC")
+class Foo
+```
+
+and the following Swift usage
+
+```swift
+func bar() {
+ FooObjC()
+}
+```
+refactoring inside either Kotlin or Swift will be consistent across Kotlin and Swift.
+
+
+## Two Implementations (K1, Analysis Api)
+
+There are currently two implementations for this tool
+
+### K1
+This is the K1 (descriptor based) implementation that is currently used by the CLI and K1 based IDEs.
+
+### Analysis Api (WiP)
+This implementation is currently 'work in progress' and shall replace the K1 usage in the IDE later.
+This implementation _could_ theoretically also replace the K1 implementation if necessary.
+
+
+## Testing
+
+### Run all tests
+```
+./gradlew :native:objcexport-header-generator:check
+```
+
+The most important test is [ObjCExportHeaderGeneratorTest.kt](test%2Forg%2Fjetbrains%2Fkotlin%2Fbackend%2Fkonan%2Ftests%2FObjCExportHeaderGeneratorTest.kt)
+as this test defines the contract of how a header shall be generated from a given Kotlin input. This test can run against
+both implementations.
+
+```
+./gradlew :native:objcexport-header-generator:testK1
+./gradlew :native:objcexport-header-generator:testAnalysisApi
+```
+
+Note: Since the Analysis Api implementation is WIP yet, this test can be used for debugging, but is not fully implemented yet.
diff --git a/native/objcexport-header-generator/build.gradle.kts b/native/objcexport-header-generator/build.gradle.kts
index b67fa7bac2c..96d7c5d9e39 100644
--- a/native/objcexport-header-generator/build.gradle.kts
+++ b/native/objcexport-header-generator/build.gradle.kts
@@ -1,23 +1,23 @@
+@file:Suppress("HasPlatformType")
+
plugins {
kotlin("jvm")
}
+sourceSets {
+ "main" { projectDefault() }
+ "test" { projectDefault() }
+}
+
dependencies {
- implementation(intellijCore())
- implementation(project(":compiler:cli-base"))
- implementation(project(":compiler:cli-common"))
- implementation(project(":compiler:ir.objcinterop"))
- implementation(project(":compiler:ir.serialization.native"))
- implementation(project(":core:compiler.common.native"))
- implementation(project(":core:descriptors"))
- implementation(project(":native:base"))
- implementation(project(":native:kotlin-native-utils"))
+ api(intellijCore())
+ api(project(":native:base"))
+ api(project(":core:compiler.common"))
- testImplementation(libs.junit.jupiter.api)
- testImplementation(libs.junit.jupiter.params)
- testImplementation(project(":compiler:tests-common", "tests-jar"))
-
- testRuntimeOnly(libs.junit.jupiter.engine)
+ testApi(libs.junit.jupiter.api)
+ testApi(libs.junit.jupiter.engine)
+ testApi(libs.junit.jupiter.params)
+ testApi(project(":compiler:tests-common", "tests-jar"))
}
kotlin {
@@ -26,8 +26,40 @@ kotlin {
}
}
-nativeTest("test", tag = null) {
- useJUnitPlatform()
- systemProperty("projectDir", projectDir.absolutePath)
- workingDir(rootProject.projectDir)
+/* Configure tests */
+
+testsJar()
+
+val k1TestRuntimeClasspath by configurations.creating
+val analysisApiRuntimeClasspath by configurations.creating
+
+dependencies {
+ k1TestRuntimeClasspath(project(":native:objcexport-header-generator-k1"))
+ k1TestRuntimeClasspath(projectTests(":native:objcexport-header-generator-k1"))
+
+ analysisApiRuntimeClasspath(project(":native:objcexport-header-generator-analysis-api"))
+ analysisApiRuntimeClasspath(projectTests(":native:objcexport-header-generator-analysis-api"))
+}
+
+tasks.test.configure {
+ enabled = false
+}
+
+nativeTest("testK1", tag = null) {
+ useJUnitPlatform()
+ enableJunit5ExtensionsAutodetection()
+ classpath += k1TestRuntimeClasspath
+}
+
+nativeTest("testAnalysisApi", tag = null) {
+ useJUnitPlatform()
+ enableJunit5ExtensionsAutodetection()
+ testClassesDirs += files(sourceSets.test.map { it.output.classesDirs })
+ classpath += analysisApiRuntimeClasspath
+}
+
+tasks.check.configure {
+ dependsOn("testK1")
+ dependsOn(":native:objcexport-header-generator-k1:check")
+ dependsOn(":native:objcexport-header-generator-analysis-api:check")
}
diff --git a/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts b/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts
new file mode 100644
index 00000000000..ccaf0633c60
--- /dev/null
+++ b/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts
@@ -0,0 +1,30 @@
+plugins {
+ kotlin("jvm")
+}
+
+kotlin {
+ compilerOptions {
+ /* Required to use Analysis Api */
+ freeCompilerArgs.add("-Xcontext-receivers")
+ }
+}
+
+dependencies {
+ api(project(":native:objcexport-header-generator"))
+ api(project(":analysis:analysis-api"))
+
+ testImplementation(projectTests(":native:objcexport-header-generator"))
+ testApi(project(":analysis:analysis-api-standalone"))
+}
+
+sourceSets {
+ "main" { projectDefault() }
+ "test" { projectDefault() }
+}
+
+testsJar()
+
+nativeTest("test", tag = null) {
+ useJUnitPlatform()
+ enableJunit5ExtensionsAutodetection()
+}
diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportNamer.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportNamer.kt
new file mode 100644
index 00000000000..fbe2fe83e96
--- /dev/null
+++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportNamer.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010-2023 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.api.symbols.KtClassLikeSymbol
+import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
+import org.jetbrains.kotlin.analysis.api.symbols.nameOrAnonymous
+import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportClassOrProtocolName
+import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportPropertyName
+
+interface KtObjCExportNamer {
+ context(KtAnalysisSession)
+ fun getClassOrProtocolName(symbol: KtClassLikeSymbol): ObjCExportClassOrProtocolName
+
+ context(KtAnalysisSession)
+ fun getPropertyName(symbol: KtPropertySymbol): ObjCExportPropertyName
+}
+
+fun ObjCExportNamer(): KtObjCExportNamer {
+ return ObjCExportNamerImpl()
+}
+
+private class ObjCExportNamerImpl : KtObjCExportNamer {
+ context(KtAnalysisSession)
+ override fun getClassOrProtocolName(symbol: KtClassLikeSymbol): ObjCExportClassOrProtocolName {
+ val resolvedObjCNameAnnotation = symbol.resolveObjCNameAnnotation()
+
+ return ObjCExportClassOrProtocolName(
+ objCName = resolvedObjCNameAnnotation.objCName ?: symbol.nameOrAnonymous.asString(),
+ swiftName = resolvedObjCNameAnnotation.swiftName ?: symbol.nameOrAnonymous.asString()
+ )
+ }
+
+ context(KtAnalysisSession)
+ override fun getPropertyName(symbol: KtPropertySymbol): ObjCExportPropertyName {
+ val resolveObjCNameAnnotation = symbol.resolveObjCNameAnnotation()
+
+ return ObjCExportPropertyName(
+ objCName = resolveObjCNameAnnotation.objCName ?: symbol.name.asString(),
+ swiftName = resolveObjCNameAnnotation.swiftName ?: symbol.name.asString()
+ )
+ }
+}
diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtResolvedObjCNameAnnotation.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtResolvedObjCNameAnnotation.kt
new file mode 100644
index 00000000000..b74d8c5c7e0
--- /dev/null
+++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtResolvedObjCNameAnnotation.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010-2023 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.api.annotations.KtConstantAnnotationValue
+import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
+import org.jetbrains.kotlin.analysis.api.base.KtConstantValue.KtStringConstantValue
+import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
+import org.jetbrains.kotlin.backend.konan.KonanFqNames
+
+/**
+ * Represents the values resolved from the [kotlin.native.ObjCName] annotation.
+ *
+ * ### Example
+ *
+ * **Given a class Foo**
+ * ```kotlin
+ * @ObjCName("FooObjC", "FooSwift", true)
+ * class Foo
+ * ```
+ *
+ * **Given class Foo being analyzed**
+ * ```kotlin
+ * val foo = getFooClassOrObjectSymbol()
+ * // ^
+ * // Imaginary method to get the symbol 'Foo' from above
+ *
+ * val resolvedObjCNameAnnotation = foo.resolveObjCNameAnnotation()
+ * // ^
+ * // objCName = "FooObjC"
+ * // swiftName = "FooSwift"
+ * // isExaclt = true
+ * ```
+ */
+internal class KtResolvedObjCNameAnnotation(
+ val objCName: String?,
+ val swiftName: String?,
+ val isExact: Boolean,
+)
+
+context(KtAnalysisSession)
+internal fun KtAnnotatedSymbol.resolveObjCNameAnnotation(): KtResolvedObjCNameAnnotation {
+ var objCName: String? = null
+ var swiftName: String? = null
+ var isExact = false
+
+ annotationsList.annotations.find { it.classId?.asSingleFqName() == KonanFqNames.objCName }?.let { annotation ->
+ annotation.arguments.forEach { argument ->
+ when (argument.name.identifier) {
+ "name" -> objCName = argument.expression.let { it as? KtConstantAnnotationValue }
+ ?.constantValue?.let { it as KtStringConstantValue }
+ ?.value
+ "swiftName" -> swiftName = argument.expression.let { it as? KtConstantAnnotationValue }
+ ?.constantValue?.let { it as KtStringConstantValue }
+ ?.value
+ "exact" -> isExact = argument.expression.let { it as? KtConstantAnnotationValue }
+ ?.constantValue?.let { it as KtConstantValue.KtBooleanConstantValue }
+ ?.value ?: isExact
+ }
+ }
+ }
+
+ return KtResolvedObjCNameAnnotation(
+ objCName = objCName,
+ swiftName = swiftName,
+ isExact = isExact
+ )
+}
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
new file mode 100644
index 00000000000..c79e4fd788a
--- /dev/null
+++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/AnalysisApiHeaderGenerator.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010-2023 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.testUtils
+
+import org.jetbrains.kotlin.backend.konan.tests.ObjCExportHeaderGeneratorTest.HeaderGenerator
+import org.junit.jupiter.api.extension.ExtensionContext
+import org.junit.jupiter.api.extension.ParameterContext
+import org.junit.jupiter.api.extension.ParameterResolver
+import java.io.File
+
+class AnalysisApiHeaderGeneratorExtension : ParameterResolver {
+ override fun supportsParameter(parameterContext: ParameterContext, extensionContext: ExtensionContext): Boolean {
+ return parameterContext.parameter.type == HeaderGenerator::class.java
+ }
+
+ override fun resolveParameter(parameterContext: ParameterContext, extensionContext: ExtensionContext): Any {
+ return AnalysisApiHeaderGenerator
+ }
+}
+
+object AnalysisApiHeaderGenerator : HeaderGenerator {
+ override fun generateHeaders(root: File): String {
+ TODO("Analysis Api based header generation in not yet implemented")
+ }
+}
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
new file mode 100644
index 00000000000..d8e2cc92d8b
--- /dev/null
+++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/InlineSourceCodeAnalysisExtension.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010-2023 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.testUtils
+
+import org.intellij.lang.annotations.Language
+import org.jetbrains.kotlin.psi.KtFile
+import org.junit.jupiter.api.extension.AfterEachCallback
+import org.junit.jupiter.api.extension.ExtensionContext
+import org.junit.jupiter.api.extension.ExtensionContext.Namespace
+import org.junit.jupiter.api.extension.ParameterContext
+import org.junit.jupiter.api.extension.ParameterResolver
+import java.io.File
+import java.nio.file.Files
+
+/**
+ * Provides ability to quickly write tests with 'inline source code' aka passing Kotlin source code as String.
+ *
+ * This interface can be injected into any test class constructor.
+ *
+ * ### Example
+ * ```
+ * class MyTest(
+ * private val inlineSourceCodeAnalysis: InlineSourceCodeAnalysis
+ * ) {
+ * @Test
+ * fun `test - something important`() {
+ * val myFile = inlineSourceCodeAnalysis.createKtFile("class Foo")
+ * analyze(myFile) {
+ * // Use analysis session to write advanced tests
+ * }
+ * }
+ * }
+ * ```
+ */
+interface InlineSourceCodeAnalysis {
+ fun createKtFile(@Language("kotlin") sourceCode: String): KtFile
+}
+
+/**
+ * Extension used to inject an instance of [InlineSourceCodeAnalysis] into tests.
+ */
+class InlineSourceCodeAnalysisExtension : ParameterResolver, AfterEachCallback {
+ private companion object {
+ val namespace: Namespace = Namespace.create(Any())
+ val tempDirKey = Any()
+ }
+
+ override fun supportsParameter(parameterContext: ParameterContext, extensionContext: ExtensionContext): Boolean {
+ return parameterContext.parameter.type == InlineSourceCodeAnalysis::class.java
+ }
+
+ override fun resolveParameter(parameterContext: ParameterContext, extensionContext: ExtensionContext): Any {
+ val temporaryDirectory = Files.createTempDirectory("inlineSourceCode").toFile()
+ extensionContext.getStore(namespace.append(extensionContext.requiredTestClass)).put(tempDirKey, temporaryDirectory)
+ return InlineSourceCodeAnalysisImpl(temporaryDirectory)
+ }
+
+ override fun afterEach(context: ExtensionContext) {
+ context.getStore(namespace.append(context.requiredTestClass))?.get(tempDirKey, File::class.java)?.deleteRecursively()
+ }
+}
+
+/**
+ * Simple implementation [InlineSourceCodeAnalysis]
+ */
+private class InlineSourceCodeAnalysisImpl(private val tempDir: File) : InlineSourceCodeAnalysis {
+ override fun createKtFile(@Language("kotlin") sourceCode: String): KtFile {
+ return createStandaloneAnalysisApiSession(tempDir, listOf(sourceCode))
+ .modulesWithFiles.entries.single()
+ .value.single() as KtFile
+ }
+}
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
new file mode 100644
index 00000000000..05ebb2fc6e9
--- /dev/null
+++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/createAnalysisSession.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010-2023 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.testUtils
+
+import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeTokenProvider
+import org.jetbrains.kotlin.analysis.api.standalone.KtAlwaysAccessibleLifetimeTokenProvider
+import org.jetbrains.kotlin.analysis.api.standalone.StandaloneAnalysisAPISession
+import org.jetbrains.kotlin.analysis.api.standalone.buildStandaloneAnalysisAPISession
+import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtLibraryModule
+import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtSourceModule
+import org.jetbrains.kotlin.backend.konan.testUtils.kotlinNativeStdlibPath
+import org.jetbrains.kotlin.konan.target.HostManager
+import org.jetbrains.kotlin.platform.konan.NativePlatforms
+import java.io.File
+import kotlin.io.path.Path
+
+/**
+ * Creates a standalone analysis session from Kotlin source code passed as [kotlinSources]
+ */
+fun createStandaloneAnalysisApiSession(
+ tempDir: File,
+ kotlinSources: List,
+): StandaloneAnalysisAPISession {
+ val testModuleRoot = tempDir.resolve("testModule")
+ testModuleRoot.mkdirs()
+
+ kotlinSources.forEachIndexed { index, kotlinSource ->
+ testModuleRoot.resolve("TestSources$index.kt").apply {
+ writeText(kotlinSource)
+ }
+ }
+ return createStandaloneAnalysisApiSession(listOf(testModuleRoot))
+}
+
+/**
+ * Creates a standalone analysis session from [kotlinFiles] on disk.
+ * The Kotlin/Native stdlib will be provided as dependency
+ */
+fun createStandaloneAnalysisApiSession(kotlinFiles: List): StandaloneAnalysisAPISession {
+ val currentArchitectureTarget = HostManager.host
+ val nativePlatform = NativePlatforms.nativePlatformByTargets(listOf(currentArchitectureTarget))
+ return buildStandaloneAnalysisAPISession {
+ @OptIn(KtAnalysisApiInternals::class)
+ registerProjectService(KtLifetimeTokenProvider::class.java, KtAlwaysAccessibleLifetimeTokenProvider())
+
+ buildKtModuleProvider {
+ platform = nativePlatform
+ val kLib = addModule(
+ buildKtLibraryModule {
+ addBinaryRoot(Path(kotlinNativeStdlibPath))
+ platform = nativePlatform
+ libraryName = "klib"
+ }
+ )
+ addModule(
+ buildKtSourceModule {
+ addSourceRoots(kotlinFiles.map { it.toPath() })
+ addRegularDependency(kLib)
+ platform = nativePlatform
+ moduleName = "source"
+ }
+ )
+ }
+ }
+}
diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtObjCExportNamerTest.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtObjCExportNamerTest.kt
new file mode 100644
index 00000000000..d80bcf14338
--- /dev/null
+++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtObjCExportNamerTest.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010-2023 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.analysis.api.analyze
+import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
+import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportClassOrProtocolName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.objcexport.ObjCExportNamer
+import org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysis
+import org.junit.jupiter.api.Test
+import kotlin.test.assertEquals
+
+class KtObjCExportNamerTest(
+ private val inlineSourceCodeAnalysis: InlineSourceCodeAnalysis,
+) {
+
+ private val namer = ObjCExportNamer()
+
+ @Test
+ fun `test - simple class`() {
+ val foo = inlineSourceCodeAnalysis.createKtFile("class Foo")
+ analyze(foo) {
+ val fooSymbol = foo.getFileSymbol().getFileScope()
+ .getClassifierSymbols(Name.identifier("Foo"))
+ .single() as KtNamedClassOrObjectSymbol
+
+ assertEquals(
+ ObjCExportClassOrProtocolName("Foo", "Foo"),
+ namer.getClassOrProtocolName(fooSymbol)
+ )
+ }
+ }
+}
diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtResolvedObjCNameAnnotationTest.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtResolvedObjCNameAnnotationTest.kt
new file mode 100644
index 00000000000..c8c13214831
--- /dev/null
+++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtResolvedObjCNameAnnotationTest.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010-2023 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.resolveObjCNameAnnotation
+import org.jetbrains.kotlin.analysis.api.analyze
+import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
+import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysis
+import org.junit.jupiter.api.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertNull
+import kotlin.test.assertTrue
+
+class KtResolvedObjCNameAnnotationTest(
+ private val inlineSourceCodeAnalysis: InlineSourceCodeAnalysis,
+) {
+
+ @Test
+ fun `test - class - no ObjCName annotation`() {
+ val ktFile = inlineSourceCodeAnalysis.createKtFile("class Foo")
+ analyze(ktFile) {
+ val fooSymbol = ktFile.getFileSymbol().getFileScope().getClassifierSymbols(Name.identifier("Foo")).single() as KtClassLikeSymbol
+ val resolvedObjCAnnotation = fooSymbol.resolveObjCNameAnnotation()
+ assertNull(resolvedObjCAnnotation.swiftName)
+ assertNull(resolvedObjCAnnotation.objCName)
+ assertFalse(resolvedObjCAnnotation.isExact)
+ }
+ }
+
+ @Test
+ fun `test - class - with ObjCName annotation`() {
+ val ktFile = inlineSourceCodeAnalysis.createKtFile(
+ """
+ @kotlin.native.ObjCName("FooObjC", "FooSwift", true)
+ class Foo
+ """.trimIndent()
+ )
+ analyze(ktFile) {
+ val fooSymbol = ktFile.getFileSymbol().getFileScope().getClassifierSymbols(Name.identifier("Foo")).single() as KtClassLikeSymbol
+ val resolvedObjCAnnotation = fooSymbol.resolveObjCNameAnnotation()
+ assertEquals("FooObjC", resolvedObjCAnnotation.objCName)
+ assertEquals("FooSwift", resolvedObjCAnnotation.swiftName)
+ assertTrue(resolvedObjCAnnotation.isExact)
+ }
+ }
+
+ @Test
+ fun `test - function - with ObjCName annotation`() {
+ val ktFile = inlineSourceCodeAnalysis.createKtFile(
+ """
+ @kotlin.native.ObjCName("fooObjC", "fooSwift", true)
+ fun foo() = Unit
+ """.trimIndent()
+ )
+ analyze(ktFile) {
+ val fooSymbol = ktFile.getFileSymbol().getFileScope().getCallableSymbols(Name.identifier("foo")).single() as KtFunctionSymbol
+ val resolvedObjCAnnotation = fooSymbol.resolveObjCNameAnnotation()
+ assertEquals("fooObjC", resolvedObjCAnnotation.objCName)
+ assertEquals("fooSwift", resolvedObjCAnnotation.swiftName)
+ assertTrue(resolvedObjCAnnotation.isExact)
+ }
+ }
+}
\ No newline at end of file
diff --git a/native/objcexport-header-generator/impl/analysis-api/testResources/META-INF/services/org.junit.jupiter.api.extension.Extension b/native/objcexport-header-generator/impl/analysis-api/testResources/META-INF/services/org.junit.jupiter.api.extension.Extension
new file mode 100644
index 00000000000..73f43b00e3b
--- /dev/null
+++ b/native/objcexport-header-generator/impl/analysis-api/testResources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -0,0 +1,6 @@
+#
+# Copyright 2010-2023 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.
+#
+org.jetbrains.kotlin.objcexport.testUtils.AnalysisApiHeaderGeneratorExtension
+org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysisExtension
\ No newline at end of file
diff --git a/native/objcexport-header-generator/impl/k1/build.gradle.kts b/native/objcexport-header-generator/impl/k1/build.gradle.kts
new file mode 100644
index 00000000000..423a01c3823
--- /dev/null
+++ b/native/objcexport-header-generator/impl/k1/build.gradle.kts
@@ -0,0 +1,31 @@
+plugins {
+ kotlin("jvm")
+}
+
+sourceSets {
+ "main" { projectDefault() }
+ "test" { projectDefault() }
+}
+
+dependencies {
+ api(project(":native:objcexport-header-generator"))
+ implementation(project(":compiler:cli-base"))
+ implementation(project(":compiler:ir.objcinterop"))
+ implementation(project(":compiler:ir.serialization.native"))
+ implementation(project(":core:descriptors"))
+
+ testImplementation(projectTests(":native:objcexport-header-generator"))
+}
+
+kotlin {
+ compilerOptions {
+ optIn.add("org.jetbrains.kotlin.backend.konan.InternalKotlinNativeApi")
+ }
+}
+
+testsJar()
+
+nativeTest("test", tag = null) {
+ useJUnitPlatform()
+ enableJunit5ExtensionsAutodetection()
+}
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/CustomTypeMapper.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/CustomTypeMapper.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/CustomTypeMapper.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/CustomTypeMapper.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/MainPackageGuesser.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/MainPackageGuesser.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/MainPackageGuesser.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/MainPackageGuesser.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/MethodBridge.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/MethodBridge.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/MethodBridge.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/MethodBridge.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazyUtils.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazyUtils.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazyUtils.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazyUtils.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt
similarity index 99%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt
index 71f1a571484..0c5c06f5f25 100644
--- a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt
+++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt
@@ -46,8 +46,16 @@ internal interface ObjCExportNameTranslator {
}
interface ObjCExportNamer {
- data class ClassOrProtocolName(val swiftName: String, val objCName: String, val binaryName: String = objCName)
- data class PropertyName(val swiftName: String, val objCName: String)
+ data class ClassOrProtocolName(
+ override val swiftName: String,
+ override val objCName: String,
+ override val binaryName: String = objCName,
+ ) : ObjCExportClassOrProtocolName
+
+ data class PropertyName(
+ override val swiftName: String,
+ override val objCName: String,
+ ) : ObjCExportPropertyName
interface Configuration {
val topLevelNamePrefix: String
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportScope.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportScope.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportScope.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportScope.kt
diff --git a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportStubFactories.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportStubFactories.kt
new file mode 100644
index 00000000000..14260a34595
--- /dev/null
+++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportStubFactories.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2010-2023 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.backend.konan.objcexport
+
+import org.jetbrains.kotlin.backend.common.serialization.extractSerializedKdocString
+import org.jetbrains.kotlin.backend.common.serialization.metadata.findKDocString
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.resolve.source.PsiSourceElement
+
+fun ObjCExportStubOrigin(descriptor: DeclarationDescriptor?): ObjCExportStubOrigin? {
+ if (descriptor == null) return null
+
+ if (descriptor is DeclarationDescriptorWithSource) {
+ return ObjCExportStubOrigin.Source(descriptor.name, descriptor.findKDocString(), (descriptor.source as? PsiSourceElement)?.psi)
+ }
+
+ assert(descriptor is DeserializedDescriptor) { "Expected '$descriptor' to implement ${DeserializedDescriptor::class.simpleName}" }
+ return ObjCExportStubOrigin.Binary(descriptor.name, descriptor.extractSerializedKdocString())
+}
+
+fun ObjCProtocolImpl(
+ name: String,
+ descriptor: ClassDescriptor,
+ superProtocols: List,
+ members: List,
+ attributes: List = emptyList(),
+ comment: ObjCComment? = null,
+) = ObjCProtocolImpl(
+ name = name,
+ comment = comment,
+ origin = ObjCExportStubOrigin(descriptor),
+ attributes = attributes,
+ superProtocols = superProtocols,
+ members = members
+)
+
+fun ObjCInterfaceImpl(
+ name: String,
+ generics: List = emptyList(),
+ descriptor: ClassDescriptor? = null,
+ superClass: String? = null,
+ superClassGenerics: List = emptyList(),
+ superProtocols: List = emptyList(),
+ categoryName: String? = null,
+ members: List = emptyList(),
+ attributes: List = emptyList(),
+ comment: ObjCComment? = null,
+) = ObjCInterfaceImpl(
+ name = name,
+ comment = comment,
+ origin = ObjCExportStubOrigin(descriptor),
+ attributes = attributes,
+ superProtocols = superProtocols,
+ members = members,
+ categoryName = categoryName,
+ generics = generics,
+ superClass = superClass,
+ superClassGenerics = superClassGenerics
+)
+
+fun ObjCMethod(
+ descriptor: DeclarationDescriptor?,
+ isInstanceMethod: Boolean,
+ returnType: ObjCType,
+ selectors: List,
+ parameters: List,
+ attributes: List,
+ comment: ObjCComment? = null,
+) = ObjCMethod(
+ comment = comment,
+ origin = ObjCExportStubOrigin(descriptor),
+ isInstanceMethod = isInstanceMethod,
+ returnType = returnType,
+ selectors = selectors,
+ parameters = parameters,
+ attributes = attributes
+)
+
+fun ObjCParameter(
+ name: String,
+ descriptor: ParameterDescriptor?,
+ type: ObjCType,
+) = ObjCParameter(
+ name = name,
+ origin = ObjCExportStubOrigin(descriptor),
+ type = type,
+ todo = null
+)
+
+fun ObjCProperty(
+ name: String,
+ descriptor: DeclarationDescriptorWithSource?,
+ type: ObjCType,
+ propertyAttributes: List,
+ setterName: String? = null,
+ getterName: String? = null,
+ declarationAttributes: List = emptyList(),
+ comment: ObjCComment? = null,
+) = ObjCProperty(
+ name = name,
+ comment = comment,
+ origin = ObjCExportStubOrigin(descriptor),
+ type = type,
+ propertyAttributes = propertyAttributes,
+ setterName = setterName,
+ getterName = getterName,
+ declarationAttributes = declarationAttributes
+)
\ No newline at end of file
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportTranslatorMobile.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportTranslatorMobile.kt
similarity index 95%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportTranslatorMobile.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportTranslatorMobile.kt
index ee03b6b685b..215aa1ebe85 100644
--- a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportTranslatorMobile.kt
+++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportTranslatorMobile.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Copyright 2010-2023 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.
*/
diff --git a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportTypeFactories.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportTypeFactories.kt
new file mode 100644
index 00000000000..e0ccfc7668b
--- /dev/null
+++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportTypeFactories.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010-2023 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.backend.konan.objcexport
+
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+
+fun ObjCGenericTypeParameterUsage(
+ typeParameterDescriptor: TypeParameterDescriptor,
+ namer: ObjCExportNamer,
+) = ObjCGenericTypeParameterUsage(
+ typeName = namer.getTypeParameterName(typeParameterDescriptor)
+)
+
+fun ObjCGenericTypeParameterDeclaration(
+ typeParameterDescriptor: TypeParameterDescriptor,
+ namer: ObjCExportNamer,
+) = ObjCGenericTypeParameterDeclaration(
+ typeName = namer.getTypeParameterName(typeParameterDescriptor),
+ variance = ObjCVariance.fromKotlinVariance(typeParameterDescriptor.variance)
+)
\ No newline at end of file
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedInterface.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedInterface.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedInterface.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedInterface.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCHeaderWriter.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCHeaderWriter.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCHeaderWriter.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCHeaderWriter.kt
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt
similarity index 90%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt
index 06cdbf87a1c..e03e6d764a6 100644
--- a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt
+++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt
@@ -1,3 +1,8 @@
+/*
+ * Copyright 2010-2023 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.backend.konan.objcexport
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/StubBuilder.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/StubBuilder.kt
similarity index 72%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/StubBuilder.kt
rename to native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/StubBuilder.kt
index 6df4853e3d5..98e366d368b 100644
--- a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/StubBuilder.kt
+++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/StubBuilder.kt
@@ -1,6 +1,6 @@
/*
- * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
- * that can be found in the LICENSE file.
+ * Copyright 2010-2023 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.backend.konan.objcexport
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/Fe10ObjCExportHeaderGenerator.kt b/native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/Fe10ObjCExportHeaderGenerator.kt
similarity index 59%
rename from native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/Fe10ObjCExportHeaderGenerator.kt
rename to native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/Fe10ObjCExportHeaderGenerator.kt
index d11487224cd..af92aa26ab7 100644
--- a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/Fe10ObjCExportHeaderGenerator.kt
+++ b/native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/Fe10ObjCExportHeaderGenerator.kt
@@ -6,15 +6,46 @@
package org.jetbrains.kotlin.backend.konan.testUtils
import com.intellij.openapi.Disposable
+import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.backend.konan.UnitSuspendFunctionObjCExport
import org.jetbrains.kotlin.backend.konan.objcexport.*
+import org.jetbrains.kotlin.backend.konan.tests.ObjCExportHeaderGeneratorTest
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.junit.jupiter.api.extension.AfterEachCallback
+import org.junit.jupiter.api.extension.ExtensionContext
+import org.junit.jupiter.api.extension.ParameterContext
+import org.junit.jupiter.api.extension.ParameterResolver
import java.io.File
-object Fe10ObjCExportHeaderGenerator : AbstractObjCExportHeaderGeneratorTest.ObjCExportHeaderGenerator {
- override fun generateHeaders(disposable: Disposable, root: File): String {
+
+class Fe10HeaderGeneratorExtension : ParameterResolver, AfterEachCallback {
+
+ companion object {
+ val namespace = ExtensionContext.Namespace.create(Fe10HeaderGeneratorExtension::class)
+ val disposableKey = "disposable"
+ }
+
+ override fun supportsParameter(parameterContext: ParameterContext, extensionContext: ExtensionContext): Boolean {
+ return parameterContext.parameter.type == ObjCExportHeaderGeneratorTest.HeaderGenerator::class.java
+ }
+
+ override fun resolveParameter(parameterContext: ParameterContext, extensionContext: ExtensionContext): Any {
+ val disposable = Disposer.newDisposable()
+ extensionContext.getStore(namespace).put(disposableKey, disposable)
+ return Fe10HeaderGeneratorImpl(disposable)
+ }
+
+ override fun afterEach(context: ExtensionContext) {
+ val disposable = context.getStore(namespace).get(disposableKey, Disposable::class.java) ?: return
+ Disposer.dispose(disposable)
+ }
+}
+
+private class Fe10HeaderGeneratorImpl(private val disposable: Disposable) :
+ ObjCExportHeaderGeneratorTest.HeaderGenerator {
+ override fun generateHeaders(root: File): String {
val headerGenerator = createObjCExportHeaderGenerator(disposable, root)
headerGenerator.translateModuleDeclarations()
return headerGenerator.build().joinToString(System.lineSeparator())
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/Fe10Utils.kt b/native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/Fe10Utils.kt
similarity index 99%
rename from native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/Fe10Utils.kt
rename to native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/Fe10Utils.kt
index 8dcf179c1b7..afa591cfc19 100644
--- a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/Fe10Utils.kt
+++ b/native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/Fe10Utils.kt
@@ -105,7 +105,7 @@ private object DependenciesContainerImpl : CommonDependenciesContainer {
private val klibFactory = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer)
private val stdlibModuleDescriptor = klibFactory.DefaultDeserializedDescriptorFactory.createDescriptor(
- library = resolveSingleFileKlib(org.jetbrains.kotlin.konan.file.File("$konanHomePath/klib/common/stdlib")),
+ library = resolveSingleFileKlib(org.jetbrains.kotlin.konan.file.File(kotlinNativeStdlibPath)),
languageVersionSettings = createLanguageVersionSettings(),
builtIns = DefaultBuiltIns.Instance,
storageManager = LockBasedStorageManager.NO_LOCKS,
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/InlineSourceTestEnvironment.kt b/native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/InlineSourceTestEnvironment.kt
similarity index 99%
rename from native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/InlineSourceTestEnvironment.kt
rename to native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/InlineSourceTestEnvironment.kt
index d59a1f4f91b..0f6b5e7be55 100644
--- a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/InlineSourceTestEnvironment.kt
+++ b/native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/InlineSourceTestEnvironment.kt
@@ -52,7 +52,6 @@ interface InlineSourceTestEnvironment {
val testTempDir: File
}
-
interface InlineSourceCodeCollector {
fun source(@Language("kotlin") sourceCode: String)
}
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/ObjCExportUtils.kt b/native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/ObjCExportUtils.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/ObjCExportUtils.kt
rename to native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/testUtils/ObjCExportUtils.kt
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/tests/ObjCExportMapperTest.kt b/native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportMapperTest.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/tests/ObjCExportMapperTest.kt
rename to native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportMapperTest.kt
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/tests/ObjCExportNamerTest.kt b/native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportNamerTest.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/tests/ObjCExportNamerTest.kt
rename to native/objcexport-header-generator/impl/k1/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportNamerTest.kt
diff --git a/native/objcexport-header-generator/impl/k1/testResources/META-INF/services/org.junit.jupiter.api.extension.Extension b/native/objcexport-header-generator/impl/k1/testResources/META-INF/services/org.junit.jupiter.api.extension.Extension
new file mode 100644
index 00000000000..4dadc1c1568
--- /dev/null
+++ b/native/objcexport-header-generator/impl/k1/testResources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -0,0 +1,5 @@
+#
+# Copyright 2010-2023 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.
+#
+org.jetbrains.kotlin.backend.konan.testUtils.Fe10HeaderGeneratorExtension
\ No newline at end of file
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ModuleMapBuilder.kt b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ModuleMapBuilder.kt
similarity index 100%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ModuleMapBuilder.kt
rename to native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ModuleMapBuilder.kt
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
new file mode 100644
index 00000000000..ef447602ab3
--- /dev/null
+++ b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportName.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2023 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.backend.konan.objcexport
+
+sealed interface ObjCExportName {
+ val swiftName: String
+ val objCName: String
+}
+
+interface ObjCExportClassOrProtocolName : ObjCExportName {
+ val binaryName: String
+}
+
+interface ObjCExportPropertyName : ObjCExportName
+
+fun ObjCExportClassOrProtocolName(
+ swiftName: String,
+ objCName: String,
+ binaryName: String = objCName,
+): ObjCExportClassOrProtocolName = ObjCExportClassOrProtocolNameImpl(
+ swiftName = swiftName,
+ objCName = objCName,
+ binaryName = binaryName
+)
+
+private data class ObjCExportClassOrProtocolNameImpl(
+ override val swiftName: String,
+ override val objCName: String,
+ override val binaryName: String,
+) : ObjCExportClassOrProtocolName
+
+fun ObjCExportPropertyName(
+ swiftName: String,
+ objCName: String,
+): ObjCExportPropertyName = ObjCExportPropertyNameImpl(
+ swiftName = swiftName,
+ objCName = objCName
+)
+
+private data class ObjCExportPropertyNameImpl(
+ override val swiftName: String,
+ override val objCName: String,
+) : ObjCExportPropertyName
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportStubOrigin.kt b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportStubOrigin.kt
similarity index 53%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportStubOrigin.kt
rename to native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportStubOrigin.kt
index 54633cb7f2a..bf18182a4fb 100644
--- a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportStubOrigin.kt
+++ b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportStubOrigin.kt
@@ -6,24 +6,8 @@
package org.jetbrains.kotlin.backend.konan.objcexport
import com.intellij.psi.PsiElement
-import org.jetbrains.kotlin.backend.common.serialization.extractSerializedKdocString
-import org.jetbrains.kotlin.backend.common.serialization.metadata.findKDocString
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
-import org.jetbrains.kotlin.descriptors.DeserializedDescriptor
+
import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.resolve.source.PsiSourceElement
-
-fun ObjCExportStubOrigin(descriptor: DeclarationDescriptor?): ObjCExportStubOrigin? {
- if (descriptor == null) return null
-
- if (descriptor is DeclarationDescriptorWithSource) {
- return ObjCExportStubOrigin.Source(descriptor.name, descriptor.findKDocString(), (descriptor.source as? PsiSourceElement)?.psi)
- }
-
- assert(descriptor is DeserializedDescriptor) { "Expected '$descriptor' to implement ${DeserializedDescriptor::class.simpleName}" }
- return ObjCExportStubOrigin.Binary(descriptor.name, descriptor.extractSerializedKdocString())
-}
sealed class ObjCExportStubOrigin {
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedStubs.kt b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedStubs.kt
similarity index 55%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedStubs.kt
rename to native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedStubs.kt
index 57077ab6b2d..7b630bca322 100644
--- a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedStubs.kt
+++ b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportedStubs.kt
@@ -1,6 +1,6 @@
/*
- * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
- * that can be found in the LICENSE file.
+ * Copyright 2010-2023 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.backend.konan.objcexport
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/StubRenderer.kt b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/StubRenderer.kt
similarity index 95%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/StubRenderer.kt
rename to native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/StubRenderer.kt
index 36f555fe053..7142753fa61 100644
--- a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/StubRenderer.kt
+++ b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/StubRenderer.kt
@@ -1,10 +1,12 @@
/*
- * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
- * that can be found in the LICENSE file.
+ * Copyright 2010-2023 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.backend.konan.objcexport
+import org.jetbrains.kotlin.backend.konan.InternalKotlinNativeApi
+
object StubRenderer {
fun render(stub: ObjCExportStub): List = render(stub, false)
@@ -21,7 +23,8 @@ object StubRenderer {
return kDoc.size
}
- internal fun render(stub: ObjCExportStub, shouldExportKDoc: Boolean): List = collect {
+ @InternalKotlinNativeApi
+ fun render(stub: ObjCExportStub, shouldExportKDoc: Boolean): List = collect {
stub.run {
val (kDocEnding, commentBlockEnding) = if (comment?.contentLines == null) {
Pair("*/", null) // Close kDoc with `*/`, and print nothing after empty comment
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt
similarity index 90%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt
rename to native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt
index cc6cf1b008b..e4f9e3b0e7b 100644
--- a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt
+++ b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt
@@ -1,12 +1,11 @@
/*
- * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
- * that can be found in the LICENSE file.
+ * Copyright 2010-2023 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.backend.konan.objcexport
import org.jetbrains.kotlin.backend.konan.InternalKotlinNativeApi
-import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.types.Variance
sealed class ObjCType {
@@ -67,12 +66,8 @@ sealed class ObjCGenericTypeUsage : ObjCNonNullReferenceType() {
data class ObjCGenericTypeRawUsage(override val typeName: String) : ObjCGenericTypeUsage()
data class ObjCGenericTypeParameterUsage(
- val typeParameterDescriptor: TypeParameterDescriptor,
- val namer: ObjCExportNamer,
-) : ObjCGenericTypeUsage() {
override val typeName: String
- get() = namer.getTypeParameterName(typeParameterDescriptor)
-}
+) : ObjCGenericTypeUsage()
data class ObjCProtocolType(
val protocolName: String,
@@ -203,14 +198,9 @@ data class ObjCGenericTypeRawDeclaration(
) : ObjCGenericTypeDeclaration()
data class ObjCGenericTypeParameterDeclaration(
- val typeParameterDescriptor: TypeParameterDescriptor,
- val namer: ObjCExportNamer,
-) : ObjCGenericTypeDeclaration() {
- override val typeName: String
- get() = namer.getTypeParameterName(typeParameterDescriptor)
+ override val typeName: String,
override val variance: ObjCVariance
- get() = ObjCVariance.fromKotlinVariance(typeParameterDescriptor.variance)
-}
+) : ObjCGenericTypeDeclaration()
@InternalKotlinNativeApi
fun ObjCType.makeNullableIfReferenceOrPointer(): ObjCType = when (this) {
diff --git a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt
similarity index 55%
rename from native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt
rename to native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt
index b0fa73b692d..9b8029d76d2 100644
--- a/native/objcexport-header-generator/src/main/kotlin/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt
+++ b/native/objcexport-header-generator/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt
@@ -1,17 +1,12 @@
/*
- * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
- * that can be found in the LICENSE file.
+ * Copyright 2010-2023 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.
*/
@file:JvmName("ObjCExportStubKt")
package org.jetbrains.kotlin.backend.konan.objcexport
-import org.jetbrains.kotlin.descriptors.ClassDescriptor
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
-import org.jetbrains.kotlin.descriptors.ParameterDescriptor
-
@Deprecated("Use 'ObjCExportStub' instead", replaceWith = ReplaceWith("ObjCExportStub"))
@Suppress("unused")
typealias Stub<@Suppress("UNUSED_TYPEALIAS_PARAMETER") T> = ObjCExportStub
@@ -77,23 +72,7 @@ class ObjCProtocolImpl(
override val attributes: List,
override val superProtocols: List,
override val members: List,
-) : ObjCProtocol() {
- constructor(
- name: String,
- descriptor: ClassDescriptor,
- superProtocols: List,
- members: List,
- attributes: List = emptyList(),
- comment: ObjCComment? = null,
- ) : this(
- name = name,
- comment = comment,
- origin = ObjCExportStubOrigin(descriptor),
- attributes = attributes,
- superProtocols = superProtocols,
- members = members
- )
-}
+) : ObjCProtocol()
class ObjCInterfaceImpl(
override val name: String,
@@ -106,31 +85,7 @@ class ObjCInterfaceImpl(
override val generics: List,
override val superClass: String?,
override val superClassGenerics: List,
-) : ObjCInterface() {
- constructor(
- name: String,
- generics: List = emptyList(),
- descriptor: ClassDescriptor? = null,
- superClass: String? = null,
- superClassGenerics: List = emptyList(),
- superProtocols: List = emptyList(),
- categoryName: String? = null,
- members: List = emptyList(),
- attributes: List = emptyList(),
- comment: ObjCComment? = null,
- ) : this(
- name = name,
- comment = comment,
- origin = ObjCExportStubOrigin(descriptor),
- attributes = attributes,
- superProtocols = superProtocols,
- members = members,
- categoryName = categoryName,
- generics = generics,
- superClass = superClass,
- superClassGenerics = superClassGenerics
- )
-}
+) : ObjCInterface()
class ObjCMethod(
override val comment: ObjCComment?,
@@ -141,43 +96,15 @@ class ObjCMethod(
val parameters: List,
val attributes: List,
) : ObjCExportStub {
- constructor(
- descriptor: DeclarationDescriptor?,
- isInstanceMethod: Boolean,
- returnType: ObjCType,
- selectors: List,
- parameters: List,
- attributes: List,
- comment: ObjCComment? = null,
- ) : this(
- comment = comment,
- origin = ObjCExportStubOrigin(descriptor),
- isInstanceMethod = isInstanceMethod,
- returnType = returnType,
- selectors = selectors,
- parameters = parameters,
- attributes = attributes
- )
-
override val name: String = buildMethodName(selectors, parameters)
}
-class ObjCParameter private constructor(
+class ObjCParameter(
override val name: String,
override val origin: ObjCExportStubOrigin?,
val type: ObjCType,
+ val todo: Nothing?
) : ObjCExportStub {
-
- constructor(
- name: String,
- descriptor: ParameterDescriptor?,
- type: ObjCType,
- ) : this(
- name = name,
- origin = ObjCExportStubOrigin(descriptor),
- type = type
- )
-
override val comment: Nothing? = null
}
@@ -190,27 +117,7 @@ class ObjCProperty(
val setterName: String? = null,
val getterName: String? = null,
val declarationAttributes: List = emptyList(),
-) : ObjCExportStub {
- constructor(
- name: String,
- descriptor: DeclarationDescriptorWithSource?,
- type: ObjCType,
- propertyAttributes: List,
- setterName: String? = null,
- getterName: String? = null,
- declarationAttributes: List = emptyList(),
- comment: ObjCComment? = null,
- ) : this(
- name = name,
- comment = comment,
- origin = ObjCExportStubOrigin(descriptor),
- type = type,
- propertyAttributes = propertyAttributes,
- setterName = setterName,
- getterName = getterName,
- declarationAttributes = declarationAttributes
- )
-}
+) : ObjCExportStub
private fun buildMethodName(selectors: List, parameters: List): String =
if (selectors.size == 1 && parameters.size == 0) {
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/AbstractObjCExportHeaderGeneratorTest.kt b/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/AbstractObjCExportHeaderGeneratorTest.kt
deleted file mode 100644
index b1d84fa1431..00000000000
--- a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/AbstractObjCExportHeaderGeneratorTest.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2010-2023 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.backend.konan.testUtils
-
-import com.intellij.openapi.Disposable
-import com.intellij.openapi.util.Disposer
-import org.jetbrains.kotlin.test.KotlinTestUtils
-import org.junit.After
-import java.io.File
-import kotlin.test.fail
-
-abstract class AbstractObjCExportHeaderGeneratorTest(
- private val generator: ObjCExportHeaderGenerator,
-) {
-
- fun interface ObjCExportHeaderGenerator {
- fun generateHeaders(disposable: Disposable, root: File): String
- }
-
- private val testRootDisposable = Disposer.newDisposable("${AbstractObjCExportHeaderGeneratorTest::class.simpleName}.testRootDisposable")
- protected val objCExportTestDataDir = testDataDir.resolve("objcexport")
-
- @After
- fun dispose() {
- Disposer.dispose(testRootDisposable)
- }
-
-
- protected fun doTest(root: File) {
- if (!root.isDirectory) fail("Expected ${root.absolutePath} to be directory")
- val generatedHeaders = generator.generateHeaders(testRootDisposable, root)
- KotlinTestUtils.assertEqualsToFile(root.resolve("!${root.nameWithoutExtension}.h"), generatedHeaders)
- }
-}
-
-abstract class AbstractFE10ObjCExportHeaderGeneratorTest : AbstractObjCExportHeaderGeneratorTest(Fe10ObjCExportHeaderGenerator)
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/tests/Fe10ObjCExportHeaderGeneratorTest.kt b/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/tests/Fe10ObjCExportHeaderGeneratorTest.kt
deleted file mode 100644
index 57ce360a18d..00000000000
--- a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/tests/Fe10ObjCExportHeaderGeneratorTest.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2010-2023 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.backend.konan.tests
-
-import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator
-import org.jetbrains.kotlin.backend.konan.testUtils.AbstractFE10ObjCExportHeaderGeneratorTest
-import org.junit.jupiter.api.Test
-
-/**
- * ## Test Scope
- * This test will cover the generation of 'objc' headers.
- * The corresponding class in would be [ObjCExportHeaderGenerator].
- *
- * The input of the test are Kotlin source files;
- * The output is the generated header files;
- * The output will be compared to already checked in golden files.
- *
- * ## How to create a new test
- * Every test has a corresponding 'root' directory.
- * All directories are found in `backend.native/functionalTest/testData/objcexport`.
- *
- * 1) Create new root directory (e.g. myTest) in testData/objcexport
- * 2) Place kotlin files into the directory e.g. testData/objcexport/myTest/Foo.kt
- * 3) Create a test function and call ` doTest(objCExportTestDataDir.resolve("myTest"))`
- * 4) The first invocation will fail the test, but generates the header that can be checked in (if sufficient)
- */
-class Fe10ObjCExportHeaderGeneratorTest : AbstractFE10ObjCExportHeaderGeneratorTest() {
- @Test
- fun `test - simpleClass`() {
- doTest(objCExportTestDataDir.resolve("simpleClass"))
- }
-
- @Test
- fun `test - simpleInterface`() {
- doTest(objCExportTestDataDir.resolve("simpleInterface"))
- }
-
- @Test
- fun `test - simpleEnumClass`() {
- doTest(objCExportTestDataDir.resolve("simpleEnumClass"))
- }
-
- @Test
- fun `test - simpleObject`() {
- doTest(objCExportTestDataDir.resolve("simpleObject"))
- }
-
- @Test
- fun `test - topLevelFunction`() {
- doTest(objCExportTestDataDir.resolve("topLevelFunction"))
- }
-
- @Test
- fun `test - topLevelProperty`() {
- doTest(objCExportTestDataDir.resolve("topLevelProperty"))
- }
-
- @Test
- fun `test - sameClassNameInDifferentPackage`() {
- doTest(objCExportTestDataDir.resolve("sameClassNameInDifferentPackage"))
- }
-
- @Test
- fun `test - samePropertyAndFunctionName`() {
- doTest(objCExportTestDataDir.resolve("samePropertyAndFunctionName"))
- }
-
- @Test
- fun `test - classImplementingInterface`() {
- doTest(objCExportTestDataDir.resolve("classImplementingInterface"))
- }
-
- @Test
- fun `test - interfaceImplementingInterface`() {
- doTest(objCExportTestDataDir.resolve("interfaceImplementingInterface"))
- }
-
- @Test
- fun `test - classWithObjCNameAnnotation`() {
- doTest(objCExportTestDataDir.resolve("classWithObjCNameAnnotation"))
- }
-
- @Test
- fun `test - functionWithObjCNameAnnotation`() {
- doTest(objCExportTestDataDir.resolve("functionWithObjCNameAnnotation"))
- }
-
- @Test
- fun `test - classWithKDoc`() {
- doTest(objCExportTestDataDir.resolve("classWithKDoc"))
- }
-
- @Test
- fun `test - classWithHidesFromObjCAnnotation`() {
- doTest(objCExportTestDataDir.resolve("classWithHidesFromObjCAnnotation"))
- }
-
- @Test
- fun `test - functionWithThrowsAnnotation`() {
- doTest(objCExportTestDataDir.resolve("functionWithThrowsAnnotation"))
- }
-
- @Test
- fun `test - functionWithErrorType`() {
- doTest(objCExportTestDataDir.resolve("functionWithErrorType"))
- }
-}
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/konanHome.kt b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/testUtils/konanHome.kt
similarity index 76%
rename from native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/konanHome.kt
rename to native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/testUtils/konanHome.kt
index c7ebfd4a4ea..3fe5af982e4 100644
--- a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/konanHome.kt
+++ b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/testUtils/konanHome.kt
@@ -8,4 +8,7 @@ package org.jetbrains.kotlin.backend.konan.testUtils
private const val konanHomePropertyKey = "kotlin.internal.native.test.nativeHome"
val konanHomePath: String
- get() = System.getProperty(konanHomePropertyKey) ?: error("Missing System property: '$konanHomePropertyKey'")
\ No newline at end of file
+ get() = System.getProperty(konanHomePropertyKey) ?: error("Missing System property: '$konanHomePropertyKey'")
+
+val kotlinNativeStdlibPath: String
+ get() = "$konanHomePath/klib/common/stdlib"
\ No newline at end of file
diff --git a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/testDataDir.kt b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/testUtils/testDataDir.kt
similarity index 69%
rename from native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/testDataDir.kt
rename to native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/testUtils/testDataDir.kt
index 8a7e32c9f5a..30dd5078bfd 100644
--- a/native/objcexport-header-generator/src/test/kotlin/org/jetbrains/kotlin/backend/konan/testUtils/testDataDir.kt
+++ b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/testUtils/testDataDir.kt
@@ -7,5 +7,5 @@ package org.jetbrains.kotlin.backend.konan.testUtils
import java.io.File
-val projectDir = File(System.getProperty("projectDir"))
-val testDataDir = projectDir.resolve("src/test/testData")
\ No newline at end of file
+val testDataDir = File("native/objcexport-header-generator/testData")
+val headersTestDataDir = testDataDir.resolve("headers")
\ No newline at end of file
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
new file mode 100644
index 00000000000..df2ce6ba2b7
--- /dev/null
+++ b/native/objcexport-header-generator/test/org/jetbrains/kotlin/backend/konan/tests/ObjCExportHeaderGeneratorTest.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010-2023 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.backend.konan.tests
+
+import org.jetbrains.kotlin.backend.konan.testUtils.headersTestDataDir
+import org.jetbrains.kotlin.test.KotlinTestUtils
+import org.junit.jupiter.api.Test
+import java.io.File
+import kotlin.test.fail
+
+/**
+ * ## Test Scope
+ * This test will cover the generation of 'ObjC' headers.
+ *
+ * The input of the test are Kotlin source files;
+ * The output is the generated header files;
+ * The output will be compared to already checked in golden files.
+ *
+ * ## How to create a new test
+ * Every test has a corresponding 'root' directory.
+ * All directories are found in `native/objcexport-header-generator/testData/headers`.
+ *
+ * 1) Create new root directory (e.g. myTest) in testData/headers
+ * 2) Place kotlin files into the directory e.g. testData/headers/myTest/Foo.kt
+ * 3) Create a test function and call ` doTest(headersTestDataDir.resolve("myTest"))`
+ * 4) The first invocation will fail the test, but generates the header that can be checked in (if sufficient)
+ */
+class ObjCExportHeaderGeneratorTest(val generator: HeaderGenerator) {
+
+ @Test
+ fun `test - simpleClass`() {
+ doTest(headersTestDataDir.resolve("simpleClass"))
+ }
+
+ @Test
+ fun `test - simpleInterface`() {
+ doTest(headersTestDataDir.resolve("simpleInterface"))
+ }
+
+ @Test
+ fun `test - simpleEnumClass`() {
+ doTest(headersTestDataDir.resolve("simpleEnumClass"))
+ }
+
+ @Test
+ fun `test - simpleObject`() {
+ doTest(headersTestDataDir.resolve("simpleObject"))
+ }
+
+ @Test
+ fun `test - topLevelFunction`() {
+ doTest(headersTestDataDir.resolve("topLevelFunction"))
+ }
+
+ @Test
+ fun `test - topLevelProperty`() {
+ doTest(headersTestDataDir.resolve("topLevelProperty"))
+ }
+
+ @Test
+ fun `test - sameClassNameInDifferentPackage`() {
+ doTest(headersTestDataDir.resolve("sameClassNameInDifferentPackage"))
+ }
+
+ @Test
+ fun `test - samePropertyAndFunctionName`() {
+ doTest(headersTestDataDir.resolve("samePropertyAndFunctionName"))
+ }
+
+ @Test
+ fun `test - classImplementingInterface`() {
+ doTest(headersTestDataDir.resolve("classImplementingInterface"))
+ }
+
+ @Test
+ fun `test - interfaceImplementingInterface`() {
+ doTest(headersTestDataDir.resolve("interfaceImplementingInterface"))
+ }
+
+ @Test
+ fun `test - classWithObjCNameAnnotation`() {
+ doTest(headersTestDataDir.resolve("classWithObjCNameAnnotation"))
+ }
+
+ @Test
+ fun `test - functionWithObjCNameAnnotation`() {
+ doTest(headersTestDataDir.resolve("functionWithObjCNameAnnotation"))
+ }
+
+ @Test
+ fun `test - classWithKDoc`() {
+ doTest(headersTestDataDir.resolve("classWithKDoc"))
+ }
+
+ @Test
+ fun `test - classWithHidesFromObjCAnnotation`() {
+ doTest(headersTestDataDir.resolve("classWithHidesFromObjCAnnotation"))
+ }
+
+ @Test
+ fun `test - functionWithThrowsAnnotation`() {
+ doTest(headersTestDataDir.resolve("functionWithThrowsAnnotation"))
+ }
+
+ @Test
+ fun `test - functionWithErrorType`() {
+ doTest(headersTestDataDir.resolve("functionWithErrorType"))
+ }
+
+ fun interface HeaderGenerator {
+ fun generateHeaders(root: File): String
+ }
+
+ private fun doTest(root: File) {
+ if (!root.isDirectory) fail("Expected ${root.absolutePath} to be directory")
+ val generatedHeaders = generator.generateHeaders(root)
+ KotlinTestUtils.assertEqualsToFile(root.resolve("!${root.nameWithoutExtension}.h"), generatedHeaders)
+ }
+}
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/classImplementingInterface/!classImplementingInterface.h b/native/objcexport-header-generator/testData/headers/classImplementingInterface/!classImplementingInterface.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/classImplementingInterface/!classImplementingInterface.h
rename to native/objcexport-header-generator/testData/headers/classImplementingInterface/!classImplementingInterface.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/classImplementingInterface/Foo.kt b/native/objcexport-header-generator/testData/headers/classImplementingInterface/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/classImplementingInterface/Foo.kt
rename to native/objcexport-header-generator/testData/headers/classImplementingInterface/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/classWithHidesFromObjCAnnotation/!classWithHidesFromObjCAnnotation.h b/native/objcexport-header-generator/testData/headers/classWithHidesFromObjCAnnotation/!classWithHidesFromObjCAnnotation.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/classWithHidesFromObjCAnnotation/!classWithHidesFromObjCAnnotation.h
rename to native/objcexport-header-generator/testData/headers/classWithHidesFromObjCAnnotation/!classWithHidesFromObjCAnnotation.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/classWithHidesFromObjCAnnotation/Foo.kt b/native/objcexport-header-generator/testData/headers/classWithHidesFromObjCAnnotation/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/classWithHidesFromObjCAnnotation/Foo.kt
rename to native/objcexport-header-generator/testData/headers/classWithHidesFromObjCAnnotation/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/classWithKDoc/!classWithKDoc.h b/native/objcexport-header-generator/testData/headers/classWithKDoc/!classWithKDoc.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/classWithKDoc/!classWithKDoc.h
rename to native/objcexport-header-generator/testData/headers/classWithKDoc/!classWithKDoc.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/classWithKDoc/Foo.kt b/native/objcexport-header-generator/testData/headers/classWithKDoc/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/classWithKDoc/Foo.kt
rename to native/objcexport-header-generator/testData/headers/classWithKDoc/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/classWithObjCNameAnnotation/!classWithObjCNameAnnotation.h b/native/objcexport-header-generator/testData/headers/classWithObjCNameAnnotation/!classWithObjCNameAnnotation.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/classWithObjCNameAnnotation/!classWithObjCNameAnnotation.h
rename to native/objcexport-header-generator/testData/headers/classWithObjCNameAnnotation/!classWithObjCNameAnnotation.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/classWithObjCNameAnnotation/Foo.kt b/native/objcexport-header-generator/testData/headers/classWithObjCNameAnnotation/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/classWithObjCNameAnnotation/Foo.kt
rename to native/objcexport-header-generator/testData/headers/classWithObjCNameAnnotation/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/functionWithErrorType/!functionWithErrorType.h b/native/objcexport-header-generator/testData/headers/functionWithErrorType/!functionWithErrorType.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/functionWithErrorType/!functionWithErrorType.h
rename to native/objcexport-header-generator/testData/headers/functionWithErrorType/!functionWithErrorType.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/functionWithErrorType/Foo.kt b/native/objcexport-header-generator/testData/headers/functionWithErrorType/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/functionWithErrorType/Foo.kt
rename to native/objcexport-header-generator/testData/headers/functionWithErrorType/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/functionWithObjCNameAnnotation/!functionWithObjCNameAnnotation.h b/native/objcexport-header-generator/testData/headers/functionWithObjCNameAnnotation/!functionWithObjCNameAnnotation.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/functionWithObjCNameAnnotation/!functionWithObjCNameAnnotation.h
rename to native/objcexport-header-generator/testData/headers/functionWithObjCNameAnnotation/!functionWithObjCNameAnnotation.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/functionWithObjCNameAnnotation/Foo.kt b/native/objcexport-header-generator/testData/headers/functionWithObjCNameAnnotation/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/functionWithObjCNameAnnotation/Foo.kt
rename to native/objcexport-header-generator/testData/headers/functionWithObjCNameAnnotation/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/functionWithThrowsAnnotation/!functionWithThrowsAnnotation.h b/native/objcexport-header-generator/testData/headers/functionWithThrowsAnnotation/!functionWithThrowsAnnotation.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/functionWithThrowsAnnotation/!functionWithThrowsAnnotation.h
rename to native/objcexport-header-generator/testData/headers/functionWithThrowsAnnotation/!functionWithThrowsAnnotation.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/functionWithThrowsAnnotation/Foo.kt b/native/objcexport-header-generator/testData/headers/functionWithThrowsAnnotation/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/functionWithThrowsAnnotation/Foo.kt
rename to native/objcexport-header-generator/testData/headers/functionWithThrowsAnnotation/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/interfaceImplementingInterface/!interfaceImplementingInterface.h b/native/objcexport-header-generator/testData/headers/interfaceImplementingInterface/!interfaceImplementingInterface.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/interfaceImplementingInterface/!interfaceImplementingInterface.h
rename to native/objcexport-header-generator/testData/headers/interfaceImplementingInterface/!interfaceImplementingInterface.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/interfaceImplementingInterface/Foo.kt b/native/objcexport-header-generator/testData/headers/interfaceImplementingInterface/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/interfaceImplementingInterface/Foo.kt
rename to native/objcexport-header-generator/testData/headers/interfaceImplementingInterface/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/sameClassNameInDifferentPackage/!sameClassNameInDifferentPackage.h b/native/objcexport-header-generator/testData/headers/sameClassNameInDifferentPackage/!sameClassNameInDifferentPackage.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/sameClassNameInDifferentPackage/!sameClassNameInDifferentPackage.h
rename to native/objcexport-header-generator/testData/headers/sameClassNameInDifferentPackage/!sameClassNameInDifferentPackage.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/sameClassNameInDifferentPackage/a/Foo.kt b/native/objcexport-header-generator/testData/headers/sameClassNameInDifferentPackage/a/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/sameClassNameInDifferentPackage/a/Foo.kt
rename to native/objcexport-header-generator/testData/headers/sameClassNameInDifferentPackage/a/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/sameClassNameInDifferentPackage/b/Foo.kt b/native/objcexport-header-generator/testData/headers/sameClassNameInDifferentPackage/b/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/sameClassNameInDifferentPackage/b/Foo.kt
rename to native/objcexport-header-generator/testData/headers/sameClassNameInDifferentPackage/b/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/samePropertyAndFunctionName/!samePropertyAndFunctionName.h b/native/objcexport-header-generator/testData/headers/samePropertyAndFunctionName/!samePropertyAndFunctionName.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/samePropertyAndFunctionName/!samePropertyAndFunctionName.h
rename to native/objcexport-header-generator/testData/headers/samePropertyAndFunctionName/!samePropertyAndFunctionName.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/samePropertyAndFunctionName/Foo.kt b/native/objcexport-header-generator/testData/headers/samePropertyAndFunctionName/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/samePropertyAndFunctionName/Foo.kt
rename to native/objcexport-header-generator/testData/headers/samePropertyAndFunctionName/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/simpleClass/!simpleClass.h b/native/objcexport-header-generator/testData/headers/simpleClass/!simpleClass.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/simpleClass/!simpleClass.h
rename to native/objcexport-header-generator/testData/headers/simpleClass/!simpleClass.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/simpleClass/Foo.kt b/native/objcexport-header-generator/testData/headers/simpleClass/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/simpleClass/Foo.kt
rename to native/objcexport-header-generator/testData/headers/simpleClass/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/simpleEnumClass/!simpleEnumClass.h b/native/objcexport-header-generator/testData/headers/simpleEnumClass/!simpleEnumClass.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/simpleEnumClass/!simpleEnumClass.h
rename to native/objcexport-header-generator/testData/headers/simpleEnumClass/!simpleEnumClass.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/simpleEnumClass/Foo.kt b/native/objcexport-header-generator/testData/headers/simpleEnumClass/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/simpleEnumClass/Foo.kt
rename to native/objcexport-header-generator/testData/headers/simpleEnumClass/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/simpleInterface/!simpleInterface.h b/native/objcexport-header-generator/testData/headers/simpleInterface/!simpleInterface.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/simpleInterface/!simpleInterface.h
rename to native/objcexport-header-generator/testData/headers/simpleInterface/!simpleInterface.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/simpleInterface/Foo.kt b/native/objcexport-header-generator/testData/headers/simpleInterface/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/simpleInterface/Foo.kt
rename to native/objcexport-header-generator/testData/headers/simpleInterface/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/simpleObject/!simpleObject.h b/native/objcexport-header-generator/testData/headers/simpleObject/!simpleObject.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/simpleObject/!simpleObject.h
rename to native/objcexport-header-generator/testData/headers/simpleObject/!simpleObject.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/simpleObject/Foo.kt b/native/objcexport-header-generator/testData/headers/simpleObject/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/simpleObject/Foo.kt
rename to native/objcexport-header-generator/testData/headers/simpleObject/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/topLevelFunction/!topLevelFunction.h b/native/objcexport-header-generator/testData/headers/topLevelFunction/!topLevelFunction.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/topLevelFunction/!topLevelFunction.h
rename to native/objcexport-header-generator/testData/headers/topLevelFunction/!topLevelFunction.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/topLevelFunction/Foo.kt b/native/objcexport-header-generator/testData/headers/topLevelFunction/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/topLevelFunction/Foo.kt
rename to native/objcexport-header-generator/testData/headers/topLevelFunction/Foo.kt
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/topLevelProperty/!topLevelProperty.h b/native/objcexport-header-generator/testData/headers/topLevelProperty/!topLevelProperty.h
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/topLevelProperty/!topLevelProperty.h
rename to native/objcexport-header-generator/testData/headers/topLevelProperty/!topLevelProperty.h
diff --git a/native/objcexport-header-generator/src/test/testData/objcexport/topLevelProperty/Foo.kt b/native/objcexport-header-generator/testData/headers/topLevelProperty/Foo.kt
similarity index 100%
rename from native/objcexport-header-generator/src/test/testData/objcexport/topLevelProperty/Foo.kt
rename to native/objcexport-header-generator/testData/headers/topLevelProperty/Foo.kt
diff --git a/prepare/ide-plugin-dependencies/kotlin-objcexport-header-generator-for-ide/build.gradle.kts b/prepare/ide-plugin-dependencies/kotlin-objcexport-header-generator-for-ide/build.gradle.kts
index d312f3848bf..b936303520e 100644
--- a/prepare/ide-plugin-dependencies/kotlin-objcexport-header-generator-for-ide/build.gradle.kts
+++ b/prepare/ide-plugin-dependencies/kotlin-objcexport-header-generator-for-ide/build.gradle.kts
@@ -6,6 +6,8 @@ publishJarsForIde(
listOf(
":native:base",
":native:objcexport-header-generator",
+ ":native:objcexport-header-generator-k1",
+ ":native:objcexport-header-generator-analysis-api",
":compiler:ir.serialization.native"
)
)
diff --git a/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt b/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt
index cc2c68990bb..3d69cc086d7 100644
--- a/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt
+++ b/repo/gradle-build-conventions/buildsrc-compat/src/main/kotlin/tasks.kt
@@ -265,6 +265,10 @@ fun Project.projectTest(
}.apply { configure(body) }
}
+fun Test.enableJunit5ExtensionsAutodetection() {
+ systemProperty("junit.jupiter.extensions.autodetection.enabled", "true")
+}
+
val defaultMaxMemoryPerTestWorkerMb = 1600
val reservedMemoryMb = 9000 // system processes, gradle daemon, kotlin daemon, etc ...
diff --git a/settings.gradle b/settings.gradle
index 6d22819051d..e8ddc070d35 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -112,6 +112,8 @@ include ":benchmarks",
":native:executors",
":native:base",
":native:objcexport-header-generator",
+ ":native:objcexport-header-generator-k1",
+ ":native:objcexport-header-generator-analysis-api",
":core:compiler.common",
":core:compiler.common.jvm",
":core:compiler.common.js",
@@ -695,6 +697,8 @@ project(':native:frontend.native').projectDir = "$rootDir/native/frontend" as Fi
project(':native:kotlin-klib-commonizer').projectDir = "$rootDir/native/commonizer" as File
project(":native:kotlin-klib-commonizer-api").projectDir = "$rootDir/native/commonizer-api" as File
project(':native:kotlin-klib-commonizer-embeddable').projectDir = "$rootDir/native/commonizer-embeddable" as File
+project(':native:objcexport-header-generator-k1').projectDir = "$rootDir/native/objcexport-header-generator/impl/k1" as File
+project(':native:objcexport-header-generator-analysis-api').projectDir = "$rootDir/native/objcexport-header-generator/impl/analysis-api" as File
project(':plugins:android-extensions-compiler').projectDir = "$rootDir/plugins/android-extensions/android-extensions-compiler" as File
project(':kotlin-android-extensions').projectDir = "$rootDir/prepare/android-extensions-compiler-gradle" as File
project(':kotlin-parcelize-compiler').projectDir = "$rootDir/prepare/parcelize-compiler-gradle" as File