diff options
author | Marcin Aman <marcin.aman@gmail.com> | 2021-08-21 14:50:55 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-21 14:50:55 +0200 |
commit | 9be7ac19b3ad38c80c78f39443eb2f55b3b699c6 (patch) | |
tree | f82ee68f489d8cdf60fdd5a61cef10a2e0f072c1 /plugins/base/src/main/kotlin/translators | |
parent | 0f866368324cf0bddd444567d26270ea02d8cd0f (diff) | |
download | dokka-9be7ac19b3ad38c80c78f39443eb2f55b3b699c6.tar.gz dokka-9be7ac19b3ad38c80c78f39443eb2f55b3b699c6.tar.bz2 dokka-9be7ac19b3ad38c80c78f39443eb2f55b3b699c6.zip |
Make briefs contain first paragraph as in spec, resolve issues with i.e. (#2048)
* Make briefs contain first paragraph as in spec, resolve issues with i.e.
* Html and the end
Diffstat (limited to 'plugins/base/src/main/kotlin/translators')
5 files changed, 97 insertions, 18 deletions
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt index 081608d6..4b5fc1c0 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt @@ -141,7 +141,7 @@ open class DefaultPageCreator( link(it.name, it.dri) if (it.sourceSets.size == 1 || (documentations.isNotEmpty() && haveSameContent)) { - documentations.first()?.let { firstSentenceComment(kind = ContentKind.Comment, content = it.root) } + documentations.first()?.let { firstParagraphComment(kind = ContentKind.Comment, content = it.root) } } } } @@ -375,7 +375,7 @@ open class DefaultPageCreator( val platforms = d.sourceSets fun DocumentableContentBuilder.contentForParams() { - if (tags.isNotEmptyForTag<Param>()) { + if (tags.isNotEmptyForTag<Param>() && d !is DProperty) { header(2, "Parameters", kind = ContentKind.Parameters) group( extra = mainExtra + SimpleAttr.header("Parameters"), @@ -504,15 +504,33 @@ open class DefaultPageCreator( protected open fun DocumentableContentBuilder.contentForBrief(documentable: Documentable) { documentable.sourceSets.forEach { sourceSet -> - documentable.documentation[sourceSet]?.children?.firstOrNull()?.root?.let { + documentable.documentation[sourceSet]?.let { + /* + Get description or a tag that holds documentation. + This tag can be either property or constructor but constructor tags are handled already in analysis so we + only need to keep an eye on property + + We purposefully ignore all other tags as they should not be visible in brief + */ + it.firstMemberOfTypeOrNull<Description>() ?: it.firstMemberOfTypeOrNull<Property>().takeIf { documentable is DProperty } + }?.let { group(sourceSets = setOf(sourceSet), kind = ContentKind.BriefComment) { - if (documentable.hasSeparatePage) firstSentenceComment(it) - else comment(it) + if (documentable.hasSeparatePage) createBriefComment(documentable, sourceSet, it) + else comment(it.root) } } } } + private fun DocumentableContentBuilder.createBriefComment(documentable: Documentable, sourceSet: DokkaSourceSet, tag: TagWrapper){ + (documentable as? WithSources)?.documentableLanguage(sourceSet)?.let { + when(it){ + DocumentableLanguage.KOTLIN -> firstParagraphComment(tag.root) + DocumentableLanguage.JAVA -> firstSentenceComment(tag.root) + } + } ?: firstParagraphComment(tag.root) + } + protected open fun DocumentableContentBuilder.contentForSinceKotlin(documentable: Documentable) { documentable.documentation.mapValues { it.value.children.find { it is CustomTagWrapper && it.name == "Since Kotlin" } as CustomTagWrapper? diff --git a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt index f98e284f..2db55d45 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt @@ -283,13 +283,37 @@ open class PageContentBuilder( contents += ContentGroup(content, DCI(mainDRI, kind), sourceSets.toDisplaySourceSets(), styles, extra) } - fun firstSentenceComment( + fun firstParagraphComment( content: DocTag, kind: Kind = ContentKind.Comment, sourceSets: Set<DokkaSourceSet> = mainSourcesetData, styles: Set<Style> = mainStyles, extra: PropertyContainer<ContentNode> = mainExtra ) { + firstParagraphBrief(content)?.let { brief -> + val builtDescription = commentsConverter.buildContent( + brief, + DCI(mainDRI, kind), + sourceSets + ) + + contents += ContentGroup( + builtDescription, + DCI(mainDRI, kind), + sourceSets.toDisplaySourceSets(), + styles, + extra + ) + } + } + + fun firstSentenceComment( + content: DocTag, + kind: Kind = ContentKind.Comment, + sourceSets: Set<DokkaSourceSet> = mainSourcesetData, + styles: Set<Style> = mainStyles, + extra: PropertyContainer<ContentNode> = mainExtra + ){ val builtDescription = commentsConverter.buildContent( content, DCI(mainDRI, kind), @@ -297,7 +321,7 @@ open class PageContentBuilder( ) contents += ContentGroup( - briefFromContentNodes(builtDescription), + firstSentenceBriefFromContentNodes(builtDescription), DCI(mainDRI, kind), sourceSets.toDisplaySourceSets(), styles, diff --git a/plugins/base/src/main/kotlin/translators/documentables/briefFromContentNodes.kt b/plugins/base/src/main/kotlin/translators/documentables/briefFromContentNodes.kt index 7ac6763d..81ddb6ed 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/briefFromContentNodes.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/briefFromContentNodes.kt @@ -1,10 +1,20 @@ package org.jetbrains.dokka.base.translators.documentables +import org.jetbrains.dokka.model.doc.* import org.jetbrains.dokka.model.withDescendants import org.jetbrains.dokka.pages.* +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.safeAs -fun briefFromContentNodes(description: List<ContentNode>): List<ContentNode> { +fun firstParagraphBrief(docTag: DocTag): DocTag? = + when(docTag){ + is P -> docTag + is CustomDocTag -> docTag.children.firstNotNullResult { firstParagraphBrief(it) } + is Text -> docTag + else -> null + } + +fun firstSentenceBriefFromContentNodes(description: List<ContentNode>): List<ContentNode> { val firstSentenceRegex = """^((?:[^.?!]|[.!?](?!\s))*[.!?])""".toRegex() //Description that is entirely based on html content. In html it is hard to define a brief so we render all of it @@ -13,21 +23,34 @@ fun briefFromContentNodes(description: List<ContentNode>): List<ContentNode> { } var sentenceFound = false - fun lookthrough(node: ContentNode): ContentNode = - if (node is ContentText && !node.isHtml && firstSentenceRegex.containsMatchIn(node.text)) { + fun lookthrough(node: ContentNode, neighbours: List<ContentNode>, currentIndex: Int): ContentNode = + if (node.finishesWithSentenceNotFollowedByHtml(firstSentenceRegex, neighbours, currentIndex) || node.containsSentenceFinish(firstSentenceRegex)) { + node as ContentText sentenceFound = true node.copy(text = firstSentenceRegex.find(node.text)?.value.orEmpty()) } else if (node is ContentGroup) { - node.copy(children = node.children.mapNotNull { - if (!sentenceFound) lookthrough(it) else null + node.copy(children = node.children.mapIndexedNotNull { i, element -> + if (!sentenceFound) lookthrough(element, node.children, i) else null }, style = node.style - TextStyle.Paragraph) } else { node } - return description.mapNotNull { - if (!sentenceFound) lookthrough(it) else null + return description.mapIndexedNotNull { i, element -> + if (!sentenceFound) lookthrough(element, description, i) else null } } -private val ContentText.isHtml +private fun ContentNode.finishesWithSentenceNotFollowedByHtml(firstSentenceRegex: Regex, neighbours: List<ContentNode>, currentIndex: Int): Boolean = + this is ContentText && !isHtml && matchContainsEnd(this, firstSentenceRegex) && !neighbours.nextElementIsHtml(currentIndex) + +private fun ContentNode.containsSentenceFinish(firstSentenceRegex: Regex): Boolean = + this is ContentText && !isHtml && firstSentenceRegex.containsMatchIn(text) && !matchContainsEnd(this, firstSentenceRegex) + +private fun matchContainsEnd(node: ContentText, regex: Regex): Boolean = + regex.find(node.text)?.let { node.text.endsWith(it.value) } ?: false + +private fun List<ContentNode>.nextElementIsHtml(currentElementIndex: Int): Boolean = + currentElementIndex != lastIndex && get(currentElementIndex + 1).isHtml + +private val ContentNode.isHtml get() = extra[HtmlContent] != null diff --git a/plugins/base/src/main/kotlin/translators/documentables/documentableLanguage.kt b/plugins/base/src/main/kotlin/translators/documentables/documentableLanguage.kt new file mode 100644 index 00000000..b3ce7c5c --- /dev/null +++ b/plugins/base/src/main/kotlin/translators/documentables/documentableLanguage.kt @@ -0,0 +1,15 @@ +package org.jetbrains.dokka.base.translators.documentables + +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.analysis.PsiDocumentableSource +import org.jetbrains.dokka.model.WithSources + +internal enum class DocumentableLanguage { + JAVA, KOTLIN +} + +internal fun WithSources.documentableLanguage(sourceSet: DokkaConfiguration.DokkaSourceSet): DocumentableLanguage = + when (sources[sourceSet]) { + is PsiDocumentableSource -> DocumentableLanguage.JAVA + else -> DocumentableLanguage.KOTLIN + }
\ No newline at end of file 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 9cb362cb..8583edf7 100644 --- a/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt +++ b/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt @@ -22,9 +22,7 @@ import org.jetbrains.kotlin.idea.util.CommentSaver.Companion.tokenType import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespace import org.jetbrains.kotlin.psi.psiUtil.siblings import org.jsoup.Jsoup -import org.jsoup.nodes.Element -import org.jsoup.nodes.Node -import org.jsoup.nodes.TextNode +import org.jsoup.nodes.* import java.util.* import org.jetbrains.dokka.utilities.htmlEscape @@ -414,6 +412,7 @@ class JavadocParser( } else { node.wholeText.parseHtmlEncodedWithNormalisedSpaces(renderWhiteCharactersAsSpaces = true) }).orEmpty() + is Comment -> listOf(Text(body = node.outerHtml(), params = DocTag.contentTypeParam("html"))) is Element -> createBlock(node, keepFormatting) else -> emptyList() } |