diff --git a/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts b/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts index ccaf0633c60..05f1158fe4f 100644 --- a/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts +++ b/native/objcexport-header-generator/impl/analysis-api/build.gradle.kts @@ -10,8 +10,9 @@ kotlin { } dependencies { - api(project(":native:objcexport-header-generator")) api(project(":analysis:analysis-api")) + api(project(":compiler:psi")) + api(project(":native:objcexport-header-generator")) testImplementation(projectTests(":native:objcexport-header-generator")) testApi(project(":analysis:analysis-api-standalone")) diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportNamer.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportNamer.kt index de303ff04c1..5a0dccbb3e1 100644 --- a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportNamer.kt +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/KtObjCExportNamer.kt @@ -20,7 +20,7 @@ interface KtObjCExportNamer { fun getPropertyName(symbol: KtPropertySymbol): ObjCExportPropertyName } -fun ObjCExportNamer(): KtObjCExportNamer { +fun KtObjCExportNamer(): KtObjCExportNamer { return ObjCExportNamerImpl() } diff --git a/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/analysisApiUtils/findKdocString.kt b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/analysisApiUtils/findKdocString.kt new file mode 100644 index 00000000000..2eca30d1fdd --- /dev/null +++ b/native/objcexport-header-generator/impl/analysis-api/src/org/jetbrains/kotlin/objcexport/analysisApiUtils/findKdocString.kt @@ -0,0 +1,23 @@ +/* + * 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.objcexport.analysisApiUtils + +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtPrimaryConstructor + +internal fun KtSymbol.findKDocString(): String? { + val psi = psi + if (psi is KtDeclaration) { + if (psi is KtPrimaryConstructor) + return null // to be rendered with class itself + val kdoc = psi.docComment + if (kdoc != null) { + return kdoc.getDefaultSection().parent.text + } + } + return null +} diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/AnalysisApiAssertions.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/AnalysisApiAssertions.kt new file mode 100644 index 00000000000..008b4f16ce6 --- /dev/null +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/testUtils/AnalysisApiAssertions.kt @@ -0,0 +1,45 @@ +/* + * 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.objcexport.testUtils + +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.scopes.KtScope +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtFile +import kotlin.test.fail + +context(KtAnalysisSession) +fun KtFile.getClassOrFail(name: String): KtNamedClassOrObjectSymbol { + return getFileSymbol().getFileScope().getClassOrFail(name) +} + +context(KtAnalysisSession) +fun KtScope.getClassOrFail(name: String): KtNamedClassOrObjectSymbol { + val allSymbols = getClassifierSymbols(Name.identifier(name)).toList() + if (allSymbols.isEmpty()) fail("Missing class '$name'") + if (allSymbols.size > 1) fail("Found multiple classes with name '$name'") + val classifier = allSymbols.single() + if (classifier !is KtNamedClassOrObjectSymbol) fail("$classifier is not a named class or object") + return classifier +} + +context(KtAnalysisSession) +fun KtFile.getFunctionOrFail(name: String): KtFunctionSymbol { + return getFileSymbol().getFileScope().getFunctionOrFail(name) +} + +context(KtAnalysisSession) +fun KtScope.getFunctionOrFail(name: String): KtFunctionSymbol { + val allSymbols = getCallableSymbols(Name.identifier(name)).toList() + if (allSymbols.isEmpty()) fail("Missing function '$name'") + if (allSymbols.size > 1) fail("Found multiple functions with name '$name'") + val symbol = allSymbols.single() + if (symbol !is KtFunctionSymbol) fail("$symbol is not a function") + return symbol +} + diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/FindKdocStringTest.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/FindKdocStringTest.kt new file mode 100644 index 00000000000..aa565e8464d --- /dev/null +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/FindKdocStringTest.kt @@ -0,0 +1,66 @@ +/* + * 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.objcexport.tests + +import org.jetbrains.kotlin.analysis.api.analyze +import org.jetbrains.kotlin.objcexport.analysisApiUtils.findKDocString +import org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysis +import org.jetbrains.kotlin.objcexport.testUtils.getClassOrFail +import org.jetbrains.kotlin.objcexport.testUtils.getFunctionOrFail +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class FindKdocStringTest( + private val inlineSourceCodeAnalysis: InlineSourceCodeAnalysis, +) { + @Test + fun `test - simple class`() { + val ktFile = inlineSourceCodeAnalysis.createKtFile( + """ + /** + * Kdoc for 'Foo' + */ + class Foo + """.trimIndent() + ) + + analyze(ktFile) { + val foo = ktFile.getClassOrFail("Foo") + assertEquals( + """ + /** + * Kdoc for 'Foo' + */ + """.trimIndent(), + foo.findKDocString() + ) + } + } + + @Test + fun `test - simple function`() { + val ktFile = inlineSourceCodeAnalysis.createKtFile( + """ + /** + * Kdoc for 'foo' + */ + fun foo() = Unit + """.trimIndent() + ) + + analyze(ktFile) { + val foo = ktFile.getFunctionOrFail("foo") + assertEquals( + """ + /** + * Kdoc for 'foo' + */ + """.trimIndent(), + foo.findKDocString() + ) + } + } +} \ No newline at end of file diff --git a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtObjCExportNamerTest.kt b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtObjCExportNamerTest.kt index d80bcf14338..a6e9413863f 100644 --- a/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtObjCExportNamerTest.kt +++ b/native/objcexport-header-generator/impl/analysis-api/test/org/jetbrains/kotlin/objcexport/tests/KtObjCExportNamerTest.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportClassOrProtocolName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.objcexport.ObjCExportNamer +import org.jetbrains.kotlin.objcexport.KtObjCExportNamer import org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysis import org.junit.jupiter.api.Test import kotlin.test.assertEquals @@ -18,7 +18,7 @@ class KtObjCExportNamerTest( private val inlineSourceCodeAnalysis: InlineSourceCodeAnalysis, ) { - private val namer = ObjCExportNamer() + private val namer = KtObjCExportNamer() @Test fun `test - simple class`() {