KT-63269: implementation for SIRGenerator with top-level functions
KT-63269: add test generator Merge-request: KT-MR-12945 Merged-by: Artem Olkov <artem.olkov@jetbrains.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { java.srcDirs("main") }
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testApi(projectTests(":native:swift:sir-analysis-api"))
|
||||
testImplementation(projectTests(":generators:test-generator"))
|
||||
|
||||
testRuntimeOnly(projectTests(":analysis:analysis-test-framework"))
|
||||
testImplementation(libs.junit.jupiter.api)
|
||||
}
|
||||
|
||||
val generateSirAnalysisApiTests by generator("org.jetbrains.kotlin.generators.tests.native.swift.sir.analysis.api.GenerateSirAnalysisApiTestsKt")
|
||||
|
||||
testsJar()
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
freeCompilerArgs.add("-Xcontext-receivers")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
projectTest(jUnitMode = JUnitMode.JUnit5) {
|
||||
workingDir = rootDir
|
||||
useJUnitPlatform { }
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.generators.tests.native.swift.sir.analysis.api
|
||||
|
||||
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5
|
||||
import org.jetbrains.kotlin.sir.analysisapi.AbstractKotlinSirContextTest
|
||||
|
||||
|
||||
fun main() {
|
||||
System.setProperty("java.awt.headless", "true")
|
||||
generateTestGroupSuiteWithJUnit5 {
|
||||
testGroup(
|
||||
"native/swift/sir-analysis-api/tests-gen/",
|
||||
"native/swift/sir-analysis-api/testData"
|
||||
) {
|
||||
testClass<AbstractKotlinSirContextTest>(
|
||||
suiteTestClassName = "SirAnalysisGeneratedTests"
|
||||
) {
|
||||
model("", pattern = "^([^_](.+)).kt$", recursive = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Build Swift IR from Analysis API
|
||||
|
||||
This module is responsible for populating SIR tree. It is the first step in Swift Export pipeline.
|
||||
|
||||
Input:
|
||||
It should be possible to populate SIR from two types of artefacts:
|
||||
1/ Kotlin Source Module
|
||||
2/ KLib (currently not supported)
|
||||
|
||||
## Dev guide
|
||||
|
||||
### How to generate tests:
|
||||
```bash
|
||||
./gradlew :generators:sir-analysis-api-generator:generateSirAnalysisApiTests
|
||||
```
|
||||
this will generate test by their input files. Input files could be found and should be placed here - `native/swift/sir-analysis-api/testData`
|
||||
|
||||
The test expects to find `.sir` file, containing serialized SIR for the test-case. Name of the `.sir` file should be the same as a name of corresponding `.kt` file.
|
||||
|
||||
The project for the generator can be found here - `generators/sir-analysis-api-generator/build.gradle.kts`
|
||||
|
||||
### How to run tests:
|
||||
```bash
|
||||
./gradlew :native:swift:sir-analysis-api:test --tests "*"
|
||||
```
|
||||
OR just open `SirAnalysisGeneratedTests` in IDEA and start them from gutter.
|
||||
|
||||
### Project Setup
|
||||
No additional setup required to develop this project.
|
||||
@@ -2,19 +2,45 @@ plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
description = "Build Swift IR from Analysis"
|
||||
description = "Build Swift IR from Analysis API"
|
||||
|
||||
dependencies {
|
||||
compileOnly(kotlinStdlib())
|
||||
|
||||
api(project(":native:swift:sir"))
|
||||
api(project(":analysis:analysis-api"))
|
||||
implementation(project(":analysis:analysis-api-standalone"))
|
||||
|
||||
testImplementation(libs.junit4)
|
||||
testApi(platform(libs.junit.bom))
|
||||
testRuntimeOnly(libs.junit.jupiter.engine)
|
||||
testImplementation(libs.junit.jupiter.api)
|
||||
|
||||
testRuntimeOnly(projectTests(":analysis:low-level-api-fir"))
|
||||
testRuntimeOnly(projectTests(":analysis:analysis-api-impl-base"))
|
||||
testImplementation(projectTests(":analysis:analysis-api-fir"))
|
||||
testImplementation(projectTests(":analysis:analysis-test-framework"))
|
||||
testImplementation(projectTests(":compiler:tests-common"))
|
||||
testImplementation(projectTests(":compiler:tests-common-new"))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
"test" {
|
||||
projectDefault()
|
||||
generatedTestDir()
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
freeCompilerArgs.add("-Xcontext-receivers")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
projectTest(jUnitMode = JUnitMode.JUnit5) {
|
||||
workingDir = rootDir
|
||||
useJUnitPlatform { }
|
||||
}
|
||||
|
||||
testsJar()
|
||||
|
||||
+33
-3
@@ -5,11 +5,41 @@
|
||||
|
||||
package org.jetbrains.kotlin.sir.analysisapi
|
||||
|
||||
import org.jetbrains.kotlin.sir.SirElement
|
||||
import org.jetbrains.kotlin.analysis.api.analyze
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPublic
|
||||
import org.jetbrains.kotlin.sir.SirDeclaration
|
||||
import org.jetbrains.kotlin.sir.SirForeignFunction
|
||||
|
||||
/**
|
||||
* A root interface for classes that produce Swift IR elements.
|
||||
*/
|
||||
interface SirFactory {
|
||||
fun build(): SirElement
|
||||
}
|
||||
fun build(fromFile: KtFile): List<SirDeclaration>
|
||||
}
|
||||
|
||||
class SirGenerator : SirFactory {
|
||||
override fun build(fromFile: KtFile): List<SirDeclaration> = analyze(fromFile) {
|
||||
val res = mutableListOf<SirForeignFunction>()
|
||||
fromFile.accept(Visitor(res))
|
||||
return res.toList()
|
||||
}
|
||||
|
||||
private class Visitor(val res: MutableList<SirForeignFunction>) : KtTreeVisitorVoid() {
|
||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||
super.visitNamedFunction(function)
|
||||
function
|
||||
.takeIf { function.isPublic }
|
||||
?.fqName
|
||||
?.pathSegments()
|
||||
?.toListString()
|
||||
?.let { names -> SirForeignFunction(fqName = names) }
|
||||
?.let { res.add(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<Name>.toListString() = map { it.asString() }
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// FILE: one.kt
|
||||
|
||||
package namespace
|
||||
fun foo(arg1: Int) = println("")
|
||||
fun foo(arg1: Double) = println("")
|
||||
|
||||
// FILE: two.kt
|
||||
|
||||
package other.namespace
|
||||
|
||||
fun foo(arg1: Int) = println("")
|
||||
fun foo(arg1: Double) = println("")
|
||||
@@ -0,0 +1,4 @@
|
||||
[namespace, foo]
|
||||
[namespace, foo]
|
||||
[other, namespace, foo]
|
||||
[other, namespace, foo]
|
||||
@@ -0,0 +1,12 @@
|
||||
// FILE: one.kt
|
||||
|
||||
package com.awesome.namespace
|
||||
fun foo() = println("")
|
||||
|
||||
fun bar() = ""
|
||||
|
||||
// FILE: two.kt
|
||||
|
||||
package com.awesome.other.namespace
|
||||
|
||||
fun foo() = ""
|
||||
@@ -0,0 +1,3 @@
|
||||
[com, awesome, namespace, foo]
|
||||
[com, awesome, namespace, bar]
|
||||
[com, awesome, other, namespace, foo]
|
||||
@@ -0,0 +1,3 @@
|
||||
public fun foo_public() = println("")
|
||||
internal fun foo_internal() = println("")
|
||||
private fun foo_private() = println("")
|
||||
@@ -0,0 +1 @@
|
||||
[foo_public]
|
||||
@@ -0,0 +1 @@
|
||||
fun foo() = println("")
|
||||
@@ -0,0 +1 @@
|
||||
[foo]
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.sir.analysisapi;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
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.analysis.api.GenerateSirAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("native/swift/sir-analysis-api/testData")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SirAnalysisGeneratedTests extends AbstractKotlinSirContextTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInTestData() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/swift/sir-analysis-api/testData"), Pattern.compile("^([^_](.+)).kt$"), null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functions_overload.kt")
|
||||
public void testFunctions_overload() throws Exception {
|
||||
runTest("native/swift/sir-analysis-api/testData/functions_overload.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("namespaced_functions.kt")
|
||||
public void testNamespaced_functions() throws Exception {
|
||||
runTest("native/swift/sir-analysis-api/testData/namespaced_functions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("should_ignore_not_public_functions.kt")
|
||||
public void testShould_ignore_not_public_functions() throws Exception {
|
||||
runTest("native/swift/sir-analysis-api/testData/should_ignore_not_public_functions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple_function.kt")
|
||||
public void testSimple_function() throws Exception {
|
||||
runTest("native/swift/sir-analysis-api/testData/simple_function.kt");
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.sir.analysisapi
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.AnalysisApiFirTestConfiguratorFactory
|
||||
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedTest
|
||||
import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModuleProvider
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.*
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind
|
||||
import org.jetbrains.kotlin.platform.konan.NativePlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.sir.SirForeignFunction
|
||||
import org.jetbrains.kotlin.sir.SirModule
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
open class AbstractKotlinSirContextTest : AbstractKotlinSirContextTestBase() {
|
||||
|
||||
override fun configureTest(builder: TestConfigurationBuilder) {
|
||||
super.configureTest(builder)
|
||||
with(builder) {
|
||||
globalDefaults {
|
||||
targetPlatform = NativePlatforms.unspecifiedNativePlatform
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val configurator: AnalysisApiTestConfigurator
|
||||
get() = AnalysisApiFirTestConfiguratorFactory.createConfigurator(
|
||||
AnalysisApiTestConfiguratorFactoryData(
|
||||
FrontendKind.Fir,
|
||||
TestModuleKind.Source,
|
||||
AnalysisSessionMode.Normal,
|
||||
AnalysisApiMode.Ide
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
abstract class AbstractKotlinSirContextTestBase : AbstractAnalysisApiBasedTest() {
|
||||
override fun doTestByModuleStructure(moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||
val ktFiles = moduleStructure.modules
|
||||
.flatMap { testServices.ktModuleProvider.getModuleFiles(it).filterIsInstance<KtFile>() }
|
||||
|
||||
val module = SirModule()
|
||||
val sirFactory = SirGenerator()
|
||||
ktFiles.forEach { file ->
|
||||
module.declarations += sirFactory.build(file)
|
||||
}
|
||||
val actual = buildString {
|
||||
module.declarations
|
||||
.filterIsInstance<SirForeignFunction>()
|
||||
.forEach {
|
||||
appendLine("${it.fqName}")
|
||||
}
|
||||
}
|
||||
|
||||
testServices.assertions.assertEqualsToTestDataFileSibling(actual, extension = ".sir")
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +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.sir.analysisapi
|
||||
|
||||
import org.jetbrains.kotlin.sir.SirElement
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class FactoryTests {
|
||||
@Test
|
||||
fun smoke() {
|
||||
val expectedString = "Element from factory"
|
||||
val myFactory = object : SirFactory {
|
||||
override fun build(): SirElement {
|
||||
return object : SirElement {
|
||||
override fun toString(): String {
|
||||
return expectedString
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val element = myFactory.build()
|
||||
assertEquals(expectedString, element.toString())
|
||||
}
|
||||
}
|
||||
@@ -9,4 +9,13 @@ package org.jetbrains.kotlin.sir
|
||||
* A marker interface that denotes Swift IR elements.
|
||||
*/
|
||||
interface SirElement {
|
||||
}
|
||||
}
|
||||
|
||||
class SirModule : SirElement {
|
||||
val declarations: MutableList<SirDeclaration> =
|
||||
mutableListOf()
|
||||
}
|
||||
|
||||
interface SirDeclaration
|
||||
|
||||
class SirForeignFunction(val fqName: List<String>) : SirDeclaration
|
||||
|
||||
+2
-1
@@ -400,7 +400,8 @@ include ":plugins:compose-compiler-plugin:compiler",
|
||||
// Swift Export modules
|
||||
include ":native:swift:sir",
|
||||
":native:swift:sir-passes",
|
||||
":native:swift:sir-analysis-api"
|
||||
":native:swift:sir-analysis-api",
|
||||
":generators:sir-analysis-api-generator"
|
||||
|
||||
void intellij(String imlPath) {
|
||||
File imlFile = new File("${rootDir}/intellij/community/plugins/kotlin/${imlPath}")
|
||||
|
||||
Reference in New Issue
Block a user