KT-65123: move Swift Export Compiler Plugin into swift-export-standalone module

Merge-request: KT-MR-14031
Merged-by: Artem Olkov <artem.olkov@jetbrains.com>
This commit is contained in:
Artem Olkov
2024-01-29 10:32:09 +00:00
committed by Space Team
parent d935db9e3a
commit de6a27aeeb
42 changed files with 442 additions and 771 deletions
-67
View File
@@ -1,67 +0,0 @@
# Swift Export Compiler Plugin
## Description
This module represents an entry point for the SwiftExport-Frontend functionality. It is implemented as a compiler plugin, without a direct CLI interface.
## Usage Guide
### How to build
```bash
./gradlew kotlin-swift-export-compiler-plugin:build
```
This will produce the resulting jar (with all dependency embedded) at `%PATH_TO_KOTLIN_REPO%/plugins/swift-export/build/libs/kotlin-swift-export-compiler-plugin-%VERSION%.jar`
### Example usage
Given that:
1. there is a `kotlinc` installed at `$PATH`
2. sources are located in the `app.kt` file
3. the `$PLUGIN_PATH` variable contains the path to the jar received from the ["How to build"](#How-to-build) section
```bash
kotlinc -language-version 2.0 app.kt -Xplugin=$PLUGIN_PATH -P plugin:org.jetbrains.kotlin.swiftexport:output_dir="~/my_awesome_directory/"
```
This will produce the following file tree:
```
~/my_awesome_directory/
|_result.swift
|_result.kt
|_result.h
```
`result.kt` - contains the kotlin bridge for the resulting module. It should be compiled against the `.klib` produced by kotlinc-native in order to receive the final binary.
`result.h` - contains C-header for final binary. The `result.swift` uses this header to talk to this compiled binary.
`result.swift` - contains the resulting Swift API for the compiled Kotlin/Native library.
### Supported Options
#### Output Directory
`output_dir` — Required parameter. Determines where the resulting artifacts will be placed.
#### Named
`named` — Optional parameter. Determines the names of the resulting files. By default — `result`.
## Dev guide
### How to generate tests:
```bash
./gradlew :generators:sir-tests-generator:generateTests
```
this will generate tests from the input files. The input files can be found and should be placed here: `plugins/swift-export/testData`
The test expects to find the `.golden.swift`, `.golden.kt` and `.golden.h` files that contain the resulting bridges. The name of the `.golden.*` file should be the same as the name of the corresponding `.kt` file.
The project for the generator can be found here — `generators/sir-tests-generator/build.gradle.kts`
### How to run the tests:
```bash
./gradlew :kotlin-swift-export-compiler-plugin:test
```
OR just open `SwiftExportCompilerPluginTest` in IDEA and start them from gutter.
-59
View File
@@ -1,59 +0,0 @@
description = "Swift Export Compiler Plugin"
plugins {
kotlin("jvm")
}
dependencies {
embedded(project(":kotlin-swift-export-compiler-plugin.backend")) { isTransitive = false }
embedded(project(":kotlin-swift-export-compiler-plugin.cli")) { isTransitive = false }
embedded(project(":native:swift:sir")) { isTransitive = false }
embedded(project(":native:swift:sir-analysis-api")) { isTransitive = false }
embedded(project(":native:swift:sir-compiler-bridge")) { isTransitive = false }
embedded(project(":native:swift:sir-passes")) { isTransitive = false }
embedded(project(":native:swift:sir-printer")) { isTransitive = false }
testApi(project(":kotlin-swift-export-compiler-plugin.cli"))
testApi(platform(libs.junit.bom))
testImplementation(libs.junit.jupiter.api)
testRuntimeOnly(libs.junit.jupiter.engine)
testImplementation(projectTests(":compiler:tests-common"))
testImplementation(projectTests(":compiler:tests-common-new"))
testApi(intellijCore())
}
optInToExperimentalCompilerApi()
sourceSets {
"main" { none() }
"test" {
projectDefault()
generatedTestDir()
}
}
optInToExperimentalCompilerApi()
if (project.kotlinBuildProperties.isSwiftExportPluginPublishingEnabled) {
// todo: is you are removing this check - don't forget to run tests in repo/artifacts-tests/src/test/kotlin/org/jetbrains/kotlin/code/ArtifactsTest.kt
publish()
}
runtimeJar()
sourcesJar()
javadocJar()
testsJar()
val testDataDir = projectDir.resolve("testData")
projectTest(parallel = true, jUnitMode = JUnitMode.JUnit5) {
workingDir = rootDir
dependsOn(":dist")
inputs.dir(testDataDir)
useJUnitPlatform()
}
@@ -1,34 +0,0 @@
description = "Swift Compiler Plugin (Backend)"
plugins {
kotlin("jvm")
}
dependencies {
compileOnly(project(":compiler:backend"))
compileOnly(project(":compiler:ir.backend.common"))
compileOnly(intellijCore())
implementation(project(":native:swift:sir"))
implementation(project(":native:swift:sir-analysis-api"))
implementation(project(":native:swift:sir-compiler-bridge"))
implementation(project(":native:swift:sir-passes"))
implementation(project(":native:swift:sir-printer"))
implementation(project(":analysis:analysis-api"))
implementation(project(":analysis:analysis-api-standalone"))
compileOnly(commonDependency("org.jetbrains.intellij.deps:asm-all"))
implementation(kotlinStdlib())
}
optInToUnsafeDuringIrConstructionAPI()
sourceSets {
"main" { projectDefault() }
"test" { none() }
}
runtimeJar()
sourcesJar()
javadocJar()
@@ -1,184 +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.swiftexport
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.buildStandaloneAnalysisAPISession
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.fir.extensions.FirAnalysisHandlerExtension
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.sir.*
import org.jetbrains.kotlin.sir.analysisapi.SirGenerator
import org.jetbrains.kotlin.sir.bridge.*
import org.jetbrains.kotlin.sir.builder.buildModule
import org.jetbrains.kotlin.sir.visitors.SirVisitorVoid
import org.jetbrains.sir.passes.SirInflatePackagesPass
import org.jetbrains.sir.passes.SirModulePass
import org.jetbrains.sir.passes.SirPass
import org.jetbrains.sir.passes.run
import org.jetbrains.sir.passes.translation.ForeignIntoSwiftFunctionTranslationPass
import org.jetbrains.sir.printer.SirAsSwiftSourcesPrinter
import java.io.File
class SwiftExportExtension(
private val destination: File,
private val outputFileName: String,
) : FirAnalysisHandlerExtension() {
override fun isApplicable(configuration: CompilerConfiguration): Boolean {
return true
}
override fun doAnalysis(configuration: CompilerConfiguration): Boolean {
val module = buildSwiftModule(configuration)
.transformToSwift()
val bridgeRequests = module.createFunctionBridges()
module.dumpResultToFiles(bridgeRequests)
return true
}
private fun SirModule.createFunctionBridges(): List<BridgeRequest> {
return BridgeGenerationPass.run(this)
}
@OptIn(KtAnalysisApiInternals::class)
private fun buildSwiftModule(configuration: CompilerConfiguration): SirModule {
val standaloneAnalysisAPISession =
buildStandaloneAnalysisAPISession(classLoader = SwiftExportExtension::class.java.classLoader) {
@Suppress("DEPRECATION") // TODO: KT-61319 Kapt: remove usages of deprecated buildKtModuleProviderByCompilerConfiguration
buildKtModuleProviderByCompilerConfiguration(configuration)
registerProjectService(KtLifetimeTokenProvider::class.java, KtAlwaysAccessibleLifetimeTokenProvider())
}
val (sourceModule, rawFiles) = standaloneAnalysisAPISession.modulesWithFiles.entries.single()
val ktFiles = rawFiles.filterIsInstance<KtFile>()
return buildModule {
name = sourceModule.moduleName
val sirFactory = SirGenerator()
ktFiles.forEach { file ->
declarations += sirFactory.build(file)
}
}.apply {
declarations.forEach { it.parent = this }
}
}
private fun SirModule.transformToSwift(): SirModule {
return SirPassesConfiguration.passes.fold(this) { module, pass ->
pass.run(module)
}
}
private fun SirModule.dumpResultToFiles(requests: List<BridgeRequest>) {
val destinationPath = destination.absolutePath
val cHeaderFile = File("${destinationPath}/${outputFileName}.h")
val ktBridgeFile = File("${destinationPath}/${outputFileName}.kt")
val swiftFile = File("${destinationPath}/${outputFileName}.swift")
val bridges = generateBridgeSources(requests)
val swiftSrc = generateSwiftSrc()
dumpTextAtFile(bridges.ktSrc, ktBridgeFile)
dumpTextAtFile(bridges.cSrc, cHeaderFile)
dumpTextAtFile(sequenceOf(swiftSrc), swiftFile)
}
private fun SirModule.generateSwiftSrc(): String {
return SirAsSwiftSourcesPrinter().print(this)
}
private fun generateBridgeSources(requests: List<BridgeRequest>): BridgeSources {
val generator = createBridgeGenerator()
val kotlinBridgePrinter = createKotlinBridgePrinter()
val cBridgePrinter = createCBridgePrinter()
requests.forEach { request ->
val bridge = generator.generate(request)
kotlinBridgePrinter.add(bridge)
cBridgePrinter.add(bridge)
}
val actualKotlinSrc = kotlinBridgePrinter.print()
val actualCHeader = cBridgePrinter.print()
return BridgeSources(ktSrc = actualKotlinSrc, cSrc = actualCHeader)
}
private fun dumpTextAtFile(text: Sequence<String>, file: File) {
if (!file.exists()) {
file.parentFile.mkdirs()
file.createNewFile()
}
val writer = file.printWriter()
for (t in text) {
writer.println(t)
}
writer.close()
}
private data class BridgeSources(val ktSrc: Sequence<String>, val cSrc: Sequence<String>)
private object SirPassesConfiguration {
val passes: List<SirModulePass> = listOf(
SirInflatePackagesPass(),
WholeModuleTranslationByElementPass(ForeignIntoSwiftFunctionTranslationPass()),
)
class WholeModuleTranslationByElementPass(
val pass: SirPass<SirElement, Nothing?, SirDeclaration>
) : SirModulePass {
override fun run(element: SirModule, data: Nothing?): SirModule {
return buildModule {
name = element.name
element.declarations.forEach {
val newDecl = pass.run(it)
declarations.add(newDecl)
}
}.apply {
declarations.forEach { it.parent = this }
}
}
}
}
private object BridgeGenerationPass : SirPass<SirElement, Nothing?, List<BridgeRequest>> {
override fun run(element: SirElement, data: Nothing?): List<BridgeRequest> {
val requests = mutableListOf<BridgeRequest>()
element.accept(Visitor(requests))
return requests.toList()
}
private class Visitor(val requests: MutableList<BridgeRequest>) : SirVisitorVoid() {
override fun visitElement(element: SirElement) {
element.acceptChildren(this)
}
override fun visitFunction(function: SirFunction) {
val fqName = (function.origin as? SirKotlinOrigin.Function)?.path
?: return
val fqNameForBridge = if (fqName.count() == 1) {
listOf("__root__", fqName.first()) // todo: should be changed with correct mangling KT-64970
} else {
fqName
}
val bridgeRequest = BridgeRequest(
function,
fqNameForBridge.joinToString("_"),
fqName
)
requests += bridgeRequest
function.body = createFunctionBodyFromRequest(bridgeRequest)
}
}
}
}
@@ -1,12 +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.swiftexport
object SwiftExportPluginNames {
const val PLUGIN_ID = "org.jetbrains.kotlin.swiftexport"
const val OUTPUT_DIR_KEY = "output_dir"
const val RESULT_NAME_KEY = "named"
}
@@ -1,34 +0,0 @@
description = "Swift Compiler Plugin (CLI)"
plugins {
kotlin("jvm")
}
dependencies {
implementation(project(":kotlin-swift-export-compiler-plugin.backend"))
compileOnly(project(":compiler:plugin-api"))
compileOnly(project(":compiler:fir:entrypoint"))
embedded(project(":analysis:analysis-api-standalone")) { isTransitive = false }
embedded(project(":analysis:analysis-api")) { isTransitive = false }
embedded(project(":analysis:analysis-api-fir")) { isTransitive = false }
embedded(project(":analysis:analysis-api-impl-base")) { isTransitive = false }
embedded(project(":analysis:analysis-api-impl-barebone")) { isTransitive = false }
embedded(project(":analysis:analysis-api-standalone:analysis-api-standalone-base")) { isTransitive = false }
embedded(project(":analysis:analysis-api-standalone:analysis-api-fir-standalone-base")) { isTransitive = false }
embedded(project(":analysis:analysis-internal-utils")) { isTransitive = false }
embedded(project(":analysis:low-level-api-fir")) { isTransitive = false }
embedded(project(":analysis:symbol-light-classes")) { isTransitive = false }
}
optInToExperimentalCompilerApi()
sourceSets {
"main" { projectDefault() }
"test" { none() }
}
runtimeJar()
sourcesJar()
javadocJar()
@@ -1 +0,0 @@
org.jetbrains.kotlin.swiftexport.SwiftExportCommandLineProcessor
@@ -1 +0,0 @@
org.jetbrains.kotlin.swiftexport.SwiftExportComponentRegistrar
@@ -1,68 +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.swiftexport
import org.jetbrains.kotlin.compiler.plugin.*
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.fir.extensions.FirAnalysisHandlerExtension
import org.jetbrains.kotlin.swiftexport.SwiftExportPluginNames.OUTPUT_DIR_KEY
import org.jetbrains.kotlin.swiftexport.SwiftExportPluginNames.PLUGIN_ID
import org.jetbrains.kotlin.swiftexport.SwiftExportPluginNames.RESULT_NAME_KEY
import java.io.File
object SwiftExportConfigurationKeys {
val OUTPUT_DIR: CompilerConfigurationKey<String> = CompilerConfigurationKey.create(
"Destination directory for swift-export resulted files"
)
val RESULT_NAME: CompilerConfigurationKey<String> = CompilerConfigurationKey.create(
"Filenames for resulted files. There will be 3 files - %RESULT_NAME%.swift, %RESULT_NAME%.h and %RESULT_NAME%.kt."
)
}
class SwiftExportCommandLineProcessor : CommandLineProcessor {
companion object {
val OUTPUT_DIR = CliOption(
OUTPUT_DIR_KEY, "output destination",
"Destination directory for swift-export resulted files",
required = true, allowMultipleOccurrences = false
)
val RESULT_NAME = CliOption(
RESULT_NAME_KEY, "Filenames for resulted files",
"Filenames for resulted files. By default - \"result\"",
required = false, allowMultipleOccurrences = false
)
}
override val pluginId = PLUGIN_ID
override val pluginOptions = listOf(
OUTPUT_DIR, RESULT_NAME
)
override fun processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) = when (option) {
OUTPUT_DIR -> configuration.put(SwiftExportConfigurationKeys.OUTPUT_DIR, value)
RESULT_NAME -> configuration.put(SwiftExportConfigurationKeys.RESULT_NAME, value)
else -> throw CliOptionProcessingException("Unknown option: ${option.optionName}")
}
}
class SwiftExportComponentRegistrar : CompilerPluginRegistrar() {
override val supportsK2: Boolean
get() = true
override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
val dir = File(
configuration.get(SwiftExportConfigurationKeys.OUTPUT_DIR)
?: throw IllegalArgumentException("output_dir is a required argument for org.jetbrains.kotlin.swiftexport")
)
val named = configuration.get(SwiftExportConfigurationKeys.RESULT_NAME)
?: "result"
FirAnalysisHandlerExtension.registerExtension(
SwiftExportExtension(dir, named)
)
}
}
@@ -1,22 +0,0 @@
plugins {
id("org.jetbrains.kotlin.jvm")
}
dependencies {
embedded(project(":kotlin-swift-export-compiler-plugin")) { isTransitive = false }
}
if (project.kotlinBuildProperties.isSwiftExportPluginPublishingEnabled) {
// todo: is you are removing this check - don't forget to run tests in repo/artifacts-tests/src/test/kotlin/org/jetbrains/kotlin/code/ArtifactsTest.kt
publish {
artifactId = "kotlin-swift-export-compiler-plugin-embeddable"
}
}
runtimeJar(rewriteDefaultJarDepsToShadedCompiler())
sourcesJarWithSourcesFromEmbedded(
project(":kotlin-swift-export-compiler-plugin").tasks.named<Jar>("sourcesJar")
)
javadocJarWithJavadocFromEmbedded(
project(":kotlin-swift-export-compiler-plugin").tasks.named<Jar>("javadocJar")
)
@@ -1,111 +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.swiftexport
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.cli.common.CLITool
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.CompilerTestUtil
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import org.jetbrains.kotlin.test.services.getKtFilesForSourceFiles
import org.jetbrains.kotlin.test.services.sourceFileProvider
import java.io.File
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import kotlin.reflect.KClass
import kotlin.test.assertEquals
internal class JvmCompilerWithSwiftExportPluginFacade(
private val testServices: TestServices,
) : AbstractTestFacade<ResultingArtifact.Source, SwiftExportArtifact>() {
override val inputKind: TestArtifactKind<ResultingArtifact.Source>
get() = SourcesKind
override val outputKind: TestArtifactKind<SwiftExportArtifact>
get() = SwiftExportArtifact.Kind
private val tmpDir = FileUtil.createTempDirectory("SwiftExportIntegrationTests", null, false)
override fun transform(module: TestModule, inputArtifact: ResultingArtifact.Source): SwiftExportArtifact {
val configurationProvider = testServices.compilerConfigurationProvider
val project = configurationProvider.getProject(module)
val ktFiles = testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project, findViaVfs = true).values.toList()
val outputDirPath = tmpDir.absolutePath + "/" + "swift_export_output"
val outputDir = File(outputDirPath)
outputDir.mkdirs()
runTest(
K2JVMCompiler(),
ktFiles,
outputDir
)
return SwiftExportArtifact(
File(outputDir.absolutePath + "/result.swift"),
File(outputDir.absolutePath + "/result.h"),
File(outputDir.absolutePath + "/result.kt"),
)
}
private fun runTest(
compiler: CLITool<*>,
src: List<KtFile>,
outputDir: File,
) {
val sources = src.map {
tmpDir.resolve(it.name).apply {
writeText(it.text)
}
}
val plugin = writePlugin(
SwiftExportCommandLineProcessor::class,
SwiftExportComponentRegistrar::class,
)
val args = listOf(
"-Xplugin=$plugin",
"-P", "plugin:org.jetbrains.kotlin.swiftexport:output_dir=${outputDir}"
) + sources.map { it.absolutePath }
val outputPath = listOf(
"-language-version", "2.0",
"-d", tmpDir.resolve("out").absolutePath
)
val (output, exitCode) = CompilerTestUtil.executeCompiler(
compiler,
args + outputPath
)
assertEquals(ExitCode.OK, exitCode, output)
}
private fun writePlugin(
cliProcessor: KClass<out CommandLineProcessor>,
registrarKClass: KClass<out CompilerPluginRegistrar>,
): String {
val jarFile = tmpDir.resolve("plugin.jar")
ZipOutputStream(jarFile.outputStream()).use {
val entryRegistry = ZipEntry("META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar")
it.putNextEntry(entryRegistry)
it.write(registrarKClass.java.name.toByteArray())
val entryCLI = ZipEntry("META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor")
it.putNextEntry(entryCLI)
it.write(cliProcessor.java.name.toByteArray())
}
return jarFile.absolutePath
}
override fun shouldRunAnalysis(module: TestModule): Boolean {
return true
}
}
@@ -1,50 +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.swiftexport
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.runners.*
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
open class AbstractSwiftExportContextTest : AbstractSwiftExportContextTestBase(TargetBackend.JVM) {
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
builder.apply {
globalDefaults {
targetBackend = TargetBackend.JVM
}
}
}
}
abstract class AbstractSwiftExportContextTestBase(
targetBackend: TargetBackend
) : AbstractKotlinCompilerWithTargetBackendTest(targetBackend) {
override fun TestConfigurationBuilder.configuration() {
globalDefaults {
frontend = FrontendKinds.FIR
targetPlatform = JvmPlatforms.defaultJvmPlatform
dependencyKind = DependencyKind.Binary
}
useConfigurators(
::CommonEnvironmentConfigurator,
::JvmEnvironmentConfigurator,
)
facadeStep(::JvmCompilerWithSwiftExportPluginFacade)
handlersStep(SwiftExportArtifact.Kind) {
useHandlers(::SirExportHandler)
}
}
}
@@ -1,37 +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.swiftexport
import org.jetbrains.kotlin.test.model.AnalysisHandler
import org.jetbrains.kotlin.test.model.TestArtifactKind
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
import java.io.File
internal class SirExportHandler(testServices: TestServices) : AnalysisHandler<SwiftExportArtifact>(
testServices,
failureDisablesNextSteps = true,
doNotRunIfThereWerePreviousFailures = true
) {
override val artifactKind: TestArtifactKind<SwiftExportArtifact>
get() = SwiftExportArtifact.Kind
override fun processModule(module: TestModule, info: SwiftExportArtifact) {
val originalFile = module.files.first().originalFile
val originalFileName = originalFile.absolutePath.removeSuffix(".kt")
val expectedSwift = File("${originalFileName}.golden.swift")
val expectedCHeader = File("${originalFileName}.golden.h")
val expectedKotlinBridge = File("${originalFileName}.golden.kt")
testServices.assertions.assertEqualsToFile(expectedSwift, info.swift.readText())
testServices.assertions.assertEqualsToFile(expectedCHeader, info.cHeader.readText())
testServices.assertions.assertEqualsToFile(expectedKotlinBridge, info.ktBridge.readText())
}
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
}
@@ -1,21 +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.swiftexport
import org.jetbrains.kotlin.test.model.BinaryKind
import org.jetbrains.kotlin.test.model.ResultingArtifact
import java.io.File
internal data class SwiftExportArtifact(
val swift: File,
val cHeader: File,
val ktBridge: File,
) : ResultingArtifact.Binary<SwiftExportArtifact>() {
object Kind : BinaryKind<SwiftExportArtifact>("SwiftExportArtifact")
override val kind: BinaryKind<SwiftExportArtifact>
get() = Kind
}
-3
View File
@@ -1,3 +0,0 @@
#include <stdint.h>
int32_t __root___meaningOfLife();
-7
View File
@@ -1,7 +0,0 @@
import kotlin.native.internal.ExportedBridge
@ExportedBridge("__root___meaningOfLife")
public fun __root___meaningOfLife(): Int {
val result = meaningOfLife()
return result
}
-3
View File
@@ -1,3 +0,0 @@
public func meaningOfLife() -> Swift.Int32 {
return __root___meaningOfLife()
}
-1
View File
@@ -1 +0,0 @@
fun meaningOfLife(): Int = 420
-9
View File
@@ -1,9 +0,0 @@
#include <stdint.h>
int32_t namespace1_main_foobar(int32_t param);
int32_t namespace1_foo();
int32_t namespace2_bar();
int32_t __root___foo();
-25
View File
@@ -1,25 +0,0 @@
import kotlin.native.internal.ExportedBridge
@ExportedBridge("namespace1_main_foobar")
public fun namespace1_main_foobar(param: Int): Int {
val result = namespace1.main.foobar(param)
return result
}
@ExportedBridge("namespace1_foo")
public fun namespace1_foo(): Int {
val result = namespace1.foo()
return result
}
@ExportedBridge("namespace2_bar")
public fun namespace2_bar(): Int {
val result = namespace2.bar()
return result
}
@ExportedBridge("__root___foo")
public fun __root___foo(): Int {
val result = foo()
return result
}
-22
View File
@@ -1,22 +0,0 @@
enum namespace1 {
enum main {
public static func foobar(
param: Swift.Int32
) -> Swift.Int32 {
return namespace1_main_foobar(param)
}
}
public static func foo() -> Swift.Int32 {
return namespace1_foo()
}
}
enum namespace2 {
public static func bar() -> Swift.Int32 {
return namespace2_bar()
}
}
public func foo() -> Swift.Int32 {
return __root___foo()
}
-19
View File
@@ -1,19 +0,0 @@
// WITH_STDLIB
// FILE: no_package.kt
fun foo(): Int = 123
// FILE: foo.kt
package namespace1
fun foo(): Int = 123
// FILE: bar.kt
package namespace2
fun bar(): Int = 321
// FILE: main.kt
package namespace1.main
import namespace1
import namespace2
fun foobar(param: Int): Int = foo() + bar() + param
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.swiftexport;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.native.swift.sir.GenerateSirTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("plugins/swift-export/testData")
@TestDataPath("$PROJECT_ROOT")
public class SwiftExportCompilerPluginTest extends AbstractSwiftExportContextTest {
@Test
public void testAllFilesPresentInTestData() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/swift-export/testData"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile(".*\\.golden\\.kt$"), TargetBackend.JVM, false);
}
@Test
@TestMetadata("no_package.kt")
public void testNo_package() throws Exception {
runTest("plugins/swift-export/testData/no_package.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("plugins/swift-export/testData/simple.kt");
}
}