diff options
author | Ignat Beresnev <ignat.beresnev@jetbrains.com> | 2023-11-10 11:46:54 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-10 11:46:54 +0100 |
commit | 8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch) | |
tree | 1b915207b2b9f61951ddbf0ff2e687efd053d555 /dokka-subprojects/plugin-base/src/test/kotlin/pageMerger | |
parent | a44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff) | |
download | dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.gz dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.bz2 dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.zip |
Restructure the project to utilize included builds (#3174)
* Refactor and simplify artifact publishing
* Update Gradle to 8.4
* Refactor and simplify convention plugins and build scripts
Fixes #3132
---------
Co-authored-by: Adam <897017+aSemy@users.noreply.github.com>
Co-authored-by: Oleg Yukhnevich <whyoleg@gmail.com>
Diffstat (limited to 'dokka-subprojects/plugin-base/src/test/kotlin/pageMerger')
-rw-r--r-- | dokka-subprojects/plugin-base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt new file mode 100644 index 00000000..983f73ff --- /dev/null +++ b/dokka-subprojects/plugin-base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt @@ -0,0 +1,465 @@ +/* + * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package pageMerger + +import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest +import org.jetbrains.dokka.model.dfs +import org.jetbrains.dokka.model.withDescendants +import org.jetbrains.dokka.pages.* +import org.junit.jupiter.api.RepeatedTest +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class PageNodeMergerTest : BaseAbstractTest() { + + private val defaultConfiguration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/main/kotlin") + } + } + } + + @Test + fun sameNameStrategyTest() { + testInline( + """ + |/src/main/kotlin/pageMerger/Test.kt + |package pageMerger + | + |fun testT(): Int = 1 + |fun testT(i: Int): Int = i + | + |object Test { + | fun test(): String = "" + | fun test(str: String): String = str + |} + """.trimMargin(), + defaultConfiguration + ) { + pagesTransformationStage = { + val allChildren = it.childrenRec().filterIsInstance<ContentPage>() + val testT = allChildren.filter { it.name == "testT" } + val test = allChildren.filter { it.name == "test" } + + assertTrue(testT.size == 1, "There can be only one testT page") + assertTrue(testT.first().dri.size == 2, "testT page should have 2 DRI, but has ${testT.first().dri.size}") + + assertTrue(test.size == 1, "There can be only one test page") + assertTrue(test.first().dri.size == 2, "test page should have 2 DRI, but has ${test.first().dri.size}") + } + } + } + + @Ignore("TODO: reenable when we have infrastructure for turning off extensions") + @Test + fun defaultStrategyTest() { + val strList: MutableList<String> = mutableListOf() + + testInline( + """ + |/src/main/kotlin/pageMerger/Test.kt + |package pageMerger + | + |fun testT(): Int = 1 + |fun testT(i: Int): Int = i + | + |object Test { + | fun test(): String = "" + | fun test(str: String): String = str + |} + """.trimMargin(), + defaultConfiguration + ) { + pagesTransformationStage = { root -> + val allChildren = root.childrenRec().filterIsInstance<ContentPage>() + val testT = allChildren.filter { it.name == "testT" } + val test = allChildren.filter { it.name == "test" } + + assertTrue(testT.size == 1, "There can be only one testT page") + assertTrue(testT.first().dri.size == 1, "testT page should have single DRI, but has ${testT.first().dri.size}") + + assertTrue(test.size == 1, "There can be only one test page") + assertTrue(test.first().dri.size == 1, "test page should have single DRI, but has ${test.first().dri.size}") + + assertTrue(strList.count() == 2, "Expected 2 warnings, got ${strList.count()}") + } + } + } + + fun PageNode.childrenRec(): List<PageNode> = listOf(this) + children.flatMap { it.childrenRec() } + + + @Test + fun `should not be merged`() { + + val configuration = dokkaConfiguration { + moduleName = "example" + sourceSets { + val common = sourceSet { + name = "common" + displayName = "common" + analysisPlatform = "common" + sourceRoots = listOf("src/commonMain/kotlin/pageMerger/Test.kt") + } + sourceSet { + name = "js" + displayName = "js" + analysisPlatform = "js" + dependentSourceSets = setOf(common.value.sourceSetID) + sourceRoots = listOf("src/jsMain/kotlin/pageMerger/Test.kt") + } + sourceSet { + name = "jvm" + displayName = "jvm" + analysisPlatform = "jvm" + dependentSourceSets = setOf(common.value.sourceSetID) + sourceRoots = listOf("src/jvmMain/kotlin/pageMerger/Test.kt") + } + } + } + + testInline( + """ + |/src/commonMain/kotlin/pageMerger/Test.kt + |package pageMerger + | + |/src/jsMain/kotlin/pageMerger/Test.kt + |package pageMerger + | + |annotation class DoNotMerge + | + |/src/jvmMain/kotlin/pageMerger/Test.kt + |package pageMerger + | + |annotation class DoNotMerge + """.trimMargin(), + configuration + ) { + pagesTransformationStage = { + println(it) + val allChildren = it.childrenRec().filterIsInstance<ClasslikePageNode>() + val jvmClass = allChildren.filter { it.name == "[jvm]DoNotMerge" } + val jsClass = allChildren.filter { it.name == "[js]DoNotMerge" } + val noClass = allChildren.filter { it.name == "DoNotMerge" } + assertTrue(jvmClass.size == 1, "There can be only one DoNotMerge(jvm) page") + assertTrue( + jvmClass.first().documentables.firstOrNull()?.sourceSets?.single()?.analysisPlatform?.key == "jvm", + "[jvm]DoNotMerge should have only jvm sources" + ) + + assertTrue(jsClass.size == 1, "There can be only one DoNotMerge(js) page") + assertTrue( + jsClass.first().documentables.firstOrNull()?.sourceSets?.single()?.analysisPlatform?.key == "js", + "[js]DoNotMerge should have only js sources" + ) + + assertTrue(noClass.isEmpty(), "There can't be any DoNotMerge page") + } + } + } + + @RepeatedTest(3) + fun `should deterministically render same name property extensions`() { + testInline( + """ + |/src/main/kotlin/test/Test.kt + |package test + | + |class ExtensionReceiver + | + |/** + | * Top level val extension + | */ + |val ExtensionReceiver.foo: String get() = "bar" + | + |class Obj { + | companion object { + | /** + | * Companion val extension + | */ + | val ExtensionReceiver.foo: String get() = "bar" + | } + |} + | + |/src/main/kotlin/test/nestedpackage/Pckg.kt + |package test.nestedpackage + | + |import test.ExtensionReceiver + | + |/** + | * From nested package int val extension + | */ + |val ExtensionReceiver.foo: Int get() = 42 + """.trimMargin(), + defaultConfiguration + ) { + renderingStage = { rootPageNode, _ -> + val extensions = rootPageNode.findDivergencesOfClass("ExtensionReceiver", ContentKind.Extensions) + + extensions.assertContainsKDocsInOrder( + "Top level val extension", + "Companion val extension", + "From nested package int val extension" + ) + } + } + } + + @RepeatedTest(3) + fun `should deterministically render parameterless same name function extensions`() { + testInline( + """ + |/src/main/kotlin/test/Test.kt + |package test + | + |class ExtensionReceiver + | + |/** + | * Top level fun extension + | */ + |fun ExtensionReceiver.bar(): String = "bar" + | + |class Obj { + | + | companion object { + | /** + | * Companion fun extension + | */ + | fun ExtensionReceiver.bar(): String = "bar" + | } + |} + | + |/src/main/kotlin/test/nestedpackage/Pckg.kt + |package test.nestedpackage + | + |import test.ExtensionReceiver + | + |/** + | * From nested package fun extension + | */ + |fun ExtensionReceiver.bar(): String = "bar" + """.trimMargin(), + defaultConfiguration + ) { + renderingStage = { rootPageNode, _ -> + val extensions = rootPageNode.findDivergencesOfClass("ExtensionReceiver", ContentKind.Extensions) + extensions.assertContainsKDocsInOrder( + "Top level fun extension", + "Companion fun extension", + "From nested package fun extension" + ) + } + } + } + + @RepeatedTest(3) + fun `should deterministically render same name function extensions with parameters`() { + testInline( + """ + |/src/main/kotlin/test/Test.kt + |package test + | + |class ExtensionReceiver + | + |/** + | * Top level fun extension with one string param + | */ + |fun ExtensionReceiver.bar(one: String): String = "bar" + | + |/** + | * Top level fun extension with one int param + | */ + |fun ExtensionReceiver.bar(one: Int): Int = 42 + | + |class Obj { + | + | companion object { + | /** + | * Companion fun extension with two params + | */ + | fun ExtensionReceiver.bar(one: String, two: String): String = "bar" + | } + |} + | + |/src/main/kotlin/test/nestedpackage/Pckg.kt + |package test.nestedpackage + | + |import test.ExtensionReceiver + | + |/** + | * From nested package fun extension with two params + | */ + |fun ExtensionReceiver.bar(one: String, two: String): String = "bar" + | + |/** + | * From nested package fun extension with three params + | */ + |fun ExtensionReceiver.bar(one: String, two: String, three: String): String = "bar" + | + |/** + | * From nested package fun extension with four params + | */ + |fun ExtensionReceiver.bar(one: String, two: String, three: String, four: String): String = "bar" + """.trimMargin(), + defaultConfiguration + ) { + renderingStage = { rootPageNode, _ -> + val extensions = rootPageNode.findDivergencesOfClass("ExtensionReceiver", ContentKind.Extensions) + extensions.assertContainsKDocsInOrder( + "Top level fun extension with one int param", + "Top level fun extension with one string param", + "Companion fun extension with two params", + "From nested package fun extension with two params", + "From nested package fun extension with three params", + "From nested package fun extension with four params" + ) + } + } + } + + @RepeatedTest(3) + fun `should deterministically render same name function extensions with different receiver and return type`() { + testInline( + """ + |/src/main/kotlin/test/Test.kt + |package test + | + |/** + | * Top level fun extension string + | */ + |fun Int.bar(): String = "bar" + | + |/** + | * Top level fun extension int + | */ + |fun String.bar(): Int = 42 + """.trimMargin(), + defaultConfiguration + ) { + renderingStage = { rootPageNode, _ -> + val packageFunctionBlocks = rootPageNode.findPackageFunctionBlocks(packageName = "test") + assertEquals(1, packageFunctionBlocks.size, "Expected to find only one group for the functions") + + val functionsBlock = packageFunctionBlocks[0] + functionsBlock.assertContainsKDocsInOrder( + "Top level fun extension string", + "Top level fun extension int" + ) + } + } + } + + @Test + fun `should not ignore case when grouping by name`() { + testInline( + """ + |/src/main/kotlin/test/Test.kt + |package test + | + |/** + | * Top level fun bAr + | */ + |fun Int.bAr(): String = "bar" + | + |/** + | * Top level fun BaR + | */ + |fun String.BaR(): Int = 42 + """.trimMargin(), + defaultConfiguration + ) { + renderingStage = { rootPageNode, _ -> + val packageFunctionBlocks = rootPageNode.findPackageFunctionBlocks(packageName = "test") + assertEquals(2, packageFunctionBlocks.size, "Expected two separate function groups") + + val firstGroup = packageFunctionBlocks[0] + firstGroup.assertContainsKDocsInOrder( + "Top level fun BaR", + ) + + val secondGroup = packageFunctionBlocks[1] + secondGroup.assertContainsKDocsInOrder( + "Top level fun bAr", + ) + } + } + } + + @Test + fun `should sort groups alphabetically ignoring case`() { + testInline( + """ + |/src/main/kotlin/test/Test.kt + |package test + | + |/** Sequence builder */ + |fun <T> sequence(): Sequence<T> + | + |/** Sequence SAM constructor */ + |fun <T> Sequence(): Sequence<T> + | + |/** Sequence.any() */ + |fun <T> Sequence<T>.any() {} + | + |/** Sequence interface */ + |interface Sequence<T> + """.trimMargin(), + defaultConfiguration + ) { + renderingStage = { rootPageNode, _ -> + val packageFunctionBlocks = rootPageNode.findPackageFunctionBlocks(packageName = "test") + assertEquals(3, packageFunctionBlocks.size, "Expected 3 separate function groups") + + packageFunctionBlocks[0].assertContainsKDocsInOrder( + "Sequence.any()", + ) + + packageFunctionBlocks[1].assertContainsKDocsInOrder( + "Sequence SAM constructor", + ) + + packageFunctionBlocks[2].assertContainsKDocsInOrder( + "Sequence builder", + ) + } + } + } + + private fun RootPageNode.findDivergencesOfClass(className: String, kind: ContentKind): ContentDivergentGroup { + val extensionReceiverPage = this.dfs { it is ClasslikePageNode && it.name == className } as ClasslikePageNode + return extensionReceiverPage.content + .dfs { it is ContentDivergentGroup && it.dci.kind == kind } as ContentDivergentGroup + } + + private fun RootPageNode.findPackageFunctionBlocks(packageName: String): List<ContentDivergentGroup> { + val packagePage = this.dfs { it is PackagePage && it.name == packageName } as PackagePage + val packageFunctionTable = packagePage.content.dfs { + it is ContentTable && it.dci.kind == ContentKind.Functions + } as ContentTable + + return packageFunctionTable.children.map { packageGroup -> + packageGroup.dfs { it is ContentDivergentGroup } as ContentDivergentGroup + } + } + + private fun ContentDivergentGroup.assertContainsKDocsInOrder(vararg expectedKDocs: String) { + expectedKDocs.forEachIndexed { index, expectedKDoc -> + assertEquals(expectedKDoc, this.getElementKDocText(index)) + } + } + + private fun ContentDivergentGroup.getElementKDocText(index: Int): String { + val element = this.children.getOrNull(index) ?: throw IllegalArgumentException("No element with index $index") + val commentNode = element.after + ?.withDescendants() + ?.singleOrNull { it is ContentText && it.dci.kind == ContentKind.Comment } + ?: throw IllegalStateException("Expected the element to contain a single paragraph of text / comment") + + return (commentNode as ContentText).text + } +} |