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.analyze
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
|
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.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.sir.*
|
import org.jetbrains.kotlin.sir.*
|
||||||
@@ -39,6 +40,9 @@ private class AAFunction(
|
|||||||
AAKotlinType(name = function.returnType.toString())
|
AAKotlinType(name = function.returnType.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val documentation: SirKotlinOrigin.Documentation?
|
||||||
|
get() = originalFunction.docComment?.let { AADocumentation(it) }
|
||||||
|
|
||||||
}
|
}
|
||||||
private data class AAParameter(
|
private data class AAParameter(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
@@ -48,3 +52,10 @@ private data class AAParameter(
|
|||||||
private data class AAKotlinType(
|
private data class AAKotlinType(
|
||||||
override val name: String
|
override val name: String
|
||||||
) : SirKotlinOrigin.Type
|
) : 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);
|
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
|
@Test
|
||||||
@TestMetadata("functions_overload.kt")
|
@TestMetadata("functions_overload.kt")
|
||||||
public void testFunctions_overload() throws Exception {
|
public void testFunctions_overload() throws Exception {
|
||||||
|
|||||||
+5
-3
@@ -43,9 +43,11 @@ abstract class AbstractKotlinSirContextTestBase : AbstractAnalysisApiBasedTest()
|
|||||||
val actual = buildString {
|
val actual = buildString {
|
||||||
module.declarations
|
module.declarations
|
||||||
.filterIsInstance<SirForeignFunction>()
|
.filterIsInstance<SirForeignFunction>()
|
||||||
.forEach {
|
.forEach { sirForeignFunction ->
|
||||||
val function = it.origin as SirKotlinOrigin.Function
|
val function = sirForeignFunction.origin as SirKotlinOrigin.Function
|
||||||
appendLine("${function.path}")
|
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() }
|
kotlinOrigin.parameters.mapTo(parameters) { it.toSir() }
|
||||||
|
|
||||||
returnType = kotlinOrigin.returnType.toSir()
|
returnType = kotlinOrigin.returnType.toSir()
|
||||||
|
|
||||||
|
documentation = kotlinOrigin.documentation?.content
|
||||||
}.apply {
|
}.apply {
|
||||||
parent = function.parent
|
parent = function.parent
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.sir.passes
|
package org.jetbrains.kotlin.sir.passes
|
||||||
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.sir.SirFunction
|
import org.jetbrains.kotlin.sir.*
|
||||||
import org.jetbrains.kotlin.sir.SirNominalType
|
import org.jetbrains.kotlin.sir.builder.*
|
||||||
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.*
|
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.MockFunction
|
||||||
import org.jetbrains.kotlin.sir.mock.MockKotlinType
|
import org.jetbrains.kotlin.sir.mock.MockKotlinType
|
||||||
import org.jetbrains.kotlin.sir.mock.MockParameter
|
import org.jetbrains.kotlin.sir.mock.MockParameter
|
||||||
@@ -149,4 +145,51 @@ class SirPassTests {
|
|||||||
)
|
)
|
||||||
assertSirFunctionsEquals(actual = result, expected = exp)
|
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,
|
actual = actual.isStatic,
|
||||||
expected = expected.isStatic
|
expected = expected.isStatic
|
||||||
)
|
)
|
||||||
|
assertEquals(
|
||||||
|
actual = actual.documentation,
|
||||||
|
expected = expected.documentation
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class MockSirFunction(
|
|||||||
override val name: String,
|
override val name: String,
|
||||||
override val parameters: List<SirParameter>,
|
override val parameters: List<SirParameter>,
|
||||||
override val returnType: SirType,
|
override val returnType: SirType,
|
||||||
|
override var documentation: String? = null,
|
||||||
) : SirFunction() {
|
) : SirFunction() {
|
||||||
override fun <R, D> acceptChildren(visitor: SirVisitor<R, D>, data: D) = Unit
|
override fun <R, D> acceptChildren(visitor: SirVisitor<R, D>, data: D) = Unit
|
||||||
override fun <D> transformChildren(transformer: SirTransformer<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) {
|
override fun visitFunction(function: SirFunction): Unit = with(printer) {
|
||||||
|
function.documentation?.let { println(it) }
|
||||||
print(
|
print(
|
||||||
function.visibility.takeIf { it != SirVisibility.INTERNAL }?.let { "${it.swift} " } ?: "",
|
function.visibility.takeIf { it != SirVisibility.INTERNAL }?.let { "${it.swift} " } ?: "",
|
||||||
if (function.isStatic) { "static " } else { "" },
|
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) {
|
private fun runTest(module: SirModule, goldenDataFile: String) {
|
||||||
val expectedSwiftSrc = File(KtTestUtil.getHomeDirectory()).resolve("$goldenDataFile.golden.swift")
|
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 parameters: List<SirParameter>
|
||||||
abstract val returnType: SirType
|
abstract val returnType: SirType
|
||||||
abstract var body: SirFunctionBody?
|
abstract var body: SirFunctionBody?
|
||||||
|
abstract var documentation: String?
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: SirVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(visitor: SirVisitor<R, D>, data: D): R =
|
||||||
visitor.visitFunction(this, data)
|
visitor.visitFunction(this, data)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class SirFunctionBuilder {
|
|||||||
val parameters: MutableList<SirParameter> = mutableListOf()
|
val parameters: MutableList<SirParameter> = mutableListOf()
|
||||||
lateinit var returnType: SirType
|
lateinit var returnType: SirType
|
||||||
var body: SirFunctionBody? = null
|
var body: SirFunctionBody? = null
|
||||||
|
var documentation: String? = null
|
||||||
|
|
||||||
fun build(): SirFunction {
|
fun build(): SirFunction {
|
||||||
return SirFunctionImpl(
|
return SirFunctionImpl(
|
||||||
@@ -33,6 +34,7 @@ class SirFunctionBuilder {
|
|||||||
parameters,
|
parameters,
|
||||||
returnType,
|
returnType,
|
||||||
body,
|
body,
|
||||||
|
documentation,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,5 +61,6 @@ inline fun buildFunctionCopy(original: SirFunction, init: SirFunctionBuilder.()
|
|||||||
copyBuilder.parameters.addAll(original.parameters)
|
copyBuilder.parameters.addAll(original.parameters)
|
||||||
copyBuilder.returnType = original.returnType
|
copyBuilder.returnType = original.returnType
|
||||||
copyBuilder.body = original.body
|
copyBuilder.body = original.body
|
||||||
|
copyBuilder.documentation = original.documentation
|
||||||
return copyBuilder.apply(init).build()
|
return copyBuilder.apply(init).build()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ internal class SirFunctionImpl(
|
|||||||
override val parameters: MutableList<SirParameter>,
|
override val parameters: MutableList<SirParameter>,
|
||||||
override val returnType: SirType,
|
override val returnType: SirType,
|
||||||
override var body: SirFunctionBody?,
|
override var body: SirFunctionBody?,
|
||||||
|
override var documentation: String?,
|
||||||
) : SirFunction() {
|
) : SirFunction() {
|
||||||
override lateinit var parent: SirDeclarationParent
|
override lateinit var parent: SirDeclarationParent
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ sealed interface SirKotlinOrigin : SirOrigin.Foreign {
|
|||||||
get() = fqName.pathSegments().map { it.asString() }
|
get() = fqName.pathSegments().map { it.asString() }
|
||||||
|
|
||||||
interface Function : SirKotlinOrigin {
|
interface Function : SirKotlinOrigin {
|
||||||
|
val documentation: Documentation?
|
||||||
val parameters: List<Parameter>
|
val parameters: List<Parameter>
|
||||||
val returnType: Type
|
val returnType: Type
|
||||||
}
|
}
|
||||||
@@ -26,4 +27,8 @@ sealed interface SirKotlinOrigin : SirOrigin.Foreign {
|
|||||||
interface Type {
|
interface Type {
|
||||||
val name: String
|
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.name.FqName
|
||||||
import org.jetbrains.kotlin.sir.SirKotlinOrigin
|
import org.jetbrains.kotlin.sir.SirKotlinOrigin
|
||||||
|
import org.jetbrains.kotlin.sir.SirOrigin
|
||||||
|
|
||||||
data class MockFunction(
|
data class MockFunction(
|
||||||
override val fqName: FqName,
|
override val fqName: FqName,
|
||||||
override val parameters: List<SirKotlinOrigin.Parameter>,
|
override val parameters: List<SirKotlinOrigin.Parameter>,
|
||||||
override val returnType: SirKotlinOrigin.Type,
|
override val returnType: SirKotlinOrigin.Type,
|
||||||
|
override val documentation: SirKotlinOrigin.Documentation? = null,
|
||||||
) : SirKotlinOrigin.Function
|
) : SirKotlinOrigin.Function
|
||||||
|
|
||||||
data class MockParameter(
|
data class MockParameter(
|
||||||
@@ -22,3 +24,5 @@ data class MockParameter(
|
|||||||
data class MockKotlinType(
|
data class MockKotlinType(
|
||||||
override val name: String
|
override val name: String
|
||||||
) : SirKotlinOrigin.Type
|
) : 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>) {
|
fun main(args: Array<String>) {
|
||||||
val generationPath = args.firstOrNull()?.let { File(it) }
|
val generationPath = args.firstOrNull()?.let { File(it) }
|
||||||
?: File("../../tree/gen").canonicalFile
|
?: File("./native/swift/sir/gen/").canonicalFile
|
||||||
val model = SwiftIrTree.build()
|
val model = SwiftIrTree.build()
|
||||||
generateTree(
|
generateTree(
|
||||||
generationPath,
|
generationPath,
|
||||||
|
|||||||
+3
-1
@@ -87,6 +87,8 @@ object SwiftIrTree : AbstractSwiftIrTreeBuilder() {
|
|||||||
+listField("parameters", parameterType)
|
+listField("parameters", parameterType)
|
||||||
+field("returnType", typeType)
|
+field("returnType", typeType)
|
||||||
+field("body", functionBodyType, nullable = true, mutable = true)
|
+field("body", functionBodyType, nullable = true, mutable = true)
|
||||||
|
|
||||||
|
+field(name = "documentation", string, nullable = true, mutable = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
val foreignFunction by element {
|
val foreignFunction by element {
|
||||||
@@ -96,4 +98,4 @@ object SwiftIrTree : AbstractSwiftIrTreeBuilder() {
|
|||||||
|
|
||||||
visitorParameterName = "function"
|
visitorParameterName = "function"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user