aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/base/src/main')
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt28
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt28
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/briefFromContentNodes.kt39
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/documentableLanguage.kt15
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt5
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()
}