aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorBłażej Kardyś <bkardys@virtuslab.com>2020-07-17 03:48:03 +0200
committerSebastian Sellmair <34319766+sellmair@users.noreply.github.com>2020-08-11 14:27:44 +0200
commitaeb2014eee704be377c06205d16f60562d2a8cf1 (patch)
treed144b627a0b379bebedf7e015f6d469fea61d0bb /plugins
parent49c9bcc586abb7c78f569526a05fea97da86993d (diff)
downloaddokka-aeb2014eee704be377c06205d16f60562d2a8cf1.tar.gz
dokka-aeb2014eee704be377c06205d16f60562d2a8cf1.tar.bz2
dokka-aeb2014eee704be377c06205d16f60562d2a8cf1.zip
Fixing javadoc comment parser for psi files
Diffstat (limited to 'plugins')
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt9
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt3
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt180
-rw-r--r--plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt54
-rw-r--r--plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt34
-rw-r--r--plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt2
-rw-r--r--plugins/base/src/test/kotlin/enums/EnumsTest.kt4
-rw-r--r--plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt164
-rw-r--r--plugins/base/src/test/kotlin/translators/JavadocParserTest.kt156
-rw-r--r--plugins/base/src/test/kotlin/translators/utils.kt42
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt21
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt5
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt1
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToHtmlTranslator.kt65
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt13
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt2
-rw-r--r--plugins/javadoc/src/main/resources/views/class.korte2
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt8
18 files changed, 531 insertions, 234 deletions
diff --git a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
index 0f953e0f..9d667623 100644
--- a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
+++ b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
@@ -53,6 +53,9 @@ object DocTagToContentConverter : CommentsToContentConverter {
)
)
+ fun P.collapseParagraphs(): P =
+ if (children.size == 1 && children.first() is P) (children.first() as P).collapseParagraphs() else this
+
return when (docTag) {
is H1 -> buildHeader(1)
is H2 -> buildHeader(2)
@@ -63,12 +66,14 @@ object DocTagToContentConverter : CommentsToContentConverter {
is Ul -> buildList(false)
is Ol -> buildList(true, docTag.params["start"]?.toInt() ?: 1)
is Li -> listOf(
- ContentGroup(children = buildChildren(docTag), dci, sourceSets, styles, extra)
+ ContentGroup(buildChildren(docTag), dci, sourceSets, styles, extra)
)
is Br -> buildNewLine()
is B -> buildChildren(docTag, setOf(TextStyle.Strong))
is I -> buildChildren(docTag, setOf(TextStyle.Italic))
- is P -> buildChildren(docTag, newStyles = setOf(TextStyle.Paragraph))
+ is P -> listOf(
+ ContentGroup(buildChildren(docTag.collapseParagraphs()), dci, sourceSets, styles + setOf(TextStyle.Paragraph), extra)
+ )
is A -> listOf(
ContentResolvedLink(
buildChildren(docTag),
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index df5d4ee1..9ed37c30 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -285,8 +285,7 @@ class DefaultPsiToDocumentableTranslator(
psiParameter.name,
DocumentationNode(
listOfNotNull(docs.firstChildOfTypeOrNull<Param> {
- it.firstChildOfTypeOrNull<DocumentationLink>()
- ?.firstChildOfTypeOrNull<Text>()?.body == psiParameter.name
+ it.name == psiParameter.name
})).toSourceSetDependent(),
null,
getBound(psiParameter.type),
diff --git a/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt b/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt
index 81955fde..8262b3c6 100644
--- a/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt
@@ -34,18 +34,30 @@ class JavadocParser(
docComment.getDescription()?.let { nodes.add(it) }
nodes.addAll(docComment.tags.mapNotNull { tag ->
when (tag.name) {
- "param" -> Param(P(convertJavadocElements(tag.dataElements.toList())), tag.text)
- "throws" -> Throws(P(convertJavadocElements(tag.dataElements.toList())), tag.text)
- "return" -> Return(P(convertJavadocElements(tag.dataElements.toList())))
- "author" -> Author(P(convertJavadocElements(tag.dataElements.toList())))
- "see" -> See(P(getSeeTagElementContent(tag)), tag.referenceElement()?.text.orEmpty(), null)
- "deprecated" -> Deprecated(P(convertJavadocElements(tag.dataElements.toList())))
+ "param" -> Param(
+ wrapTagIfNecessary(convertJavadocElements(tag.contentElements())),
+ tag.children.firstIsInstanceOrNull<PsiDocParamRef>()?.text.orEmpty()
+ )
+ "throws" -> Throws(wrapTagIfNecessary(convertJavadocElements(tag.contentElements())), tag.text)
+ "return" -> Return(wrapTagIfNecessary(convertJavadocElements(tag.contentElements())))
+ "author" -> Author(wrapTagIfNecessary(convertJavadocElements(tag.contentElements())))
+ "see" -> getSeeTagElementContent(tag).let {
+ See(
+ wrapTagIfNecessary(it.first),
+ tag.referenceElement()?.text.orEmpty(),
+ it.second
+ )
+ }
+ "deprecated" -> Deprecated(wrapTagIfNecessary(convertJavadocElements(tag.dataElements.toList())))
else -> null
}
})
return DocumentationNode(nodes)
}
+ private fun wrapTagIfNecessary(list: List<DocTag>): DocTag =
+ if (list.size == 1) list.first() else P(list)
+
private fun findClosestDocComment(element: PsiNamedElement): PsiDocComment? {
(element as? PsiDocCommentOwner)?.docComment?.run { return this }
if (element is PsiMethod) {
@@ -119,88 +131,118 @@ class JavadocParser(
}
}
- private fun getSeeTagElementContent(tag: PsiDocTag): List<DocTag> =
- listOfNotNull(tag.referenceElement()?.toDocumentationLink())
+ private fun getSeeTagElementContent(tag: PsiDocTag): Pair<List<DocumentationLink>, DRI?> {
+ val content = tag.referenceElement()?.toDocumentationLink()
+ return Pair(listOfNotNull(content), content?.dri)
+ }
private fun PsiDocComment.getDescription(): Description? {
- val nonEmptyDescriptionElements = descriptionElements.filter { it.text.trim().isNotEmpty() }
- val convertedDescriptionElements = convertJavadocElements(nonEmptyDescriptionElements)
- if (convertedDescriptionElements.isNotEmpty()) {
- return Description(P(convertedDescriptionElements))
+ val nonEmptyDescriptionElements = descriptionElements.filter { it.text.isNotBlank() }
+ return convertJavadocElements(nonEmptyDescriptionElements).takeIf { it.isNotEmpty() }?.let {
+ Description(wrapTagIfNecessary(it))
}
-
- return null
}
- private fun convertJavadocElements(elements: Iterable<PsiElement>): List<DocTag> =
- elements.mapNotNull {
- when (it) {
- is PsiReference -> convertJavadocElements(it.children.toList())
- is PsiInlineDocTag -> listOfNotNull(convertInlineDocTag(it))
- is PsiDocParamRef -> listOfNotNull(it.toDocumentationLink())
- is PsiDocTagValue,
- is LeafPsiElement -> Jsoup.parse(it.text.trim()).body().childNodes().mapNotNull(::convertHtmlNode)
- else -> null
+ private inner class Parse : (Iterable<PsiElement>, Boolean) -> List<DocTag> {
+ val driMap = mutableMapOf<String, DRI>()
+
+ private fun PsiElement.stringify(): String? = when (this) {
+ is PsiReference -> children.joinToString("") { it.stringify().orEmpty() }
+ is PsiInlineDocTag -> convertInlineDocTag(this)
+ is PsiDocParamRef -> toDocumentationLinkString()
+ is PsiDocTagValue,
+ is LeafPsiElement -> (if ((prevSibling as? PsiDocToken)?.isLeadingAsterisk() == true) text?.trim() else text)?.takeUnless { it.isBlank() }
+ else -> null
+ }
+
+ private fun PsiElement.toDocumentationLinkString(
+ labelElement: PsiElement? = null
+ ): String? =
+ reference?.resolve()?.let {
+ if (it !is PsiParameter) {
+ val dri = DRI.from(it)
+ driMap[dri.toString()] = dri
+ val label = labelElement ?: defaultLabel()
+ """<a data-dri=$dri>${label.text}</a>"""
+ } else null
}
- }.flatten()
- private fun convertHtmlNode(node: Node, insidePre: Boolean = false): DocTag? = when (node) {
- is TextNode -> Text(body = if (insidePre) node.wholeText else node.text())
- is Element -> createBlock(node)
- else -> null
- }
+ private fun convertInlineDocTag(tag: PsiInlineDocTag) = when (tag.name) {
+ "link", "linkplain" -> {
+ tag.referenceElement()?.toDocumentationLinkString(tag.dataElements.firstIsInstanceOrNull<PsiDocToken>())
+ }
+ "code", "literal" -> {
+ "<code data-inline>${tag.text}</code>"
+ }
+ "index" -> "<index>${tag.children.filterIsInstance<PsiDocTagValue>().joinToString { it.text }}</index>"
+ else -> tag.text
+ }
- private fun createBlock(element: Element): DocTag {
- val children = element.childNodes().mapNotNull { convertHtmlNode(it) }
- return when (element.tagName()) {
- "p" -> P(listOf(Br, Br) + children)
- "b" -> B(children)
- "strong" -> Strong(children)
- "i" -> I(children)
- "em" -> Em(children)
- "code" -> CodeBlock(children)
- "pre" -> Pre(children)
- "ul" -> Ul(children)
- "ol" -> Ol(children)
- "li" -> Li(children)
- "a" -> createLink(element, children)
- else -> Text(body = element.ownText())
+ private fun createLink(element: Element, children: List<DocTag>): DocTag {
+ return when {
+ element.hasAttr("docref") ->
+ A(children, params = mapOf("docref" to element.attr("docref")))
+ element.hasAttr("href") ->
+ A(children, params = mapOf("href" to element.attr("href")))
+ element.hasAttr("data-dri") && driMap.containsKey(element.attr("data-dri")) ->
+ DocumentationLink(driMap[element.attr("data-dri")]!!, children)
+ else -> Text(children = children)
+ }
}
- }
- private fun createLink(element: Element, children: List<DocTag>): DocTag {
- return when {
- element.hasAttr("docref") -> {
- A(children, params = mapOf("docref" to element.attr("docref")))
+ private fun createBlock(element: Element): DocTag? {
+ val children = element.childNodes().mapNotNull { convertHtmlNode(it) }
+ fun ifChildrenPresent(operation: () -> DocTag): DocTag? {
+ return if (children.isNotEmpty()) operation() else null
}
- element.hasAttr("href") -> {
- A(children, params = mapOf("href" to element.attr("href")))
+ return when (element.tagName()) {
+ "blockquote" -> ifChildrenPresent { BlockQuote(children) }
+ "p" -> ifChildrenPresent { P(children) }
+ "b" -> ifChildrenPresent { B(children) }
+ "strong" -> ifChildrenPresent { Strong(children) }
+ "index" -> Index(children)
+ "i" -> ifChildrenPresent { I(children) }
+ "em" -> Em(children)
+ "code" -> ifChildrenPresent {
+ if (element.hasAttr("data-inline")) CodeInline(children) else CodeBlock(
+ children
+ )
+ }
+ "pre" -> Pre(children)
+ "ul" -> ifChildrenPresent { Ul(children) }
+ "ol" -> ifChildrenPresent { Ol(children) }
+ "li" -> Li(children)
+ "a" -> createLink(element, children)
+ else -> Text(body = element.ownText())
}
- else -> Text(children = children)
}
+
+ private fun convertHtmlNode(node: Node, insidePre: Boolean = false): DocTag? = when (node) {
+ is TextNode -> Text(body = if (insidePre) node.wholeText else node.text())
+ is Element -> createBlock(node)
+ else -> null
+ }
+
+ override fun invoke(elements: Iterable<PsiElement>, asParagraph: Boolean): List<DocTag> =
+ Jsoup.parseBodyFragment(elements.mapNotNull { it.stringify() }.joinToString(" ", prefix = if (asParagraph) "<p>" else ""))
+ .body().childNodes().mapNotNull { convertHtmlNode(it) }
}
+ private fun PsiDocTag.contentElements(): List<PsiElement> =
+ dataElements.mapNotNull { it.takeIf { it.text.isNotBlank() } }
+
+ private fun convertJavadocElements(elements: Iterable<PsiElement>, asParagraph: Boolean = true): List<DocTag> = Parse()(elements, asParagraph)
+
private fun PsiDocToken.isSharpToken() = tokenType.toString() == "DOC_TAG_VALUE_SHARP_TOKEN"
+ private fun PsiDocToken.isLeadingAsterisk() = tokenType.toString() == "DOC_COMMENT_LEADING_ASTERISKS"
+
private fun PsiElement.toDocumentationLink(labelElement: PsiElement? = null) =
reference?.resolve()?.let {
val dri = DRI.from(it)
- val label = labelElement ?: children.firstOrNull {
- it is PsiDocToken && it.text.isNotBlank() && !it.isSharpToken()
- } ?: this
- DocumentationLink(dri, convertJavadocElements(listOfNotNull(label)))
- }
-
- private fun convertInlineDocTag(tag: PsiInlineDocTag) = when (tag.name) {
- "link", "linkplain" -> {
- tag.referenceElement()?.toDocumentationLink(tag.dataElements.firstIsInstanceOrNull<PsiDocToken>())
+ val label = labelElement ?: defaultLabel()
+ DocumentationLink(dri, convertJavadocElements(listOfNotNull(label), asParagraph = false))
}
- "code", "literal" -> {
- CodeInline(listOf(Text(tag.text)))
- }
- "index" -> Index(tag.children.filterIsInstance<PsiDocTagValue>().map { Text(it.text) })
- else -> Text(tag.text)
- }
private fun PsiDocTag.referenceElement(): PsiElement? =
linkElement()?.let {
@@ -211,6 +253,10 @@ class JavadocParser(
}
}
+ private fun PsiElement.defaultLabel() = children.firstOrNull {
+ it is PsiDocToken && it.text.isNotBlank() && !it.isSharpToken()
+ } ?: this
+
private fun PsiDocTag.linkElement(): PsiElement? =
valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace }
}
diff --git a/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt b/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt
index a9689bc5..4ac5717d 100644
--- a/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt
+++ b/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt
@@ -86,7 +86,7 @@ class ContentForParamsTest : AbstractCoreTest() {
divergentGroup {
divergentInstance {
before {
- pWrapped("comment to function")
+ group { pWrapped("comment to function") }
}
divergent {
bareSignature(
@@ -131,8 +131,8 @@ class ContentForParamsTest : AbstractCoreTest() {
divergentGroup {
divergentInstance {
before {
- unnamedTag("Author") { +"Kordyjan" }
- unnamedTag("Since") { +"0.11" }
+ unnamedTag("Author") { group { +"Kordyjan" } }
+ unnamedTag("Since") { group { +"0.11" } }
}
divergent {
bareSignature(
@@ -178,9 +178,9 @@ class ContentForParamsTest : AbstractCoreTest() {
divergentGroup {
divergentInstance {
before {
- pWrapped("comment to function")
- unnamedTag("Author") { +"Kordyjan" }
- unnamedTag("Since") { +"0.11" }
+ group { pWrapped("comment to function") }
+ unnamedTag("Author") { group { +"Kordyjan" } }
+ unnamedTag("Since") { group { +"0.11" } }
}
divergent {
bareSignature(
@@ -225,14 +225,14 @@ class ContentForParamsTest : AbstractCoreTest() {
divergentGroup {
divergentInstance {
before {
- pWrapped("comment to function")
+ group { pWrapped("comment to function") }
header(2) { +"Parameters" }
group {
platformHinted {
table {
group {
+"abc"
- group { +"comment to param" }
+ group { group { +"comment to param" } }
}
}
}
@@ -283,22 +283,22 @@ class ContentForParamsTest : AbstractCoreTest() {
divergentGroup {
divergentInstance {
before {
- pWrapped("comment to function")
+ group { group { group { +"comment to function" } } }
header(2) { +"Parameters" }
group {
platformHinted {
table {
group {
+"first"
- group { +"comment to first param" }
+ group { group { +"comment to first param" } }
}
group {
+"second"
- group { +"comment to second param" }
+ group { group { +"comment to second param" } }
}
group {
+"third"
- group { +"comment to third param" }
+ group { group { +"comment to third param" } }
}
}
}
@@ -351,15 +351,15 @@ class ContentForParamsTest : AbstractCoreTest() {
table {
group {
+"first"
- group { +"comment to first param" }
+ group { group { +"comment to first param" } }
}
group {
+"second"
- group { +"comment to second param" }
+ group { group { +"comment to second param" } }
}
group {
+"third"
- group { +"comment to third param" }
+ group { group { +"comment to third param" } }
}
}
}
@@ -406,18 +406,18 @@ class ContentForParamsTest : AbstractCoreTest() {
divergentGroup {
divergentInstance {
before {
- pWrapped("comment to function")
+ group { pWrapped("comment to function") }
header(2) { +"Parameters" }
group {
platformHinted {
table {
group {
+"<receiver>"
- group { +"comment to receiver" }
+ group { group { +"comment to receiver" } }
}
group {
+"abc"
- group { +"comment to param" }
+ group { group { +"comment to param" } }
}
}
}
@@ -468,18 +468,18 @@ class ContentForParamsTest : AbstractCoreTest() {
divergentGroup {
divergentInstance {
before {
- pWrapped("comment to function")
+ group { group { group { +"comment to function" } } }
header(2) { +"Parameters" }
group {
platformHinted {
table {
group {
+"first"
- group { +"comment to first param" }
+ group { group { +"comment to first param" } }
}
group {
+"third"
- group { +"comment to third param" }
+ group { group { +"comment to third param" } }
}
}
}
@@ -529,9 +529,9 @@ class ContentForParamsTest : AbstractCoreTest() {
divergentGroup {
divergentInstance {
before {
- pWrapped("comment to function")
- unnamedTag("Author") { +"Kordyjan" }
- unnamedTag("Since") { +"0.11" }
+ group { pWrapped("comment to function") }
+ unnamedTag("Author") { group { +"Kordyjan" } }
+ unnamedTag("Since") { group { +"0.11" } }
header(2) { +"Parameters" }
group {
@@ -539,15 +539,15 @@ class ContentForParamsTest : AbstractCoreTest() {
table {
group {
+"first"
- group { +"comment to first param" }
+ group { group { +"comment to first param" } }
}
group {
+"second"
- group { +"comment to second param" }
+ group { group { +"comment to second param" } }
}
group {
+"third"
- group { +"comment to third param" }
+ group { group { +"comment to third param" } }
}
}
}
diff --git a/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt b/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt
index 24970660..fd51c895 100644
--- a/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt
+++ b/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt
@@ -89,7 +89,7 @@ class ContentForSeeAlsoTest : AbstractCoreTest() {
group {
//DRI should be "test//abc/#/-1/"
link { +"abc" }
- group { }
+ group { group { } }
}
}
}
@@ -144,7 +144,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() {
group {
//DRI should be "test//abc/#/-1/"
link { +"abc" }
- group { +"Comment to abc" }
+ group {
+ group { +"Comment to abc" }
+ }
}
}
}
@@ -199,7 +201,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() {
group {
//DRI should be "kotlin.collections/Collection////"
link { +"Collection" }
- group { }
+ group {
+ group { }
+ }
}
}
}
@@ -254,7 +258,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() {
group {
//DRI should be "test//abc/#/-1/"
link { +"Collection" }
- group { +"Comment to stdliblink" }
+ group {
+ group { +"Comment to stdliblink" }
+ }
}
}
}
@@ -305,9 +311,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() {
divergentGroup {
divergentInstance {
before {
- pWrapped("random comment")
- unnamedTag("Author") { +"pikinier20" }
- unnamedTag("Since") { +"0.11" }
+ group { group { group { +"random comment"} } }
+ unnamedTag("Author") { group { +"pikinier20" } }
+ unnamedTag("Since") { group { +"0.11" } }
header(2) { +"See also" }
group {
@@ -316,7 +322,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() {
group {
//DRI should be "test//abc/#/-1/"
link { +"Collection" }
- group { +"Comment to stdliblink" }
+ group {
+ group { +"Comment to stdliblink" }
+ }
}
}
}
@@ -372,7 +380,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() {
group {
//DRI should be "test//abc/#/-1/"
link { +"abc" }
- group { +"Comment to abc2" }
+ group {
+ group { +"Comment to abc2" }
+ }
}
}
}
@@ -428,12 +438,14 @@ class ContentForSeeAlsoTest : AbstractCoreTest() {
group {
//DRI should be "test//abc/#/-1/"
link { +"abc" }
- group { +"Comment to abc1" }
+ group {
+ group { +"Comment to abc1" }
+ }
}
group {
//DRI should be "test//abc/#/-1/"
link { +"Collection" }
- group { +"Comment to collection" }
+ group { group { +"Comment to collection" } }
}
}
}
diff --git a/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt b/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt
index 90a38055..b3da3f71 100644
--- a/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt
+++ b/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt
@@ -230,7 +230,7 @@ class ConstructorsSignaturesTest : AbstractCoreTest() {
platformHinted {
group {
group {
- +"ctor comment"
+ group { +"ctor comment" }
}
}
group {
diff --git a/plugins/base/src/test/kotlin/enums/EnumsTest.kt b/plugins/base/src/test/kotlin/enums/EnumsTest.kt
index 6a973f8e..9cd41dcd 100644
--- a/plugins/base/src/test/kotlin/enums/EnumsTest.kt
+++ b/plugins/base/src/test/kotlin/enums/EnumsTest.kt
@@ -210,7 +210,9 @@ class EnumsTest : AbstractCoreTest() {
platformHinted {
group {
group {
- + "Sample docs for E1"
+ group {
+ +"Sample docs for E1"
+ }
}
}
group {
diff --git a/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt b/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt
index 5197afc6..ad023d84 100644
--- a/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt
+++ b/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt
@@ -37,7 +37,7 @@ class CommentsToContentConverterTest {
fun `simple text`() {
val docTag = P(listOf(Text("This is simple test of string Next line")))
executeTest(docTag) {
- +"This is simple test of string Next line"
+ group { +"This is simple test of string Next line" }
}
}
@@ -51,9 +51,11 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- +"This is simple test of string"
- node<ContentBreakLine>()
- +"Next line"
+ group {
+ +"This is simple test of string"
+ node<ContentBreakLine>()
+ +"Next line"
+ }
}
}
@@ -66,10 +68,14 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- +"Paragraph number one"
- +"Paragraph"
- node<ContentBreakLine>()
- +"number two"
+ group {
+ group { +"Paragraph number one" }
+ group {
+ +"Paragraph"
+ node<ContentBreakLine>()
+ +"number two"
+ }
+ }
}
}
@@ -122,20 +128,22 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- node<ContentList> {
- group { +"Outer first Outer next line" }
- group { +"Outer second" }
+ group {
node<ContentList> {
- group { +"Middle first Middle next line" }
- group { +"Middle second" }
+ group { +"Outer first Outer next line" }
+ group { +"Outer second" }
node<ContentList> {
- group { +"Inner first Inner next line" }
+ group { +"Middle first Middle next line" }
+ group { +"Middle second" }
+ node<ContentList> {
+ group { +"Inner first Inner next line" }
+ }
+ group { +"Middle third" }
}
- group { +"Middle third" }
+ group { +"Outer third" }
}
- group { +"Outer third" }
+ group { +"New paragraph" }
}
- +"New paragraph"
}
}
@@ -149,9 +157,11 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- header(1) { +"Header 1" }
- +"Following text"
- +"New paragraph"
+ group {
+ header(1) { +"Header 1" }
+ group { +"Following text" }
+ group { +"New paragraph" }
+ }
}
}
@@ -174,18 +184,20 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- header(1) {+"Header 1"}
- +"Text 1"
- header(2) {+"Header 2"}
- +"Text 2"
- header(3) {+"Header 3"}
- +"Text 3"
- header(4) {+"Header 4"}
- +"Text 4"
- header(5) {+"Header 5"}
- +"Text 5"
- header(6) {+"Header 6"}
- +"Text 6"
+ group {
+ header(1) { +"Header 1" }
+ group { +"Text 1" }
+ header(2) { +"Header 2" }
+ group { +"Text 2" }
+ header(3) { +"Header 3" }
+ group { +"Text 3" }
+ header(4) { +"Header 4" }
+ group { +"Text 4" }
+ header(5) { +"Header 5" }
+ group { +"Text 5" }
+ header(6) { +"Header 6" }
+ group { +"Text 6" }
+ }
}
}
@@ -211,12 +223,14 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- node<ContentCodeBlock> {
- +"Blockquotes are very handy in email to emulate reply text. This line is part of the same quote."
- }
- +"Quote break."
- node<ContentCodeBlock> {
- +"Quote"
+ group {
+ node<ContentCodeBlock> {
+ +"Blockquotes are very handy in email to emulate reply text. This line is part of the same quote."
+ }
+ group { +"Quote break." }
+ node<ContentCodeBlock> {
+ +"Quote"
+ }
}
}
}
@@ -245,16 +259,18 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- node<ContentCodeBlock> {
- +"text 1 text 2"
+ group {
node<ContentCodeBlock> {
- +"text 3 text 4"
+ +"text 1 text 2"
+ node<ContentCodeBlock> {
+ +"text 3 text 4"
+ }
+ +"text 5"
+ }
+ group { +"Quote break." }
+ node<ContentCodeBlock> {
+ +"Quote"
}
- +"text 5"
- }
- +"Quote break."
- node<ContentCodeBlock> {
- +"Quote"
}
}
}
@@ -278,21 +294,23 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- node<ContentCodeBlock> {
- +"val x: Int = 0"
- node<ContentBreakLine>()
- +"val y: String = \"Text\""
- node<ContentBreakLine>()
- node<ContentBreakLine>()
- +" val z: Boolean = true"
- node<ContentBreakLine>()
- +"for(i in 0..10) {"
- node<ContentBreakLine>()
- +" println(i)"
- node<ContentBreakLine>()
- +"}"
+ group {
+ node<ContentCodeBlock> {
+ +"val x: Int = 0"
+ node<ContentBreakLine>()
+ +"val y: String = \"Text\""
+ node<ContentBreakLine>()
+ node<ContentBreakLine>()
+ +" val z: Boolean = true"
+ node<ContentBreakLine>()
+ +"for(i in 0..10) {"
+ node<ContentBreakLine>()
+ +" println(i)"
+ node<ContentBreakLine>()
+ +"}"
+ }
+ group { +"Sample text" }
}
- +"Sample text"
}
}
@@ -307,7 +325,7 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- link {
+ group { link {
+"I'm an inline-style link"
check {
assertEquals(
@@ -315,7 +333,7 @@ class CommentsToContentConverterTest {
"https://www.google.com"
)
}
- }
+ } }
}
}
@@ -384,20 +402,24 @@ class CommentsToContentConverterTest {
)
)
executeTest(docTag) {
- node<ContentList> {
- group { +"Outer first Outer next line" }
- group { +"Outer second" }
+ group {
node<ContentList> {
- group { +"Middle first Middle next line" }
- group { +"Middle second" }
+ group { +"Outer first Outer next line" }
+ group { +"Outer second" }
node<ContentList> {
- +"Inner first Inner next line"
+ group { +"Middle first Middle next line" }
+ group { +"Middle second" }
+ node<ContentList> {
+ +"Inner first Inner next line"
+ }
+ group { +"Middle third" }
}
- group { +"Middle third" }
+ group { +"Outer third" }
+ }
+ group {
+ +"New paragraph"
}
- group { +"Outer third" }
}
- +"New paragraph"
}
}
} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt b/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt
new file mode 100644
index 00000000..a1fbb2a0
--- /dev/null
+++ b/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt
@@ -0,0 +1,156 @@
+package translators
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.DModule
+import org.jetbrains.dokka.model.childrenOfType
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.model.firstChildOfType
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.Assertions.*
+import utils.text
+
+class JavadocParserTest : AbstractCoreTest() {
+
+ private fun performJavadocTest(testOperation: (DModule) -> Unit) {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/Date2.java
+ |/**
+ | * The class <code>Date</code> represents a specific instant
+ | * in time, with millisecond precision.
+ | * <p>
+ | * Prior to JDK&nbsp;1.1, the class <code>Date</code> had two additional
+ | * functions. It allowed the interpretation of dates as year, month, day, hour,
+ | * minute, and second values. It also allowed the formatting and parsing
+ | * of date strings. Unfortunately, the API for these functions was not
+ | * amenable to internationalization. As of JDK&nbsp;1.1, the
+ | * <code>Calendar</code> class should be used to convert between dates and time
+ | * fields and the <code>DateFormat</code> class should be used to format and
+ | * parse date strings.
+ | * The corresponding methods in <code>Date</code> are deprecated.
+ | * <p>
+ | * Although the <code>Date</code> class is intended to reflect
+ | * coordinated universal time (UTC), it may not do so exactly,
+ | * depending on the host environment of the Java Virtual Machine.
+ | * Nearly all modern operating systems assume that 1&nbsp;day&nbsp;=
+ | * 24&nbsp;&times;&nbsp;60&nbsp;&times;&nbsp;60&nbsp;= 86400 seconds
+ | * in all cases. In UTC, however, about once every year or two there
+ | * is an extra second, called a "leap second." The leap
+ | * second is always added as the last second of the day, and always
+ | * on December 31 or June 30. For example, the last minute of the
+ | * year 1995 was 61 seconds long, thanks to an added leap second.
+ | * Most computer clocks are not accurate enough to be able to reflect
+ | * the leap-second distinction.
+ | * <p>
+ | * Some computer standards are defined in terms of Greenwich mean
+ | * time (GMT), which is equivalent to universal time (UT). GMT is
+ | * the "civil" name for the standard; UT is the
+ | * "scientific" name for the same standard. The
+ | * distinction between UTC and UT is that UTC is based on an atomic
+ | * clock and UT is based on astronomical observations, which for all
+ | * practical purposes is an invisibly fine hair to split. Because the
+ | * earth's rotation is not uniform (it slows down and speeds up
+ | * in complicated ways), UT does not always flow uniformly. Leap
+ | * seconds are introduced as needed into UTC so as to keep UTC within
+ | * 0.9 seconds of UT1, which is a version of UT with certain
+ | * corrections applied. There are other time and date systems as
+ | * well; for example, the time scale used by the satellite-based
+ | * global positioning system (GPS) is synchronized to UTC but is
+ | * <i>not</i> adjusted for leap seconds. An interesting source of
+ | * further information is the U.S. Naval Observatory, particularly
+ | * the Directorate of Time at:
+ | * <blockquote><pre>
+ | * <a href=http://tycho.usno.navy.mil>http://tycho.usno.navy.mil</a>
+ | * </pre></blockquote>
+ | * <p>
+ | * and their definitions of "Systems of Time" at:
+ | * <blockquote><pre>
+ | * <a href=http://tycho.usno.navy.mil/systime.html>http://tycho.usno.navy.mil/systime.html</a>
+ | * </pre></blockquote>
+ | * <p>
+ | * In all methods of class <code>Date</code> that accept or return
+ | * year, month, date, hours, minutes, and seconds values, the
+ | * following representations are used:
+ | * <ul>
+ | * <li>A year <i>y</i> is represented by the integer
+ | * <i>y</i>&nbsp;<code>-&nbsp;1900</code>.
+ | * <li>A month is represented by an integer from 0 to 11; 0 is January,
+ | * 1 is February, and so forth; thus 11 is December.
+ | * <li>A date (day of month) is represented by an integer from 1 to 31
+ | * in the usual manner.
+ | * <li>An hour is represented by an integer from 0 to 23. Thus, the hour
+ | * from midnight to 1 a.m. is hour 0, and the hour from noon to 1
+ | * p.m. is hour 12.
+ | * <li>A minute is represented by an integer from 0 to 59 in the usual manner.
+ | * <li>A second is represented by an integer from 0 to 61; the values 60 and
+ | * 61 occur only for leap seconds and even then only in Java
+ | * implementations that actually track leap seconds correctly. Because
+ | * of the manner in which leap seconds are currently introduced, it is
+ | * extremely unlikely that two leap seconds will occur in the same
+ | * minute, but this specification follows the date and time conventions
+ | * for ISO C.
+ | * </ul>
+ | * <p>
+ | * In all cases, arguments given to methods for these purposes need
+ | * not fall within the indicated ranges; for example, a date may be
+ | * specified as January 32 and is interpreted as meaning February 1.
+ | *
+ | * @author James Gosling
+ | * @author Arthur van Hoff
+ | * @author Alan Liu
+ | * @see java.text.DateFormat
+ | * @see java.util.Calendar
+ | * @since JDK1.0
+ | * @apiSince 1
+ | */
+ |public class Date2 implements java.io.Serializable, java.lang.Cloneable, java.lang.Comparable<java.util.Date> {
+ | void x() { }
+ |}
+ """.trimIndent(),
+ configuration
+ ) {
+ documentablesMergingStage = testOperation
+ }
+ }
+
+ @Test
+ fun `correctly parsed list`() {
+ performJavadocTest { module ->
+ val dateDescription = module.descriptionOf("Date2")!!
+ assertEquals(6, dateDescription.firstChildOfType<Ul>().children.filterIsInstance<Li>().size)
+ }
+ }
+
+ @Test
+ fun `correctly parsed author tags`() {
+ performJavadocTest { module ->
+ val authors = module.findClasslike().documentation.values.single().childrenOfType<Author>()
+ assertEquals(3, authors.size)
+ assertEquals("James Gosling", authors[0].firstChildOfType<Text>().text())
+ assertEquals("Arthur van Hoff", authors[1].firstChildOfType<Text>().text())
+ assertEquals("Alan Liu", authors[2].firstChildOfType<Text>().text())
+ }
+ }
+
+ @Test
+ fun `correctly parsed see tags`() {
+ performJavadocTest { module ->
+ val sees = module.findClasslike().documentation.values.single().childrenOfType<See>()
+ assertEquals(2, sees.size)
+ assertEquals(DRI("java.text", "DateFormat"), sees[0].address)
+ assertEquals("java.text.DateFormat", sees[0].name)
+ assertEquals(DRI("java.util", "Calendar"), sees[1].address)
+ assertEquals("java.util.Calendar", sees[1].name)
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/translators/utils.kt b/plugins/base/src/test/kotlin/translators/utils.kt
index 96d3035a..71b4a28b 100644
--- a/plugins/base/src/test/kotlin/translators/utils.kt
+++ b/plugins/base/src/test/kotlin/translators/utils.kt
@@ -1,16 +1,40 @@
package translators
-import org.jetbrains.dokka.model.DModule
+import org.jetbrains.dokka.model.*
import org.jetbrains.dokka.model.doc.Description
import org.jetbrains.dokka.model.doc.Text
+import java.util.NoSuchElementException
-fun DModule.documentationOf(className: String, functionName: String): String {
- return (packages.single()
- .classlikes.single { it.name == className }
- .functions.single { it.name == functionName }
- .documentation.values.singleOrNull()
- ?.children?.singleOrNull()
- .run { this as? Description }
- ?.root?.children?.single() as? Text)
+fun DModule.documentationOf(className: String, functionName: String? = null): String =
+ descriptionOf(className, functionName)
+ ?.firstChildOfType<Text>()
?.body.orEmpty()
+
+fun DModule.descriptionOf(className: String, functionName: String? = null): Description? {
+ val classlike = packages.single()
+ .classlikes.single { it.name == className }
+ val target: Documentable =
+ if (functionName != null) classlike.functions.single { it.name == functionName } else classlike
+ return target.documentation.values.singleOrNull()
+ ?.firstChildOfTypeOrNull<Description>()
+}
+
+fun DModule.findPackage(packageName: String? = null) =
+ packageName?.let { packages.firstOrNull { pkg -> pkg.name == packageName }
+ ?: throw NoSuchElementException("No packageName with name $packageName") } ?: packages.single()
+
+fun DModule.findClasslike(packageName: String? = null, className: String? = null): DClasslike {
+ val pkg = findPackage(packageName)
+ return className?.let {
+ pkg.classlikes.firstOrNull { cls -> cls.name == className }
+ ?: throw NoSuchElementException("No classlike with name $className")
+ } ?: pkg.classlikes.single()
+}
+
+fun DModule.findFunction(packageName: String? = null, className: String, functionName: String? = null): DFunction {
+ val classlike = findClasslike(packageName, className)
+ return functionName?.let {
+ classlike.functions.firstOrNull { fn -> fn.name == functionName }
+ ?: throw NoSuchElementException("No classlike with name $functionName")
+ } ?: classlike.functions.single()
} \ No newline at end of file
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt
index 8b86fab0..b3bb49d3 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt
@@ -66,7 +66,8 @@ open class JavadocPageCreator(
)
},
documentable = c,
- extra = ((c as? WithExtraProperties<Documentable>)?.extra ?: PropertyContainer.empty()) + c.indexesInDocumentation()
+ extra = ((c as? WithExtraProperties<Documentable>)?.extra
+ ?: PropertyContainer.empty()) + c.indexesInDocumentation()
)
}
@@ -142,6 +143,7 @@ open class JavadocPageCreator(
dri = dri,
signature = signatureForNode(this, jvm),
brief = brief(jvm),
+ description = descriptionToContentNodes(jvm),
parameters = parameters.mapNotNull {
val signature = signatureForNode(it, jvm)
signature.modifiers?.let { type ->
@@ -194,16 +196,21 @@ open class JavadocPageCreator(
briefFromContentNodes(descriptionToContentNodes(sourceSet))
private fun briefFromContentNodes(description: List<ContentNode>): List<ContentNode> {
- val contents = mutableListOf<ContentNode>()
- for (node in description) {
+ var sentenceFound = false
+ fun lookthrough(node: ContentNode): ContentNode =
if (node is ContentText && firstSentenceRegex.containsMatchIn(node.text)) {
- contents.add(node.copy(text = firstSentenceRegex.find(node.text)?.value.orEmpty()))
- break
+ 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
+ }, style = node.style - TextStyle.Paragraph)
} else {
- contents.add(node)
+ node
}
+ return description.mapNotNull {
+ if (!sentenceFound) lookthrough(it) else null
}
- return contents
}
private fun DParameter.brief(sourceSet: DokkaSourceSet? = highestJvmSourceSet): List<ContentNode> =
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt
index 7f27ff18..e0a7768c 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt
@@ -66,7 +66,7 @@ class JavadocLocationProvider(pageRoot: RootPageNode, dokkaContext: DokkaContext
override fun resolve(dri: DRI, sourceSets: Set<DokkaSourceSet>, context: PageNode?): String {
return nodeIndex[dri]?.let { resolve(it, context) }
- ?: nodeIndex[dri.parent]?.let {
+ ?: nodeIndex[dri.parent]?.takeIf { it is JavadocClasslikePageNode }?.let {
val anchor = when (val anchorElement = (it as? JavadocClasslikePageNode)?.findAnchorableByDRI(dri)) {
is JavadocFunctionNode -> anchorElement.getAnchor()
is JavadocEntryNode -> anchorElement.name
@@ -80,7 +80,8 @@ class JavadocLocationProvider(pageRoot: RootPageNode, dokkaContext: DokkaContext
private fun JavadocFunctionNode.getAnchor(): String =
"$name(${parameters.joinToString(",") {
- when (val bound = if (it.typeBound is org.jetbrains.dokka.model.Nullable) it.typeBound.inner else it.typeBound) {
+ when (val bound =
+ if (it.typeBound is org.jetbrains.dokka.model.Nullable) it.typeBound.inner else it.typeBound) {
is TypeConstructor -> bound.dri.classNames.orEmpty()
is OtherParameter -> bound.name
is PrimitiveJavaType -> bound.name
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt
index 790e15c5..ec4591c3 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt
@@ -115,6 +115,7 @@ data class JavadocPropertyNode(
data class JavadocFunctionNode(
val signature: JavadocSignatureContentNode,
val brief: List<ContentNode>,
+ val description: List<ContentNode>,
val parameters: List<JavadocParameterNode>,
val name: String,
override val dri: DRI,
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToHtmlTranslator.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToHtmlTranslator.kt
index 906c9d5a..1e9a3d65 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToHtmlTranslator.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToHtmlTranslator.kt
@@ -14,37 +14,51 @@ internal class JavadocContentToHtmlTranslator(
fun htmlForContentNode(node: ContentNode, relative: PageNode?): String =
when (node) {
- is ContentGroup -> htmlForContentNodes(node.children, node.style, relative)
- is ContentText -> buildText(node)
- is ContentDRILink -> buildLink(
- locationProvider.resolve(node.address, node.sourceSets, relative),
- htmlForContentNodes(node.children, node.style, relative)
- )
- is ContentResolvedLink -> buildLink(node.address, htmlForContentNodes(node.children, node.style, relative))
- is ContentCode -> htmlForCode(node.children)
+ is ContentGroup ->
+ if (node.style.contains(TextStyle.Paragraph)) htmlForParagraph(node.children, relative)
+ else htmlForContentNodes(node.children, relative)
+ is ContentText -> htmlForText(node)
+ is ContentDRILink -> buildLinkFromNode(node, relative)
+ is ContentResolvedLink -> buildLinkFromNode(node, relative)
+ is ContentCode -> htmlForCode(node.children, relative)
+ is ContentList -> htmlForList(node.children, relative)
is JavadocSignatureContentNode -> htmlForSignature(node, relative)
+ is ContentBreakLine -> "<br>"
else -> ""
}
- fun htmlForContentNodes(list: List<ContentNode>, styles: Set<Style>, relative: PageNode?) =
- list.joinToString(separator = "") { htmlForContentNode(it, relative) }
-
- private fun buildText(node: ContentText): String {
+ fun htmlForText(node: ContentText): String {
val escapedText = node.text.htmlEscape()
- return if (node.style.contains(ContentStyle.InDocumentationAnchor)) {
- """<em><a id="$escapedText" class="searchTagResult">${escapedText}</a></em>"""
- } else {
- escapedText
+ return when {
+ node.style.contains(ContentStyle.InDocumentationAnchor) -> """<em><a id="$escapedText" class="searchTagResult">${escapedText}</a></em>"""
+ node.style.contains(TextStyle.Bold) -> "<b>$escapedText</b>"
+ node.style.contains(TextStyle.Italic) -> "<i>$escapedText</i>"
+ node.style.contains(TextStyle.Strikethrough) -> "<del>$escapedText</del>"
+ else -> node.text.htmlEscape()
}
}
- private fun htmlForCode(code: List<ContentNode>): String = code.map { element ->
- when (element) {
- is ContentText -> element.text
+ fun htmlForContentNodes(list: List<ContentNode>, relative: PageNode?) =
+ list.joinToString(separator = "") { htmlForContentNode(it, relative) }
+
+ private fun htmlForParagraph(nodes: List<ContentNode>, relative: PageNode?) =
+ "<p>${htmlForContentNodes(nodes, relative)}</p>"
+
+ private fun htmlForCode(code: List<ContentNode>, relative: PageNode?): String {
+ fun nodeToText(node: ContentNode): String = when (node) {
+ is ContentText -> node.text
is ContentBreakLine -> ""
- else -> run { context.logger.error("Cannot cast $element as ContentText!"); "" }
+ is ContentDRILink -> buildLinkFromNode(node, relative)
+ is ContentResolvedLink -> buildLinkFromNode(node, relative)
+ is ContentCode -> node.children.joinToString("") { nodeToText(it) }
+ else -> run { context.logger.error("Cannot cast $node as ContentText!"); "" }
}
- }.joinToString("<br>", """<span class="code">""", "</span>") { it }
+ return code.map(::nodeToText).joinToString("<br>", """<code>""", "</code>") { it }
+ }
+
+ private fun htmlForList(elements: List<ContentNode>, relative: PageNode?) =
+ elements.filterIsInstance<ContentGroup>()
+ .joinToString("", "<ul>", "</ul>") { "<li>${htmlForContentNode(it, relative)}</li>" }
private fun htmlForSignature(node: JavadocSignatureContentNode, relative: PageNode?): String =
listOfNotNull(
@@ -54,6 +68,15 @@ internal class JavadocContentToHtmlTranslator(
node.supertypes
).joinToString(separator = " ") { htmlForContentNode(it, relative) }
+ private fun buildLinkFromNode(node: ContentDRILink, relative: PageNode?) =
+ buildLink(
+ locationProvider.resolve(node.address, node.sourceSets, relative),
+ htmlForContentNodes(node.children, relative)
+ )
+
+ private fun buildLinkFromNode(node: ContentResolvedLink, relative: PageNode?) =
+ buildLink(node.address, htmlForContentNodes(node.children, relative))
+
companion object {
fun buildLink(address: String, content: String) =
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
index 1a286095..57255cf1 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
@@ -72,22 +72,21 @@ internal class JavadocContentToTemplateMapTranslator(
)
}
- fun templateMapForPackagePageNode(node: JavadocPackagePageNode): TemplateMap {
- return mapOf(
+ fun templateMapForPackagePageNode(node: JavadocPackagePageNode): TemplateMap =
+ mapOf(
"kind" to "package"
) + templateMapForJavadocContentNode(node.content)
- }
- fun templateMapForFunctionNode(node: JavadocFunctionNode): TemplateMap {
- return mapOf(
+ fun templateMapForFunctionNode(node: JavadocFunctionNode): TemplateMap =
+ mapOf(
"brief" to htmlForContentNodes(node.brief, contextNode),
+ "description" to htmlForContentNodes(node.description, contextNode),
"parameters" to node.parameters.map { templateMapForParameterNode(it) },
"inlineParameters" to node.parameters.joinToString { renderInlineParameter(it) },
"anchorLink" to locationProvider.anchorForFunctionNode(node),
"signature" to templateMapForSignatureNode(node.signature),
"name" to node.name
)
- }
fun templateMapForClasslikeNode(node: JavadocClasslikePageNode): TemplateMap =
mapOf(
@@ -214,7 +213,7 @@ internal class JavadocContentToTemplateMapTranslator(
htmlTranslator.htmlForContentNode(node, relativeNode)
private fun htmlForContentNodes(nodes: List<ContentNode>, relativeNode: PageNode) =
- htmlTranslator.htmlForContentNodes(nodes, emptySet(), relativeNode)
+ htmlTranslator.htmlForContentNodes(nodes, relativeNode)
}
private fun DRI.displayable(): String = "${packageName}.${sureClassNames}"
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt
index 092fed2c..7826e590 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt
@@ -119,7 +119,7 @@ class KorteJavadocRenderer(private val outputWriter: OutputWriter, val context:
(buildLink(
locationProvider.resolve(link, contextRoot),
link.name
- ) to contentToHtmlTranslator.htmlForContentNodes(doc, emptySet(), contextRoot)).pairToTag().trim()
+ ) to contentToHtmlTranslator.htmlForContentNodes(doc, contextRoot)).pairToTag().trim()
},
TeFunction("createListRow") { args ->
val link = args.first() as LinkJavadocListEntry
diff --git a/plugins/javadoc/src/main/resources/views/class.korte b/plugins/javadoc/src/main/resources/views/class.korte
index ddaadc3a..048a479e 100644
--- a/plugins/javadoc/src/main/resources/views/class.korte
+++ b/plugins/javadoc/src/main/resources/views/class.korte
@@ -270,7 +270,7 @@
<li class="blockList">
<h4>{{ method.name }}</h4>
<pre class="methodSignature">{{ method.signature.annotations|raw }} {{ method.signature.modifiers|raw }} {{ method.signature.signatureWithoutModifiers|raw}}</pre>
- <div class="block">{{ method.brief|raw }}</div>
+ <div class="block">{{ method.description|raw }}</div>
{% if method.parameters.size != 0 && hasAnyDescription(method.parameters) %}
<dl>
<dt><span class="paramLabel">Parameters:</span></dt>
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
index 18bc69ff..463ad7fd 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
@@ -33,7 +33,7 @@ internal class JavadocClasslikeTemplateMapTest : AbstractJavadocTemplateMapTest(
assertEquals("TestClass", map["name"])
assertEquals("TestClass", map["title"])
assertEquals("com.test.package0", map["packageName"])
- assertEquals("Documentation for TestClass", map["classlikeDocumentation"])
+ assertEquals("<p>Documentation for TestClass</p>", map["classlikeDocumentation"])
assertEquals("Documentation for TestClass", map["subtitle"])
assertEquals("public final class <a href=TestClass.html>TestClass</a>", map.signatureWithModifiers())
}
@@ -78,7 +78,7 @@ internal class JavadocClasslikeTemplateMapTest : AbstractJavadocTemplateMapTest(
assertEquals("TestClass", map["name"])
assertEquals("TestClass", map["title"])
assertEquals("com.test.package0", map["packageName"])
- assertEquals("Documentation for TestClass", map["classlikeDocumentation"])
+ assertEquals("<p>Documentation for TestClass</p>", map["classlikeDocumentation"])
assertEquals("Documentation for TestClass", map["subtitle"])
assertEquals("public final class", map.modifiers())
assertEquals("<a href=TestClass.html>TestClass</a>", map.signatureWithoutModifiers())
@@ -200,8 +200,8 @@ internal class JavadocClasslikeTemplateMapTest : AbstractJavadocTemplateMapTest(
assertEquals(2, entries.size)
val (first, second) = entries
- assertEquals("Sample docs for first", first["brief"])
- assertEquals("Sample docs for second", second["brief"])
+ assertEquals("<p>Sample docs for first</p>", first["brief"])
+ assertEquals("<p>Sample docs for second</p>", second["brief"])
assertEquals("<a href=ClockDays.html#FIRST>FIRST</a>", first.signatureWithoutModifiers())
assertEquals("<a href=ClockDays.html#SECOND>SECOND</a>", second.signatureWithoutModifiers())