diff options
Diffstat (limited to 'plugins/base')
10 files changed, 339 insertions, 12 deletions
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt index 4da2cb6e..2dbad3a7 100644 --- a/plugins/base/src/main/kotlin/DokkaBase.kt +++ b/plugins/base/src/main/kotlin/DokkaBase.kt @@ -67,7 +67,11 @@ class DokkaBase : DokkaPlugin() { } val suppressedDocumentableFilter by extending { - preMergeDocumentableTransformer providing ::SuppressedDocumentableFilterTransformer + preMergeDocumentableTransformer providing ::SuppressedByConfigurationDocumentableFilterTransformer + } + + val suppressedBySuppressTagDocumentableFilter by extending { + preMergeDocumentableTransformer providing ::SuppressTagDocumentableFilter } val documentableVisbilityFilter by extending { @@ -76,7 +80,12 @@ class DokkaBase : DokkaPlugin() { val emptyPackagesFilter by extending { preMergeDocumentableTransformer providing ::EmptyPackagesFilterTransformer order { - after(deprecatedDocumentableFilter, suppressedDocumentableFilter, documentableVisbilityFilter) + after( + deprecatedDocumentableFilter, + suppressedDocumentableFilter, + documentableVisbilityFilter, + suppressedBySuppressTagDocumentableFilter + ) } } diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationReader.kt b/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationReader.kt index b74242c3..37903988 100644 --- a/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationReader.kt +++ b/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationReader.kt @@ -45,7 +45,7 @@ private class ContextModuleAndPackageDocumentationReader( ): SourceSetDependent<DocumentationNode> { return sourceSets.associateWithNotNull { sourceSet -> val fragments = documentationFragments[sourceSet].orEmpty().filter(predicate) - val resolutionFacade = kotlinAnalysis?.get(sourceSet)?.facade + val resolutionFacade = kotlinAnalysis[sourceSet].facade val documentations = fragments.map { fragment -> parseModuleAndPackageDocumentation( context = ModuleAndPackageDocumentationParsingContext(context.logger, resolutionFacade), diff --git a/plugins/base/src/main/kotlin/transformers/documentables/SuppressTagDocumentableFilter.kt b/plugins/base/src/main/kotlin/transformers/documentables/SuppressTagDocumentableFilter.kt new file mode 100644 index 00000000..7efb23ab --- /dev/null +++ b/plugins/base/src/main/kotlin/transformers/documentables/SuppressTagDocumentableFilter.kt @@ -0,0 +1,12 @@ +package org.jetbrains.dokka.base.transformers.documentables + +import org.jetbrains.dokka.model.Documentable +import org.jetbrains.dokka.model.dfs +import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.model.doc.Suppress + +class SuppressTagDocumentableFilter(val dokkaContext: DokkaContext) : + SuppressedByTagDocumentableFilterTransformer(dokkaContext) { + override fun shouldBeSuppressed(d: Documentable): Boolean = + d.documentation.any { (_, docs) -> docs.dfs { it is Suppress } != null } +}
\ No newline at end of file diff --git a/plugins/base/src/main/kotlin/transformers/documentables/SuppressedDocumentableFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConfigurationDocumentableFilterTransformer.kt index b066e69b..a013bfee 100644 --- a/plugins/base/src/main/kotlin/transformers/documentables/SuppressedDocumentableFilterTransformer.kt +++ b/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConfigurationDocumentableFilterTransformer.kt @@ -8,7 +8,7 @@ import org.jetbrains.dokka.transformers.documentation.source import org.jetbrains.dokka.transformers.documentation.sourceSet import java.io.File -class SuppressedDocumentableFilterTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer { +class SuppressedByConfigurationDocumentableFilterTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer { override fun invoke(modules: List<DModule>): List<DModule> { return modules.mapNotNull(::filterModule) } diff --git a/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByTagDocumentableFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByTagDocumentableFilterTransformer.kt new file mode 100644 index 00000000..f40abe70 --- /dev/null +++ b/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByTagDocumentableFilterTransformer.kt @@ -0,0 +1,110 @@ +package org.jetbrains.dokka.base.transformers.documentables + +import org.jetbrains.dokka.model.* +import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer + +abstract class SuppressedByTagDocumentableFilterTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer { + override fun invoke(modules: List<DModule>): List<DModule> = + modules.map { module -> + val (documentable, wasChanged) = processModule(module) + documentable.takeIf { wasChanged } ?: module + } + + abstract fun shouldBeSuppressed(d: Documentable): Boolean + + private fun processModule(module: DModule): DocumentableWithChanges<DModule> { + val afterProcessing = module.packages.map { processPackage(it) } + val processedModule = module.takeIf { afterProcessing.none { it.changed } } + ?: module.copy(packages = afterProcessing.mapNotNull { it.documentable }) + return DocumentableWithChanges(processedModule, afterProcessing.any { it.changed }) + } + + private fun processPackage(dPackage: DPackage): DocumentableWithChanges<DPackage> { + val classlikes = dPackage.classlikes.map { processClassLike(it) } + val typeAliases = dPackage.typealiases.map { processMember(it) } + val functions = dPackage.functions.map { processMember(it) } + val properies = dPackage.properties.map { processMember(it) } + + val wasChanged = (classlikes + typeAliases + functions + properies).any { it.changed } + return (dPackage.takeIf { !wasChanged } ?: dPackage.copy( + classlikes = classlikes.mapNotNull { it.documentable }, + typealiases = typeAliases.mapNotNull { it.documentable }, + functions = functions.mapNotNull { it.documentable }, + properties = properies.mapNotNull { it.documentable } + )).let { processedPackage -> DocumentableWithChanges(processedPackage, wasChanged) } + } + + private fun processClassLike(classlike: DClasslike): DocumentableWithChanges<DClasslike> { + if (shouldBeSuppressed(classlike)) return DocumentableWithChanges.filteredDocumentable() + + val functions = classlike.functions.map { processMember(it) } + val classlikes = classlike.classlikes.map { processClassLike(it) } + val properties = classlike.properties.map { processMember(it) } + val companion = (classlike as? WithCompanion)?.companion?.let { processClassLike(it) } + + val wasClasslikeChanged = (functions + classlikes + properties).any { it.changed } || companion?.changed == true + return when (classlike) { + is DClass -> { + val constructors = classlike.constructors.map { processMember(it) } + val wasClassChange = + wasClasslikeChanged || constructors.any { it.changed } + (classlike.takeIf { !wasClassChange } ?: classlike.copy( + functions = functions.mapNotNull { it.documentable }, + classlikes = classlikes.mapNotNull { it.documentable }, + properties = properties.mapNotNull { it.documentable }, + constructors = constructors.mapNotNull { it.documentable }, + companion = companion?.documentable as? DObject + )).let { DocumentableWithChanges(it, wasClassChange) } + } + is DInterface -> (classlike.takeIf { !wasClasslikeChanged } ?: classlike.copy( + functions = functions.mapNotNull { it.documentable }, + classlikes = classlikes.mapNotNull { it.documentable }, + properties = properties.mapNotNull { it.documentable }, + companion = companion?.documentable as? DObject + )).let { DocumentableWithChanges(it, wasClasslikeChanged) } + is DObject -> (classlike.takeIf { !wasClasslikeChanged } ?: classlike.copy( + functions = functions.mapNotNull { it.documentable }, + classlikes = classlikes.mapNotNull { it.documentable }, + properties = properties.mapNotNull { it.documentable }, + )).let { DocumentableWithChanges(it, wasClasslikeChanged) } + is DAnnotation -> { + val constructors = classlike.constructors.map { processMember(it) } + val wasClassChange = + wasClasslikeChanged || constructors.any { it.changed } + (classlike.takeIf { !wasClassChange } ?: classlike.copy( + functions = functions.mapNotNull { it.documentable }, + classlikes = classlikes.mapNotNull { it.documentable }, + properties = properties.mapNotNull { it.documentable }, + constructors = constructors.mapNotNull { it.documentable }, + companion = companion?.documentable as? DObject + )).let { DocumentableWithChanges(it, wasClassChange) } + } + is DEnum -> { + val constructors = classlike.constructors.map { processMember(it) } + val entries = classlike.entries.map { processMember(it) } + val wasClassChange = + wasClasslikeChanged || (constructors + entries).any { it.changed } + (classlike.takeIf { !wasClassChange } ?: classlike.copy( + functions = functions.mapNotNull { it.documentable }, + classlikes = classlikes.mapNotNull { it.documentable }, + properties = properties.mapNotNull { it.documentable }, + constructors = constructors.mapNotNull { it.documentable }, + companion = companion?.documentable as? DObject, + entries = entries.mapNotNull { it.documentable } + )).let { DocumentableWithChanges(it, wasClassChange) } + } + } + } + + private fun <T : Documentable> processMember(member: T): DocumentableWithChanges<T> = + if (shouldBeSuppressed(member)) DocumentableWithChanges.filteredDocumentable() + else DocumentableWithChanges(member, false) + + private data class DocumentableWithChanges<T : Documentable>(val documentable: T?, val changed: Boolean = false) { + companion object { + fun <T : Documentable> filteredDocumentable(): DocumentableWithChanges<T> = + DocumentableWithChanges(null, true) + } + } +}
\ No newline at end of file diff --git a/plugins/base/src/main/kotlin/translators/psi/parsers/InheritDocResolver.kt b/plugins/base/src/main/kotlin/translators/psi/parsers/InheritDocResolver.kt index c2fb6fb4..21c2c72a 100644 --- a/plugins/base/src/main/kotlin/translators/psi/parsers/InheritDocResolver.kt +++ b/plugins/base/src/main/kotlin/translators/psi/parsers/InheritDocResolver.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull internal data class CommentResolutionContext( val comment: PsiDocComment, - val tag: JavadocTag, + val tag: JavadocTag?, val name: String? = null, val parameterIndex: Int? = null, ) @@ -25,7 +25,7 @@ internal class InheritDocResolver( JavadocTag.PARAM -> context.parameterIndex?.let { paramIndex -> resolveParamTag(context.comment, paramIndex) } JavadocTag.DEPRECATED -> resolveGenericTag(context.comment, JavadocTag.DESCRIPTION) JavadocTag.SEE -> emptyList() - else -> resolveGenericTag(context.comment, context.tag) + else -> context.tag?.let { tag -> resolveGenericTag(context.comment, tag) } } private fun resolveGenericTag(currentElement: PsiDocComment, tag: JavadocTag): List<PsiElement> = diff --git a/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt b/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt index 96c62b36..a02bceac 100644 --- a/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt +++ b/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt @@ -12,6 +12,7 @@ import org.jetbrains.dokka.analysis.from import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.doc.* import org.jetbrains.dokka.model.doc.Deprecated +import org.jetbrains.dokka.model.doc.Suppress import org.jetbrains.dokka.utilities.DokkaLogger import org.jetbrains.dokka.utilities.enumValueOrNull import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName @@ -118,7 +119,15 @@ class JavadocParser( else -> null //TODO https://github.com/Kotlin/dokka/issues/1618 } - } + } ?: CustomTagWrapper( + wrapTagIfNecessary( + convertJavadocElements( + tag.contentElementsWithSiblingIfNeeded(), + context = CommentResolutionContext(docComment, null) + ) + ), + tag.name + ) private fun wrapTagIfNecessary(list: List<DocTag>): CustomDocTag = if (list.size == 1 && (list.first() as? CustomDocTag)?.name == MarkdownElementTypes.MARKDOWN_FILE.name) @@ -148,14 +157,14 @@ class JavadocParser( } private data class ParserState( - val currentJavadocTag: JavadocTag, + val currentJavadocTag: JavadocTag?, val previousElement: PsiElement? = null, val openPreTags: Int = 0, val closedPreTags: Int = 0 ) private data class ParsingResult(val newState: ParserState, val parsedLine: String? = null) { - constructor(tag: JavadocTag) : this(ParserState(tag)) + constructor(tag: JavadocTag?) : this(ParserState(tag)) operator fun plus(other: ParsingResult): ParsingResult = ParsingResult( @@ -267,7 +276,7 @@ class JavadocParser( private fun convertInlineDocTag( tag: PsiInlineDocTag, - javadocTag: JavadocTag, + javadocTag: JavadocTag?, context: CommentResolutionContext ) = when (tag.name) { diff --git a/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocTag.kt b/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocTag.kt index 8ea39453..869ced30 100644 --- a/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocTag.kt +++ b/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocTag.kt @@ -1,7 +1,7 @@ package org.jetbrains.dokka.base.translators.psi.parsers internal enum class JavadocTag { - PARAM, THROWS, RETURN, AUTHOR, SEE, DEPRECATED, EXCEPTION, + PARAM, THROWS, RETURN, AUTHOR, SEE, DEPRECATED, EXCEPTION, HIDE, /** * Artificial tag created to handle tag-less section diff --git a/plugins/base/src/test/kotlin/transformers/SuppressTagFilterTest.kt b/plugins/base/src/test/kotlin/transformers/SuppressTagFilterTest.kt new file mode 100644 index 00000000..268f934d --- /dev/null +++ b/plugins/base/src/test/kotlin/transformers/SuppressTagFilterTest.kt @@ -0,0 +1,187 @@ +package transformers + +import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest +import org.jetbrains.dokka.model.DEnum +import org.jetbrains.dokka.model.WithCompanion +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertNull + +class SuppressTagFilterTest : BaseAbstractTest() { + private val configuration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src") + } + } + } + + @Test + fun `should filter classes with suppress tag`() { + testInline( + """ + |/src/suppressed/NotSuppressed.kt + |/** + | * sample docs + |*/ + |class NotSuppressed + |/src/suppressed/Suppressed.kt + |/** + | * sample docs + | * @suppress + |*/ + |class Suppressed + """.trimIndent(), configuration + ) { + documentablesFirstTransformationStep = { modules -> + assertEquals( + "NotSuppressed", + modules.flatMap { it.packages }.flatMap { it.classlikes }.singleOrNull()?.name + ) + } + } + } + + @Test + fun `should filter functions with suppress tag`() { + testInline( + """ + |/src/suppressed/Suppressed.kt + |class Suppressed { + | /** + | * sample docs + | * @suppress + | */ + | fun suppressedFun(){ } + |} + """.trimIndent(), configuration + ) { + documentablesFirstTransformationStep = { modules -> + assertNull(modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } + .firstOrNull { it.name == "suppressedFun" }) + } + } + } + + @Test + fun `should filter top level functions`() { + testInline( + """ + |/src/suppressed/Suppressed.kt + |/** + | * sample docs + | * @suppress + | */ + |fun suppressedFun(){ } + | + |/** + | * Sample + | */ + |fun notSuppressedFun() { } + """.trimIndent(), configuration + ) { + documentablesFirstTransformationStep = { modules -> + assertNull(modules.flatMap { it.packages }.flatMap { it.functions } + .firstOrNull { it.name == "suppressedFun" }) + } + } + } + + @Test + fun `should filter top level type aliases`() { + testInline( + """ + |/src/suppressed/suppressed.kt + |/** + | * sample docs + | * @suppress + | */ + |typealias suppressedTypeAlias = String + | + |/** + | * Sample + | */ + |typealias notSuppressedTypeAlias = String + """.trimIndent(), configuration + ) { + documentablesFirstTransformationStep = { modules -> + assertNull(modules.flatMap { it.packages }.flatMap { it.typealiases } + .firstOrNull { it.name == "suppressedTypeAlias" }) + assertNotNull(modules.flatMap { it.packages }.flatMap { it.typealiases } + .firstOrNull { it.name == "notSuppressedTypeAlias" }) + } + } + } + + @Test + fun `should filter companion object`() { + testInline( + """ + |/src/suppressed/Suppressed.kt + |class Suppressed { + |/** + | * @suppress + | */ + |companion object { + | val x = 1 + |} + |} + """.trimIndent(), configuration + ) { + documentablesFirstTransformationStep = { modules -> + assertNull((modules.flatMap { it.packages }.flatMap { it.classlikes } + .firstOrNull { it.name == "Suppressed" } as? WithCompanion)?.companion) + } + } + } + + @Test + fun `should suppress inner classlike`() { + testInline( + """ + |/src/suppressed/Testing.kt + |class Testing { + | /** + | * Sample + | * @suppress + | */ + | inner class Suppressed { + | val x = 1 + | } + |} + """.trimIndent(), configuration + ) { + documentablesFirstTransformationStep = { modules -> + val testingClass = modules.flatMap { it.packages }.flatMap { it.classlikes }.single() + assertNull(testingClass.classlikes.firstOrNull()) + } + } + } + + @Test + fun `should suppress enum entry`() { + testInline( + """ + |/src/suppressed/Testing.kt + |enum class Testing { + | /** + | * Sample + | * @suppress + | */ + | SUPPRESSED, + | + | /** + | * Not suppressed + | */ + | NOT_SUPPRESSED + |} + """.trimIndent(), configuration + ) { + documentablesFirstTransformationStep = { modules -> + val testingClass = modules.flatMap { it.packages }.flatMap { it.classlikes }.single() as DEnum + assertEquals(listOf("NOT_SUPPRESSED"), testingClass.entries.map { it.name }) + } + } + } +}
\ No newline at end of file diff --git a/plugins/base/src/test/kotlin/transformers/SuppressedDocumentableFilterTransformerTest.kt b/plugins/base/src/test/kotlin/transformers/SuppressedByConfigurationDocumentableFilterTransformerTest.kt index a022458a..c6d46b1f 100644 --- a/plugins/base/src/test/kotlin/transformers/SuppressedDocumentableFilterTransformerTest.kt +++ b/plugins/base/src/test/kotlin/transformers/SuppressedByConfigurationDocumentableFilterTransformerTest.kt @@ -7,7 +7,7 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertIterableEquals import org.junit.jupiter.api.Test -class SuppressedDocumentableFilterTransformerTest : BaseAbstractTest() { +class SuppressedByConfigurationDocumentableFilterTransformerTest : BaseAbstractTest() { @Test fun `class filtered by package options`() { |