From 4d9d5ba17872c1aea526002646f4a4c25c027ba9 Mon Sep 17 00:00:00 2001 From: vmishenev Date: Thu, 11 Jan 2024 22:53:18 +0200 Subject: [PATCH 1/4] [K2] Support `[this]` link for extensions --- .../kotlin/symbols/translators/DRIFactory.kt | 25 ++++++- .../src/test/kotlin/markdown/LinkTest.kt | 68 +++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt b/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt index a2cb423aba..cd430f3f05 100644 --- a/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt +++ b/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithTypeParameters -import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType +import org.jetbrains.kotlin.analysis.api.types.* import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -93,6 +93,28 @@ internal fun KtAnalysisSession.getDRIFromValueParameter(symbol: KtValueParameter return funDRI.copy(target = PointingToCallableParameters(index)) } +/** + * @return [DRI] to receiver type + */ +internal fun KtAnalysisSession.getDRIFromReceiverParameter(receiverParameterSymbol: KtReceiverParameterSymbol): DRI = + getDRIFromType(receiverParameterSymbol.type) + +private fun KtAnalysisSession.getDRIFromType(type: KtType): DRI { + return when(type) { + is KtNonErrorClassType -> getDRIFromNonErrorClassType(type) + is KtClassErrorType -> DRI(packageName = "", classNames = "$ERROR_CLASS_NAME $type") + is KtTypeParameterType -> getDRIFromTypeParameter(type.symbol) + is KtDefinitelyNotNullType -> getDRIFromType(type.original) + is KtTypeErrorType -> DRI(packageName = "", classNames = "$ERROR_CLASS_NAME $type") + + is KtDynamicType -> throw IllegalStateException("Dynamic type while creating DRI $type") + is KtCapturedType -> throw IllegalStateException("Non-denotable type while creating DRI $type") + is KtFlexibleType -> throw IllegalStateException("Non-denotable type while creating DRI $type") + is KtIntegerLiteralType -> throw IllegalStateException("Non-denotable type while creating DRI $type") + is KtIntersectionType -> throw IllegalStateException("Non-denotable type while creating DRI $type") + } +} + internal fun KtAnalysisSession.getDRIFromSymbol(symbol: KtSymbol): DRI = when (symbol) { is KtEnumEntrySymbol -> getDRIFromEnumEntry(symbol) @@ -103,6 +125,7 @@ internal fun KtAnalysisSession.getDRIFromSymbol(symbol: KtSymbol): DRI = is KtFunctionLikeSymbol -> getDRIFromFunctionLike(symbol) is KtClassLikeSymbol -> getDRIFromClassLike(symbol) is KtPackageSymbol -> getDRIFromPackage(symbol) + is KtReceiverParameterSymbol -> getDRIFromReceiverParameter(symbol) else -> throw IllegalStateException("Unknown symbol while creating DRI $symbol") } diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt index 97e027b8c0..3facb66677 100644 --- a/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt +++ b/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt @@ -7,12 +7,14 @@ package markdown import org.jetbrains.dokka.analysis.kotlin.markdown.MARKDOWN_ELEMENT_FILE_NAME import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest import org.jetbrains.dokka.links.* +import org.jetbrains.dokka.model.DFunction import org.jetbrains.dokka.model.WithGenerics import org.jetbrains.dokka.model.dfs import org.jetbrains.dokka.model.doc.* import org.jetbrains.dokka.pages.ClasslikePageNode import org.jetbrains.dokka.pages.ContentDRILink import org.jetbrains.dokka.pages.MemberPageNode +import utils.OnlySymbols import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull @@ -121,6 +123,72 @@ class LinkTest : BaseAbstractTest() { } } + @Test + @OnlySymbols("#3207") + fun `link to this keyword with receiver to some class`() { + val configuration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/") + } + } + } + + testInline( + """ + |/src/main/kotlin/Test.kt + |package example + | + |/** + |* Link to [this] + |*/ + |fun String.stop() {} + """.trimMargin(), + configuration + ) { + documentablesMergingStage = { module -> + val fn = module.dfs { it.name == "stop" } as DFunction + val link = fn.documentation.values.single() + .dfs { it is DocumentationLink } as DocumentationLink + + assertEquals(DRI("kotlin", "String"), link.dri) + } + } + } + + @Test + @OnlySymbols("#3207") + fun `link to this keyword with receiver to type parameter`() { + val configuration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/") + } + } + } + + testInline( + """ + |/src/main/kotlin/Test.kt + |package example + | + |/** + |* Link to [this] + |*/ + |fun T.stop() {} + """.trimMargin(), + configuration + ) { + documentablesMergingStage = { module -> + val fn = module.dfs { it.name == "stop" } as DFunction + val link = fn.documentation.values.single() + .dfs { it is DocumentationLink } as DocumentationLink + + assertEquals(fn.generics.first().dri, link.dri) + } + } + } + @Test fun `link with exclamation mark`() { val configuration = dokkaConfiguration { From 31cf3d87836121538bce6cd8845dee5aeb3f4f98 Mon Sep 17 00:00:00 2001 From: vmishenev Date: Thu, 11 Jan 2024 23:11:18 +0200 Subject: [PATCH 2/4] Enable serialization test --- .../dokka/it/gradle/kotlin/SerializationGradleIntegrationTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/dokka-integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/kotlin/SerializationGradleIntegrationTest.kt b/dokka-integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/kotlin/SerializationGradleIntegrationTest.kt index 7b354484c8..561f7fae49 100644 --- a/dokka-integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/kotlin/SerializationGradleIntegrationTest.kt +++ b/dokka-integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/kotlin/SerializationGradleIntegrationTest.kt @@ -45,7 +45,6 @@ class SerializationGradleIntegrationTest : AbstractGradleIntegrationTest(), Test copyAndApplyGitDiff(File("projects", "serialization/serialization.diff")) } - @OnlyDescriptors // failed due to https://github.com/Kotlin/dokka/issues/3207 @ParameterizedTest(name = "{0}") @ArgumentsSource(SerializationBuildVersionsArgumentsProvider::class) fun execute(buildVersions: BuildVersions) { From dfb3f2554c841fcee2ad1f8d9b7fdf4e498ebce1 Mon Sep 17 00:00:00 2001 From: vmishenev Date: Sat, 13 Jan 2024 15:48:30 +0200 Subject: [PATCH 3/4] Refactor and add one more test --- .../kotlin/symbols/translators/DRIFactory.kt | 18 +++++----- .../src/test/kotlin/markdown/LinkTest.kt | 33 +++++++++++++++++++ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt b/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt index cd430f3f05..5001a7cd80 100644 --- a/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt +++ b/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt @@ -97,21 +97,21 @@ internal fun KtAnalysisSession.getDRIFromValueParameter(symbol: KtValueParameter * @return [DRI] to receiver type */ internal fun KtAnalysisSession.getDRIFromReceiverParameter(receiverParameterSymbol: KtReceiverParameterSymbol): DRI = - getDRIFromType(receiverParameterSymbol.type) + getDRIFromReceiverType(receiverParameterSymbol.type) -private fun KtAnalysisSession.getDRIFromType(type: KtType): DRI { +private fun KtAnalysisSession.getDRIFromReceiverType(type: KtType): DRI { return when(type) { is KtNonErrorClassType -> getDRIFromNonErrorClassType(type) - is KtClassErrorType -> DRI(packageName = "", classNames = "$ERROR_CLASS_NAME $type") is KtTypeParameterType -> getDRIFromTypeParameter(type.symbol) - is KtDefinitelyNotNullType -> getDRIFromType(type.original) + is KtDefinitelyNotNullType -> getDRIFromReceiverType(type.original) is KtTypeErrorType -> DRI(packageName = "", classNames = "$ERROR_CLASS_NAME $type") + is KtClassErrorType -> DRI(packageName = "", classNames = "$ERROR_CLASS_NAME $type") - is KtDynamicType -> throw IllegalStateException("Dynamic type while creating DRI $type") - is KtCapturedType -> throw IllegalStateException("Non-denotable type while creating DRI $type") - is KtFlexibleType -> throw IllegalStateException("Non-denotable type while creating DRI $type") - is KtIntegerLiteralType -> throw IllegalStateException("Non-denotable type while creating DRI $type") - is KtIntersectionType -> throw IllegalStateException("Non-denotable type while creating DRI $type") + is KtDynamicType -> throw IllegalStateException("Dynamic receiver is prohibited while creating DRI $type") + is KtCapturedType -> throw IllegalStateException("Unexpected non-denotable type while creating DRI $type") + is KtFlexibleType -> throw IllegalStateException("Unexpected non-denotable type while creating DRI $type") + is KtIntegerLiteralType -> throw IllegalStateException("Unexpected non-denotable type while creating DRI $type") + is KtIntersectionType -> throw IllegalStateException("Unexpected non-denotable type while creating DRI $type") } } diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt index 3facb66677..fd2c5bc510 100644 --- a/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt +++ b/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt @@ -189,6 +189,39 @@ class LinkTest : BaseAbstractTest() { } } + @Test + @OnlySymbols("#3207") + fun `link to this keyword with receiver of DNN-type`() { + val configuration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/") + } + } + } + + testInline( + """ + |/src/main/kotlin/Test.kt + |package example + | + |/** + |* Link to [this] + |*/ + |fun (T&Any).stop() {} + """.trimMargin(), + configuration + ) { + documentablesMergingStage = { module -> + val fn = module.dfs { it.name == "stop" } as DFunction + val link = fn.documentation.values.single() + .dfs { it is DocumentationLink } as DocumentationLink + + assertEquals(fn.generics.first().dri, link.dri) + } + } + } + @Test fun `link with exclamation mark`() { val configuration = dokkaConfiguration { From d81207d2e263fc4fa7e7efde221829f6591f9906 Mon Sep 17 00:00:00 2001 From: vmishenev Date: Tue, 16 Jan 2024 15:09:47 +0200 Subject: [PATCH 4/4] Support dynamic receiver as a possible input --- .../kotlin/symbols/translators/DRIFactory.kt | 2 +- .../src/test/kotlin/markdown/LinkTest.kt | 39 +++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt b/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt index 5001a7cd80..37914dd8d5 100644 --- a/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt +++ b/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt @@ -106,8 +106,8 @@ private fun KtAnalysisSession.getDRIFromReceiverType(type: KtType): DRI { is KtDefinitelyNotNullType -> getDRIFromReceiverType(type.original) is KtTypeErrorType -> DRI(packageName = "", classNames = "$ERROR_CLASS_NAME $type") is KtClassErrorType -> DRI(packageName = "", classNames = "$ERROR_CLASS_NAME $type") + is KtDynamicType -> DRI(packageName = "", classNames = "$ERROR_CLASS_NAME $type") // prohibited by a compiler, but it's a possible input - is KtDynamicType -> throw IllegalStateException("Dynamic receiver is prohibited while creating DRI $type") is KtCapturedType -> throw IllegalStateException("Unexpected non-denotable type while creating DRI $type") is KtFlexibleType -> throw IllegalStateException("Unexpected non-denotable type while creating DRI $type") is KtIntegerLiteralType -> throw IllegalStateException("Unexpected non-denotable type while creating DRI $type") diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt index fd2c5bc510..0fe4983fee 100644 --- a/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt +++ b/dokka-subprojects/plugin-base/src/test/kotlin/markdown/LinkTest.kt @@ -124,7 +124,7 @@ class LinkTest : BaseAbstractTest() { } @Test - @OnlySymbols("#3207") + @OnlySymbols("#3207 - In Dokka K1 [this] has an incorrect link that leads to a page of containing package") fun `link to this keyword with receiver to some class`() { val configuration = dokkaConfiguration { sourceSets { @@ -157,7 +157,7 @@ class LinkTest : BaseAbstractTest() { } @Test - @OnlySymbols("#3207") + @OnlySymbols("#3207 In Dokka K1 [this] has an incorrect link that leads to a page of containing package") fun `link to this keyword with receiver to type parameter`() { val configuration = dokkaConfiguration { sourceSets { @@ -190,7 +190,40 @@ class LinkTest : BaseAbstractTest() { } @Test - @OnlySymbols("#3207") + @OnlySymbols("#3207 In Dokka K1 [this] has an incorrect link that leads to a page of containing package") + fun `link to this keyword with receiver of dynamic that is prohibited by compiler`() { + val configuration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/") + } + } + } + + testInline( + """ + |/src/main/kotlin/Test.kt + |package example + | + |/** + |* Link to [this] + |*/ + |fun dynamic.stop() {} + """.trimMargin(), + configuration + ) { + documentablesMergingStage = { module -> + val fn = module.dfs { it.name == "stop" } as DFunction + val link = fn.documentation.values.single() + .dfs { it is DocumentationLink } as DocumentationLink + + assertEquals(DRI(packageName = "", classNames = " dynamic"), link.dri) + } + } + } + + @Test + @OnlySymbols("#3207 In Dokka K1 [this] has an incorrect link that leads to a page of containing package") fun `link to this keyword with receiver of DNN-type`() { val configuration = dokkaConfiguration { sourceSets {