add Initial support for comments in SIR #KT-65174 Fixed
Merge-request: KT-MR-14007 Merged-by: Artem Olkov <artem.olkov@jetbrains.com>
This commit is contained in:
+11
@@ -7,6 +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.kdoc.psi.api.KDoc
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.sir.*
|
||||
@@ -39,6 +40,9 @@ private class AAFunction(
|
||||
AAKotlinType(name = function.returnType.toString())
|
||||
}
|
||||
|
||||
override val documentation: SirKotlinOrigin.Documentation?
|
||||
get() = originalFunction.docComment?.let { AADocumentation(it) }
|
||||
|
||||
}
|
||||
private data class AAParameter(
|
||||
override val name: String,
|
||||
@@ -48,3 +52,10 @@ private data class AAParameter(
|
||||
private data class AAKotlinType(
|
||||
override val name: String
|
||||
) : SirKotlinOrigin.Type
|
||||
|
||||
private data class AADocumentation(
|
||||
private val kdoc: KDoc
|
||||
) : SirKotlinOrigin.Documentation {
|
||||
override val content: String
|
||||
get() = kdoc.text
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Function foo description
|
||||
*
|
||||
* @param p first Integer to consume
|
||||
* @param p2 second Double to consume
|
||||
* @return Short, constant 1
|
||||
*/
|
||||
fun foo(p: Int, p2: Double): Short = 1
|
||||
@@ -0,0 +1 @@
|
||||
[foo] commented
|
||||
+6
@@ -24,6 +24,12 @@ public class SirAnalysisGeneratedTests extends AbstractKotlinSirContextTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/swift/sir-analysis-api/testData"), Pattern.compile("^(.+)\\.kt$"), null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("function_with_comment.kt")
|
||||
public void testFunction_with_comment() throws Exception {
|
||||
runTest("native/swift/sir-analysis-api/testData/function_with_comment.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functions_overload.kt")
|
||||
public void testFunctions_overload() throws Exception {
|
||||
|
||||
+5
-3
@@ -43,9 +43,11 @@ abstract class AbstractKotlinSirContextTestBase : AbstractAnalysisApiBasedTest()
|
||||
val actual = buildString {
|
||||
module.declarations
|
||||
.filterIsInstance<SirForeignFunction>()
|
||||
.forEach {
|
||||
val function = it.origin as SirKotlinOrigin.Function
|
||||
appendLine("${function.path}")
|
||||
.forEach { sirForeignFunction ->
|
||||
val function = sirForeignFunction.origin as SirKotlinOrigin.Function
|
||||
val functionPath = "${function.path}"
|
||||
val isCommented = function.documentation?.let { " commented" } ?: ""
|
||||
appendLine("$functionPath$isCommented")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -41,6 +41,8 @@ public class ForeignIntoSwiftFunctionTranslationPass : SirPass<SirElement, Nothi
|
||||
kotlinOrigin.parameters.mapTo(parameters) { it.toSir() }
|
||||
|
||||
returnType = kotlinOrigin.returnType.toSir()
|
||||
|
||||
documentation = kotlinOrigin.documentation?.content
|
||||
}.apply {
|
||||
parent = function.parent
|
||||
}
|
||||
|
||||
@@ -6,14 +6,10 @@
|
||||
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.*
|
||||
import org.jetbrains.kotlin.sir.builder.*
|
||||
import org.jetbrains.kotlin.sir.constants.*
|
||||
import org.jetbrains.kotlin.sir.mock.MockDocumentation
|
||||
import org.jetbrains.kotlin.sir.mock.MockFunction
|
||||
import org.jetbrains.kotlin.sir.mock.MockKotlinType
|
||||
import org.jetbrains.kotlin.sir.mock.MockParameter
|
||||
@@ -149,4 +145,51 @@ class SirPassTests {
|
||||
)
|
||||
assertSirFunctionsEquals(actual = result, expected = exp)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `foreign toplevel function with kdoc should be translated`() {
|
||||
val module = buildModule {
|
||||
name = "demo"
|
||||
}
|
||||
val mySirElement = buildForeignFunction {
|
||||
origin = MockFunction(
|
||||
fqName = FqName.fromSegments(listOf("foo")),
|
||||
parameters = emptyList(),
|
||||
returnType = MockKotlinType(BOOLEAN),
|
||||
documentation = MockDocumentation(
|
||||
"""
|
||||
/**
|
||||
* Function foo description
|
||||
*
|
||||
* @param p first Integer to consume
|
||||
* @param p2 second Double to consume
|
||||
* @return empty String
|
||||
*/
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
visibility = SirVisibility.PUBLIC
|
||||
}
|
||||
mySirElement.parent = module
|
||||
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 = module,
|
||||
isStatic = false,
|
||||
documentation = """
|
||||
/**
|
||||
* Function foo description
|
||||
*
|
||||
* @param p first Integer to consume
|
||||
* @param p2 second Double to consume
|
||||
* @return empty String
|
||||
*/
|
||||
""".trimIndent()
|
||||
)
|
||||
assertSirFunctionsEquals(actual = result, expected = exp)
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -29,4 +29,8 @@ fun assertSirFunctionsEquals(expected: SirFunction, actual: SirFunction) {
|
||||
actual = actual.isStatic,
|
||||
expected = expected.isStatic
|
||||
)
|
||||
assertEquals(
|
||||
actual = actual.documentation,
|
||||
expected = expected.documentation
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ class MockSirFunction(
|
||||
override val name: String,
|
||||
override val parameters: List<SirParameter>,
|
||||
override val returnType: SirType,
|
||||
override var documentation: String? = null,
|
||||
) : SirFunction() {
|
||||
override fun <R, D> acceptChildren(visitor: SirVisitor<R, D>, data: D) = Unit
|
||||
override fun <D> transformChildren(transformer: SirTransformer<D>, data: D) = Unit
|
||||
|
||||
@@ -29,6 +29,7 @@ public class SirAsSwiftSourcesPrinter(private val printer: SmartPrinter) : SirVi
|
||||
}
|
||||
|
||||
override fun visitFunction(function: SirFunction): Unit = with(printer) {
|
||||
function.documentation?.let { println(it) }
|
||||
print(
|
||||
function.visibility.takeIf { it != SirVisibility.INTERNAL }?.let { "${it.swift} " } ?: "",
|
||||
if (function.isStatic) { "static " } else { "" },
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
/// Function foo description.
|
||||
/// - Parameters:
|
||||
/// - p: first Integer to consume
|
||||
/// - Returns: Bool
|
||||
public func foo(
|
||||
p: Swift.Int64
|
||||
) -> Swift.Bool {
|
||||
fatalError()
|
||||
}
|
||||
+34
@@ -255,6 +255,40 @@ class SirAsSwiftSourcesPrinterTests {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should print DocC comment`() {
|
||||
|
||||
val module = buildModule {
|
||||
name = "Test"
|
||||
declarations.add(
|
||||
buildFunction {
|
||||
origin = SirOrigin.Unknown
|
||||
isStatic = false
|
||||
visibility = SirVisibility.PUBLIC
|
||||
name = "foo"
|
||||
parameters.add(
|
||||
SirParameter(
|
||||
argumentName = "p",
|
||||
type = SirNominalType(SirSwiftModule.int64)
|
||||
)
|
||||
)
|
||||
returnType = SirNominalType(SirSwiftModule.bool)
|
||||
documentation = """
|
||||
/// Function foo description.
|
||||
/// - Parameters:
|
||||
/// - p: first Integer to consume
|
||||
/// - Returns: Bool
|
||||
""".trimIndent()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
runTest(
|
||||
module,
|
||||
"testData/commented_function"
|
||||
)
|
||||
}
|
||||
|
||||
private fun runTest(module: SirModule, goldenDataFile: String) {
|
||||
val expectedSwiftSrc = File(KtTestUtil.getHomeDirectory()).resolve("$goldenDataFile.golden.swift")
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ abstract class SirFunction : SirElementBase(), SirCallable {
|
||||
abstract val parameters: List<SirParameter>
|
||||
abstract val returnType: SirType
|
||||
abstract var body: SirFunctionBody?
|
||||
abstract var documentation: String?
|
||||
|
||||
override fun <R, D> accept(visitor: SirVisitor<R, D>, data: D): R =
|
||||
visitor.visitFunction(this, data)
|
||||
|
||||
@@ -23,6 +23,7 @@ class SirFunctionBuilder {
|
||||
val parameters: MutableList<SirParameter> = mutableListOf()
|
||||
lateinit var returnType: SirType
|
||||
var body: SirFunctionBody? = null
|
||||
var documentation: String? = null
|
||||
|
||||
fun build(): SirFunction {
|
||||
return SirFunctionImpl(
|
||||
@@ -33,6 +34,7 @@ class SirFunctionBuilder {
|
||||
parameters,
|
||||
returnType,
|
||||
body,
|
||||
documentation,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -59,5 +61,6 @@ inline fun buildFunctionCopy(original: SirFunction, init: SirFunctionBuilder.()
|
||||
copyBuilder.parameters.addAll(original.parameters)
|
||||
copyBuilder.returnType = original.returnType
|
||||
copyBuilder.body = original.body
|
||||
copyBuilder.documentation = original.documentation
|
||||
return copyBuilder.apply(init).build()
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ internal class SirFunctionImpl(
|
||||
override val parameters: MutableList<SirParameter>,
|
||||
override val returnType: SirType,
|
||||
override var body: SirFunctionBody?,
|
||||
override var documentation: String?,
|
||||
) : SirFunction() {
|
||||
override lateinit var parent: SirDeclarationParent
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ sealed interface SirKotlinOrigin : SirOrigin.Foreign {
|
||||
get() = fqName.pathSegments().map { it.asString() }
|
||||
|
||||
interface Function : SirKotlinOrigin {
|
||||
val documentation: Documentation?
|
||||
val parameters: List<Parameter>
|
||||
val returnType: Type
|
||||
}
|
||||
@@ -26,4 +27,8 @@ sealed interface SirKotlinOrigin : SirOrigin.Foreign {
|
||||
interface Type {
|
||||
val name: String
|
||||
}
|
||||
|
||||
interface Documentation {
|
||||
val content: String
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ package org.jetbrains.kotlin.sir.mock
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.sir.SirKotlinOrigin
|
||||
import org.jetbrains.kotlin.sir.SirOrigin
|
||||
|
||||
data class MockFunction(
|
||||
override val fqName: FqName,
|
||||
override val parameters: List<SirKotlinOrigin.Parameter>,
|
||||
override val returnType: SirKotlinOrigin.Type,
|
||||
override val documentation: SirKotlinOrigin.Documentation? = null,
|
||||
) : SirKotlinOrigin.Function
|
||||
|
||||
data class MockParameter(
|
||||
@@ -22,3 +24,5 @@ data class MockParameter(
|
||||
data class MockKotlinType(
|
||||
override val name: String
|
||||
) : SirKotlinOrigin.Type
|
||||
|
||||
data class MockDocumentation(override val content: String) : SirKotlinOrigin.Documentation
|
||||
|
||||
@@ -17,7 +17,7 @@ typealias Model = org.jetbrains.kotlin.generators.tree.Model<Element>
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val generationPath = args.firstOrNull()?.let { File(it) }
|
||||
?: File("../../tree/gen").canonicalFile
|
||||
?: File("./native/swift/sir/gen/").canonicalFile
|
||||
val model = SwiftIrTree.build()
|
||||
generateTree(
|
||||
generationPath,
|
||||
|
||||
+3
-1
@@ -87,6 +87,8 @@ object SwiftIrTree : AbstractSwiftIrTreeBuilder() {
|
||||
+listField("parameters", parameterType)
|
||||
+field("returnType", typeType)
|
||||
+field("body", functionBodyType, nullable = true, mutable = true)
|
||||
|
||||
+field(name = "documentation", string, nullable = true, mutable = true)
|
||||
}
|
||||
|
||||
val foreignFunction by element {
|
||||
@@ -96,4 +98,4 @@ object SwiftIrTree : AbstractSwiftIrTreeBuilder() {
|
||||
|
||||
visitorParameterName = "function"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user