KT-64931: add convertion of kotlin top-lvl functions into swift static functions
Merge-request: KT-MR-13878 Merged-by: Artem Olkov <artem.olkov@jetbrains.com>
This commit is contained in:
+3
-5
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.sir.analysisapi.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.analyze
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.sir.*
|
||||
import org.jetbrains.kotlin.sir.builder.buildForeignFunction
|
||||
@@ -24,8 +24,8 @@ private fun KtValueParameterSymbol.toSirParam(): SirKotlinOrigin.Parameter = AAP
|
||||
private class AAFunction(
|
||||
private val originalFunction: KtNamedFunction
|
||||
) : SirKotlinOrigin.Function {
|
||||
override val fqName: List<String>
|
||||
get() = originalFunction.fqName?.pathSegments()?.toListString() ?: emptyList()
|
||||
override val fqName: FqName
|
||||
get() = originalFunction.fqName ?: FqName.fromSegments(emptyList())
|
||||
|
||||
override val parameters: List<SirKotlinOrigin.Parameter>
|
||||
get() = analyze(originalFunction) {
|
||||
@@ -48,5 +48,3 @@ private data class AAParameter(
|
||||
private data class AAKotlinType(
|
||||
override val name: String
|
||||
) : SirKotlinOrigin.Type
|
||||
|
||||
private fun List<Name>.toListString() = map { it.asString() }
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ abstract class AbstractKotlinSirContextTestBase : AbstractAnalysisApiBasedTest()
|
||||
.filterIsInstance<SirForeignFunction>()
|
||||
.forEach {
|
||||
val function = it.origin as SirKotlinOrigin.Function
|
||||
appendLine("${function.fqName}")
|
||||
appendLine("${function.path}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -90,6 +90,7 @@ private fun readRequestFromFile(file: File): BridgeRequest {
|
||||
this.name = fqName.last()
|
||||
this.returnType = returnType
|
||||
this.parameters += parameters
|
||||
this.isStatic = false
|
||||
}
|
||||
return BridgeRequest(function, bridgeName, fqName)
|
||||
}
|
||||
+3
-1
@@ -35,7 +35,9 @@ public class ForeignIntoSwiftFunctionTranslationPass : SirPass<SirElement, Nothi
|
||||
return buildFunction {
|
||||
origin = function.origin
|
||||
visibility = function.visibility
|
||||
name = kotlinOrigin.fqName.last()
|
||||
|
||||
isStatic = function.parent is SirDeclaration
|
||||
name = kotlinOrigin.path.last()
|
||||
kotlinOrigin.parameters.mapTo(parameters) { it.toSir() }
|
||||
|
||||
returnType = kotlinOrigin.returnType.toSir()
|
||||
|
||||
@@ -29,6 +29,7 @@ class SirParentPatcherTests {
|
||||
val function = buildFunction {
|
||||
name = "foo"
|
||||
returnType = SirNominalType(SirSwiftModule.bool)
|
||||
isStatic = false
|
||||
}
|
||||
function.parent = wrongEnum
|
||||
val wrongModule = buildModule { name = "wrongModule" }
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.sir.passes
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.sir.SirFunction
|
||||
import org.jetbrains.kotlin.sir.SirNominalType
|
||||
import org.jetbrains.kotlin.sir.SirParameter
|
||||
import org.jetbrains.kotlin.sir.SirVisibility
|
||||
import org.jetbrains.kotlin.sir.builder.buildEnum
|
||||
import org.jetbrains.kotlin.sir.builder.buildForeignFunction
|
||||
import org.jetbrains.kotlin.sir.builder.buildModule
|
||||
import org.jetbrains.kotlin.sir.constants.*
|
||||
@@ -19,9 +21,7 @@ import org.jetbrains.kotlin.sir.passes.asserts.assertSirFunctionsEquals
|
||||
import org.jetbrains.kotlin.sir.passes.mocks.MockSirFunction
|
||||
import org.jetbrains.kotlin.sir.passes.util.runWithAsserts
|
||||
import org.jetbrains.kotlin.sir.util.SirSwiftModule
|
||||
import org.jetbrains.sir.passes.run
|
||||
import org.jetbrains.sir.passes.translation.ForeignIntoSwiftFunctionTranslationPass
|
||||
import org.jetbrains.sir.passes.utility.assertValid
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
@@ -33,7 +33,7 @@ class SirPassTests {
|
||||
}
|
||||
val mySirElement = buildForeignFunction {
|
||||
origin = MockFunction(
|
||||
fqName = listOf("foo"),
|
||||
fqName = FqName.fromSegments(listOf("foo")),
|
||||
parameters = emptyList(),
|
||||
returnType = MockKotlinType(BOOLEAN),
|
||||
)
|
||||
@@ -48,6 +48,38 @@ class SirPassTests {
|
||||
parameters = emptyList(),
|
||||
returnType = SirNominalType(SirSwiftModule.bool),
|
||||
parent = module,
|
||||
isStatic = false,
|
||||
)
|
||||
assertSirFunctionsEquals(actual = result, expected = exp)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `foreign toplevel function without params with package should be translated as static`() {
|
||||
val module = buildModule {
|
||||
name = "demo"
|
||||
}
|
||||
val mySirEnum = buildEnum {
|
||||
name = "bar"
|
||||
}
|
||||
mySirEnum.parent = module
|
||||
val mySirElement = buildForeignFunction {
|
||||
origin = MockFunction(
|
||||
fqName = FqName.fromSegments(listOf("bar", "foo")),
|
||||
parameters = emptyList(),
|
||||
returnType = MockKotlinType(BOOLEAN),
|
||||
)
|
||||
visibility = SirVisibility.PUBLIC
|
||||
}
|
||||
mySirElement.parent = mySirEnum
|
||||
val myPass = ForeignIntoSwiftFunctionTranslationPass()
|
||||
val result = myPass.runWithAsserts(mySirElement, null) as? SirFunction
|
||||
assertNotNull(result, "SirFunction should be produced")
|
||||
val exp = MockSirFunction(
|
||||
name = "foo",
|
||||
parameters = emptyList(),
|
||||
returnType = SirNominalType(SirSwiftModule.bool),
|
||||
parent = mySirEnum,
|
||||
isStatic = true,
|
||||
)
|
||||
assertSirFunctionsEquals(actual = result, expected = exp)
|
||||
}
|
||||
@@ -59,7 +91,7 @@ class SirPassTests {
|
||||
}
|
||||
val mySirElement = buildForeignFunction {
|
||||
origin = MockFunction(
|
||||
fqName = listOf("foo"),
|
||||
fqName = FqName.fromSegments(listOf("foo")),
|
||||
parameters = listOf(
|
||||
MockParameter(
|
||||
name = "arg1",
|
||||
@@ -112,7 +144,8 @@ class SirPassTests {
|
||||
SirParameter(argumentName = "arg7", type = SirNominalType(SirSwiftModule.bool)),
|
||||
),
|
||||
returnType = SirNominalType(SirSwiftModule.int8),
|
||||
parent = module
|
||||
parent = module,
|
||||
isStatic = false,
|
||||
)
|
||||
assertSirFunctionsEquals(actual = result, expected = exp)
|
||||
}
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.sir.passes
|
||||
|
||||
import org.jetbrains.kotlin.sir.SirOrigin
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.sir.builder.buildForeignFunction
|
||||
import org.jetbrains.kotlin.sir.builder.buildModule
|
||||
import org.jetbrains.kotlin.sir.mock.MockFunction
|
||||
import org.jetbrains.kotlin.sir.mock.MockKotlinType
|
||||
import org.jetbrains.sir.passes.utility.PatchDeclarationParentVisitor
|
||||
import org.jetbrains.sir.passes.utility.SirValidatorConfig
|
||||
import org.jetbrains.sir.passes.utility.ValidationError
|
||||
import org.jetbrains.sir.passes.utility.validate
|
||||
@@ -40,9 +39,9 @@ class SirValidatorTests {
|
||||
}
|
||||
val foreignFunction = buildForeignFunction {
|
||||
val kotlinEntity = MockFunction(
|
||||
fqName = listOf("foo"),
|
||||
fqName = FqName.fromSegments(listOf("foo")),
|
||||
parameters = emptyList(),
|
||||
returnType = MockKotlinType("kotlin/Byte")
|
||||
returnType = MockKotlinType("kotlin/Byte"),
|
||||
)
|
||||
origin = kotlinEntity
|
||||
}
|
||||
@@ -60,4 +59,4 @@ class SirValidatorTests {
|
||||
assertEquals(foreignFunction, error.declaration)
|
||||
assertEquals(module, error.expectedParent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -25,4 +25,8 @@ fun assertSirFunctionsEquals(expected: SirFunction, actual: SirFunction) {
|
||||
actual = actual.returnType,
|
||||
expected = expected.returnType
|
||||
)
|
||||
assertEquals(
|
||||
actual = actual.isStatic,
|
||||
expected = expected.isStatic
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.sir.visitors.SirVisitor
|
||||
|
||||
class MockSirFunction(
|
||||
override val origin: SirOrigin = SirOrigin.Unknown,
|
||||
override val isStatic: Boolean,
|
||||
override val visibility: SirVisibility = SirVisibility.PUBLIC,
|
||||
override var parent: SirDeclarationParent,
|
||||
override val name: String,
|
||||
|
||||
@@ -31,6 +31,7 @@ public class SirAsSwiftSourcesPrinter(private val printer: SmartPrinter) : SirVi
|
||||
override fun visitFunction(function: SirFunction): Unit = with(printer) {
|
||||
print(
|
||||
function.visibility.takeIf { it != SirVisibility.INTERNAL }?.let { "${it.swift} " } ?: "",
|
||||
if (function.isStatic) { "static " } else { "" },
|
||||
"func ",
|
||||
function.name.swiftIdentifier,
|
||||
"("
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
public static func foo(
|
||||
arg1: Swift.Int32
|
||||
) -> Swift.Bool {
|
||||
return foo_wrapped(arg1)
|
||||
}
|
||||
+36
@@ -37,6 +37,7 @@ class SirAsSwiftSourcesPrinterTests {
|
||||
declarations.add(
|
||||
buildFunction {
|
||||
origin = SirOrigin.Unknown
|
||||
isStatic = false
|
||||
visibility = SirVisibility.PUBLIC
|
||||
name = "foo"
|
||||
returnType = SirNominalType(SirSwiftModule.bool)
|
||||
@@ -57,6 +58,7 @@ class SirAsSwiftSourcesPrinterTests {
|
||||
declarations.add(
|
||||
buildFunction {
|
||||
origin = SirOrigin.Unknown
|
||||
isStatic = false
|
||||
visibility = SirVisibility.PUBLIC
|
||||
name = "foo1"
|
||||
returnType = SirNominalType(SirSwiftModule.bool)
|
||||
@@ -65,6 +67,7 @@ class SirAsSwiftSourcesPrinterTests {
|
||||
declarations.add(
|
||||
buildFunction {
|
||||
origin = SirOrigin.Unknown
|
||||
isStatic = false
|
||||
visibility = SirVisibility.PUBLIC
|
||||
name = "foo2"
|
||||
returnType = SirNominalType(SirSwiftModule.bool)
|
||||
@@ -85,6 +88,7 @@ class SirAsSwiftSourcesPrinterTests {
|
||||
declarations.add(
|
||||
buildFunction {
|
||||
origin = SirOrigin.Unknown
|
||||
isStatic = false
|
||||
visibility = SirVisibility.PUBLIC
|
||||
name = "foo"
|
||||
parameters.add(
|
||||
@@ -112,6 +116,7 @@ class SirAsSwiftSourcesPrinterTests {
|
||||
declarations.add(
|
||||
buildFunction {
|
||||
origin = SirOrigin.Unknown
|
||||
isStatic = false
|
||||
visibility = SirVisibility.PUBLIC
|
||||
name = "foo"
|
||||
parameters.add(
|
||||
@@ -146,6 +151,7 @@ class SirAsSwiftSourcesPrinterTests {
|
||||
declarations.add(
|
||||
buildFunction {
|
||||
origin = SirOrigin.Unknown
|
||||
isStatic = false
|
||||
visibility = SirVisibility.PUBLIC
|
||||
name = "foo"
|
||||
parameters.addAll(
|
||||
@@ -199,6 +205,7 @@ class SirAsSwiftSourcesPrinterTests {
|
||||
declarations.add(
|
||||
buildFunction {
|
||||
origin = SirOrigin.Unknown
|
||||
isStatic = false
|
||||
visibility = SirVisibility.PUBLIC
|
||||
name = "foo"
|
||||
parameters.add(
|
||||
@@ -219,6 +226,35 @@ class SirAsSwiftSourcesPrinterTests {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should print static`() {
|
||||
|
||||
val module = buildModule {
|
||||
name = "Test"
|
||||
declarations.add(
|
||||
buildFunction {
|
||||
origin = SirOrigin.Unknown
|
||||
isStatic = true
|
||||
visibility = SirVisibility.PUBLIC
|
||||
name = "foo"
|
||||
parameters.add(
|
||||
SirParameter(
|
||||
argumentName = "arg1",
|
||||
type = SirNominalType(SirSwiftModule.int32)
|
||||
)
|
||||
)
|
||||
returnType = SirNominalType(SirSwiftModule.bool)
|
||||
body = SirFunctionBody(listOf("return foo_wrapped(arg1)"))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
runTest(
|
||||
module,
|
||||
"testData/static_function"
|
||||
)
|
||||
}
|
||||
|
||||
private fun runTest(module: SirModule, goldenDataFile: String) {
|
||||
val expectedSwiftSrc = File(KtTestUtil.getHomeDirectory()).resolve("$goldenDataFile.golden.swift")
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ description = "Swift Intermediate Representation"
|
||||
dependencies {
|
||||
compileOnly(kotlinStdlib())
|
||||
|
||||
api(project(":core:compiler.common"))
|
||||
|
||||
if (kotlinBuildProperties.isInIdeaSync) {
|
||||
compileOnly(project("tree-generator")) // Provided, so that IDEA can recognize references to this module in KDoc.
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ abstract class SirFunction : SirElementBase(), SirCallable {
|
||||
abstract override val origin: SirOrigin
|
||||
abstract override val visibility: SirVisibility
|
||||
abstract override var parent: SirDeclarationParent
|
||||
abstract val isStatic: Boolean
|
||||
abstract val name: String
|
||||
abstract val parameters: List<SirParameter>
|
||||
abstract val returnType: SirType
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.sir.impl.SirFunctionImpl
|
||||
class SirFunctionBuilder {
|
||||
var origin: SirOrigin = SirOrigin.Unknown
|
||||
var visibility: SirVisibility = SirVisibility.PUBLIC
|
||||
var isStatic: Boolean by kotlin.properties.Delegates.notNull<Boolean>()
|
||||
lateinit var name: String
|
||||
val parameters: MutableList<SirParameter> = mutableListOf()
|
||||
lateinit var returnType: SirType
|
||||
@@ -27,6 +28,7 @@ class SirFunctionBuilder {
|
||||
return SirFunctionImpl(
|
||||
origin,
|
||||
visibility,
|
||||
isStatic,
|
||||
name,
|
||||
parameters,
|
||||
returnType,
|
||||
@@ -52,6 +54,7 @@ inline fun buildFunctionCopy(original: SirFunction, init: SirFunctionBuilder.()
|
||||
val copyBuilder = SirFunctionBuilder()
|
||||
copyBuilder.origin = original.origin
|
||||
copyBuilder.visibility = original.visibility
|
||||
copyBuilder.isStatic = original.isStatic
|
||||
copyBuilder.name = original.name
|
||||
copyBuilder.parameters.addAll(original.parameters)
|
||||
copyBuilder.returnType = original.returnType
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.sir.visitors.SirVisitor
|
||||
internal class SirFunctionImpl(
|
||||
override val origin: SirOrigin,
|
||||
override val visibility: SirVisibility,
|
||||
override val isStatic: Boolean,
|
||||
override val name: String,
|
||||
override val parameters: MutableList<SirParameter>,
|
||||
override val returnType: SirType,
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.sir
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
sealed interface SirKotlinOrigin : SirOrigin.Foreign {
|
||||
val fqName: List<String>
|
||||
val fqName: FqName
|
||||
|
||||
override val path: List<String>
|
||||
get() = fqName
|
||||
get() = fqName.pathSegments().map { it.asString() }
|
||||
|
||||
interface Function : SirKotlinOrigin {
|
||||
val parameters: List<Parameter>
|
||||
@@ -24,4 +26,4 @@ sealed interface SirKotlinOrigin : SirOrigin.Foreign {
|
||||
interface Type {
|
||||
val name: String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.sir.mock
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.sir.SirKotlinOrigin
|
||||
|
||||
data class MockFunction(
|
||||
override val fqName: List<String>,
|
||||
override val fqName: FqName,
|
||||
override val parameters: List<SirKotlinOrigin.Parameter>,
|
||||
override val returnType: SirKotlinOrigin.Type,
|
||||
) : SirKotlinOrigin.Function
|
||||
|
||||
+2
@@ -7,6 +7,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.sir.tree.generator
|
||||
|
||||
import org.jetbrains.kotlin.generators.tree.StandardTypes.boolean
|
||||
import org.jetbrains.kotlin.generators.tree.StandardTypes.string
|
||||
import org.jetbrains.kotlin.sir.tree.generator.config.AbstractSwiftIrTreeBuilder
|
||||
import org.jetbrains.kotlin.sir.tree.generator.model.Element
|
||||
@@ -81,6 +82,7 @@ object SwiftIrTree : AbstractSwiftIrTreeBuilder() {
|
||||
customParentInVisitor = callable
|
||||
parent(callable)
|
||||
|
||||
+field("isStatic", boolean) // todo: KT-65046 Method|function distinction in SIR
|
||||
+field("name", string)
|
||||
+listField("parameters", parameterType)
|
||||
+field("returnType", typeType)
|
||||
|
||||
+1
-1
@@ -164,7 +164,7 @@ class SwiftExportExtension(
|
||||
}
|
||||
|
||||
override fun visitFunction(function: SirFunction) {
|
||||
val fqName = (function.origin as? SirKotlinOrigin.Function)?.fqName
|
||||
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
|
||||
|
||||
@@ -5,3 +5,5 @@ int32_t namespace1_main_foobar(int32_t param);
|
||||
int32_t namespace1_foo();
|
||||
|
||||
int32_t namespace2_bar();
|
||||
|
||||
int32_t __root___foo();
|
||||
|
||||
@@ -17,3 +17,9 @@ public fun namespace2_bar(): Int {
|
||||
val result = namespace2.bar()
|
||||
return result
|
||||
}
|
||||
|
||||
@ExportedBridge("__root___foo")
|
||||
public fun __root___foo(): Int {
|
||||
val result = foo()
|
||||
return result
|
||||
}
|
||||
|
||||
+7
-3
@@ -1,18 +1,22 @@
|
||||
enum namespace1 {
|
||||
enum main {
|
||||
public func foobar(
|
||||
public static func foobar(
|
||||
param: Swift.Int32
|
||||
) -> Swift.Int32 {
|
||||
return namespace1_main_foobar(param)
|
||||
}
|
||||
}
|
||||
public func foo() -> Swift.Int32 {
|
||||
public static func foo() -> Swift.Int32 {
|
||||
return namespace1_foo()
|
||||
}
|
||||
}
|
||||
|
||||
enum namespace2 {
|
||||
public func bar() -> Swift.Int32 {
|
||||
public static func bar() -> Swift.Int32 {
|
||||
return namespace2_bar()
|
||||
}
|
||||
}
|
||||
|
||||
public func foo() -> Swift.Int32 {
|
||||
return __root___foo()
|
||||
}
|
||||
|
||||
+3
@@ -1,5 +1,8 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
// FILE: no_package.kt
|
||||
fun foo(): Int = 123
|
||||
|
||||
// FILE: foo.kt
|
||||
package namespace1
|
||||
fun foo(): Int = 123
|
||||
|
||||
Reference in New Issue
Block a user