From 34a8ae166e7220ddf8c3c42fab466234623501e7 Mon Sep 17 00:00:00 2001 From: Ignat Beresnev Date: Fri, 26 Aug 2022 16:38:37 +0200 Subject: Do not render constructor pages and blocks and for annotation classes (#2642) --- .../documentables/DefaultPageCreator.kt | 14 +- .../signatures/ConstructorsSignaturesTest.kt | 341 +++++++++++++++++++++ .../SkippingParenthesisForConstructorsTest.kt | 296 ------------------ 3 files changed, 353 insertions(+), 298 deletions(-) create mode 100644 plugins/base/src/test/kotlin/content/signatures/ConstructorsSignaturesTest.kt delete mode 100644 plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt index 44e2728a..7f16c568 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt @@ -96,7 +96,12 @@ open class DefaultPageCreator( } } - val constructors = documentables.flatMap { if (it is WithConstructors) it.constructors else emptyList() } + val constructors = + if (documentables.shouldRenderConstructors()) { + documentables.flatMap { (it as? WithConstructors)?.constructors ?: emptyList() } + } else { + emptyList() + } val classlikes = documentables.flatMap { it.classlikes } val functions = documentables.flatMap { it.filteredFunctions } @@ -366,7 +371,7 @@ open class DefaultPageCreator( group(styles = setOf(ContentStyle.TabbedContent), sourceSets = mainSourcesetData + extensions.sourceSets) { +contentForComments(documentables) val csWithConstructor = classlikes.filterIsInstance() - if (csWithConstructor.isNotEmpty()) { + if (csWithConstructor.isNotEmpty() && documentables.shouldRenderConstructors()) { val constructorsToDocumented = csWithConstructor.flatMap { it.constructors } multiBlock( "Constructors", @@ -432,6 +437,11 @@ open class DefaultPageCreator( } } + // Annotations might have constructors to substitute reflection invocations + // and for internal/compiler purposes, but they are not expected to be documented + // and instantiated directly under normal circumstances, so constructors should not be rendered. + private fun List.shouldRenderConstructors() = !this.any { it is DAnnotation } + @Suppress("UNCHECKED_CAST") private inline fun GroupedTags.withTypeUnnamed(): SourceSetDependent = (this[T::class] as List>?)?.toMap().orEmpty() diff --git a/plugins/base/src/test/kotlin/content/signatures/ConstructorsSignaturesTest.kt b/plugins/base/src/test/kotlin/content/signatures/ConstructorsSignaturesTest.kt new file mode 100644 index 00000000..943d1bc4 --- /dev/null +++ b/plugins/base/src/test/kotlin/content/signatures/ConstructorsSignaturesTest.kt @@ -0,0 +1,341 @@ +package content.signatures + +import matchers.content.* +import org.jetbrains.dokka.pages.ContentPage +import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest +import org.junit.jupiter.api.Test +import utils.ParamAttributes +import utils.functionSignature + +class ConstructorsSignaturesTest : BaseAbstractTest() { + private val testConfiguration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/") + analysisPlatform = "jvm" + } + } + } + + @Test + fun `class name without parenthesis`() { + testInline( + """ + |/src/main/kotlin/test/source.kt + |package test + | + |class SomeClass + | + """.trimIndent(), testConfiguration + ) { + pagesTransformationStage = { module -> + val page = module.children.single { it.name == "test" } + .children.single { it.name == "SomeClass" } as ContentPage + page.content.assertNode { + group { + header(1) { +"SomeClass" } + platformHinted { + group { + +"class " + link { +"SomeClass" } + } + } + } + skipAllNotMatching() + } + } + } + } + + @Test + fun `class name with empty parenthesis`() { + testInline( + """ + |/src/main/kotlin/test/source.kt + |package test + | + |class SomeClass() + | + """.trimIndent(), testConfiguration + ) { + pagesTransformationStage = { module -> + val page = module.children.single { it.name == "test" } + .children.single { it.name == "SomeClass" } as ContentPage + page.content.assertNode { + group { + header(1) { +"SomeClass" } + platformHinted { + group { + +"class " + link { +"SomeClass" } + } + } + } + skipAllNotMatching() + } + } + } + } + + @Test + fun `class with a parameter`() { + testInline( + """ + |/src/main/kotlin/test/source.kt + |package test + | + |class SomeClass(a: String) + | + """.trimIndent(), testConfiguration + ) { + pagesTransformationStage = { module -> + val page = module.children.single { it.name == "test" } + .children.single { it.name == "SomeClass" } as ContentPage + page.content.assertNode { + group { + header(1) { +"SomeClass" } + platformHinted { + group { + +"class " + link { +"SomeClass" } + +"(" + group { + group { + +"a: " + group { link { +"String" } } + } + } + +")" + } + } + } + skipAllNotMatching() + } + } + } + } + + @Test + fun `class with a val parameter`() { + testInline( + """ + |/src/main/kotlin/test/source.kt + |package test + | + |class SomeClass(val a: String, var i: Int) + | + """.trimIndent(), testConfiguration + ) { + pagesTransformationStage = { module -> + val page = module.children.single { it.name == "test" } + .children.single { it.name == "SomeClass" } as ContentPage + page.content.assertNode { + group { + header(1) { +"SomeClass" } + platformHinted { + group { + +"class " + link { +"SomeClass" } + +"(" + group { + group { + +"val a: " + group { link { +"String" } } + +", " + } + group { + +"var i: " + group { link { +"Int" } } + } + } + +")" + } + } + } + skipAllNotMatching() + } + } + } + } + + @Test + fun `class with a parameterless secondary constructor`() { + testInline( + """ + |/src/main/kotlin/test/source.kt + |package test + | + |class SomeClass(a: String) { + | constructor() + |} + """.trimIndent(), testConfiguration + ) { + pagesTransformationStage = { module -> + val page = module.children.single { it.name == "test" } + .children.single { it.name == "SomeClass" } as ContentPage + page.content.assertNode { + group { + header(1) { +"SomeClass" } + platformHinted { + group { + +"class " + link { +"SomeClass" } + +"(" + group { + group { + +"a: " + group { link { +"String" } } + } + } + +")" + } + } + } + group { + header { +"Constructors" } + table { + group { + link { +"SomeClass" } + functionSignature( + annotations = emptyMap(), + visibility = "", + modifier = "", + keywords = emptySet(), + name = "SomeClass" + ) + } + group { + link { +"SomeClass" } + functionSignature( + annotations = emptyMap(), + visibility = "", + modifier = "", + keywords = emptySet(), + name = "SomeClass", + params = listOf("a" to ParamAttributes(emptyMap(), emptySet(), "String")).toTypedArray() + ) + } + } + skipAllNotMatching() + } + } + } + } + } + + @Test + fun `class with explicitly documented constructor`() { + testInline( + """ + |/src/main/kotlin/test/source.kt + |package test + | + | /** + | * some comment + | * @constructor ctor comment + | **/ + |class SomeClass(a: String) + """.trimIndent(), testConfiguration + ) { + pagesTransformationStage = { module -> + val page = module.children.single { it.name == "test" } + .children.single { it.name == "SomeClass" } as ContentPage + page.content.assertNode { + group { + header(1) { +"SomeClass" } + platformHinted { + group { + +"class " + link { +"SomeClass" } + +"(" + group { + group { + +"a: " + group { link { +"String" } } + } + } + +")" + } + skipAllNotMatching() + } + } + group { + header { +"Constructors" } + table { + group { + link { +"SomeClass" } + platformHinted { + group { + +"fun " + link { +"SomeClass" } + +"(" + group { + group { + +"a: " + group { + link { +"String" } + } + } + } + +")" + } + group { + group { + group { +"ctor comment" } + } + } + } + } + } + skipAllNotMatching() + } + } + } + } + } + + @Test + fun `should render primary constructor, but not constructors block for annotation class`() { + testInline( + """ + |/src/main/kotlin/test/source.kt + |package test + | + |annotation class MyAnnotation(val param: String) {} + """.trimIndent(), + testConfiguration + ) { + pagesTransformationStage = { module -> + val page = module.children.single { it.name == "test" } + .children.single { it.name == "MyAnnotation" } as ContentPage + page.content.assertNode { + group { + header(1) { +"MyAnnotation" } + platformHinted { + group { + +"annotation class " + link { +"MyAnnotation" } + +"(" + group { + group { + +"val param: " + group { link { +"String" } } + } + } + +")" + } + } + } + group { + group { + header { +"Properties" } + table { + skipAllNotMatching() + } + } + } + } + } + } + } +} diff --git a/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt b/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt deleted file mode 100644 index b6fc4e6b..00000000 --- a/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt +++ /dev/null @@ -1,296 +0,0 @@ -package content.signatures - -import matchers.content.* -import org.jetbrains.dokka.pages.ContentPage -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.junit.jupiter.api.Test -import utils.ParamAttributes -import utils.functionSignature - -class ConstructorsSignaturesTest : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - } - } - } - - @Test - fun `class name without parenthesis`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass - | - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `class name with empty parenthesis`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass() - | - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `class with a parameter`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass(a: String) - | - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - +"(" - group { - group { - +"a: " - group { link { +"String" } } - } - } - +")" - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `class with a val parameter`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass(val a: String, var i: Int) - | - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - +"(" - group { - group { - +"val a: " - group { link { +"String" } } - +", " - } - group { - +"var i: " - group { link { +"Int" } } - } - } - +")" - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `class with a parameterless secondary constructor`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass(a: String) { - | constructor() - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - +"(" - group { - group { - +"a: " - group { link { +"String" } } - } - } - +")" - } - } - } - group { - header { +"Constructors" } - table { - group { - link { +"SomeClass" } - functionSignature( - annotations = emptyMap(), - visibility = "", - modifier = "", - keywords = emptySet(), - name = "SomeClass" - ) - } - group { - link { +"SomeClass" } - functionSignature( - annotations = emptyMap(), - visibility = "", - modifier = "", - keywords = emptySet(), - name = "SomeClass", - params = listOf("a" to ParamAttributes(emptyMap(), emptySet(), "String")).toTypedArray() - ) - } - } - skipAllNotMatching() - } - } - } - } - } - - @Test - fun `class with explicitly documented constructor`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - | /** - | * some comment - | * @constructor ctor comment - | **/ - |class SomeClass(a: String) - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - +"(" - group { - group { - +"a: " - group { link { +"String" } } - } - } - +")" - } - skipAllNotMatching() - } - } - group { - header { +"Constructors" } - table { - group { - link { +"SomeClass" } - platformHinted { - group { - +"fun " - link { +"SomeClass" } - +"(" - group { - group { - +"a: " - group { - link { +"String" } - } - } - } - +")" - } - group { - group { - group { +"ctor comment" } - } - } - } - } - } - skipAllNotMatching() - } - } - } - } - } -} -- cgit