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