aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin/parsers
diff options
context:
space:
mode:
authorVadim Mishenev <vad-mishenev@yandex.ru>2022-04-11 18:22:44 +0300
committerGitHub <noreply@github.com>2022-04-11 18:22:44 +0300
commitc59d6ef872186d185318c2bdcedabf9eaaa7b8ca (patch)
tree0ed30277d90a82beb9be91b296d572fc4560d74f /plugins/base/src/main/kotlin/parsers
parent2f0a259a5f07ebe41e9a5510b3684d95bc40b95f (diff)
downloaddokka-c59d6ef872186d185318c2bdcedabf9eaaa7b8ca.tar.gz
dokka-c59d6ef872186d185318c2bdcedabf9eaaa7b8ca.tar.bz2
dokka-c59d6ef872186d185318c2bdcedabf9eaaa7b8ca.zip
Fix using `@` symbol inside code block (#2418)
Diffstat (limited to 'plugins/base/src/main/kotlin/parsers')
-rw-r--r--plugins/base/src/main/kotlin/parsers/Parser.kt81
1 files changed, 77 insertions, 4 deletions
diff --git a/plugins/base/src/main/kotlin/parsers/Parser.kt b/plugins/base/src/main/kotlin/parsers/Parser.kt
index 960d7a64..af07ec53 100644
--- a/plugins/base/src/main/kotlin/parsers/Parser.kt
+++ b/plugins/base/src/main/kotlin/parsers/Parser.kt
@@ -1,6 +1,8 @@
package org.jetbrains.dokka.base.parsers
import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.model.doc.Deprecated
+import org.jetbrains.dokka.model.doc.Suppress
abstract class Parser {
@@ -9,7 +11,7 @@ abstract class Parser {
abstract fun preparse(text: String): String
open fun parse(text: String): DocumentationNode =
- DocumentationNode(jkdocToListOfPairs(preparse(text)).map { (tag, content) -> parseTagWithBody(tag, content) })
+ DocumentationNode(extractTagsToListOfPairs(preparse(text)).map { (tag, content) -> parseTagWithBody(tag, content) })
open fun parseTagWithBody(tagName: String, content: String): TagWrapper =
when (tagName) {
@@ -47,12 +49,83 @@ abstract class Parser {
else -> CustomTagWrapper(parseStringToDocNode(content), tagName)
}
- private fun jkdocToListOfPairs(javadoc: String): List<Pair<String, String>> =
- "description $javadoc"
- .split("\n@")
+ /**
+ * KDoc parser from Kotlin compiler relies on a comment asterisk
+ * So there is a mini parser here
+ * TODO: at least to adapt [org.jetbrains.kotlin.kdoc.lexer.KDocLexer] to analyze KDoc without the asterisks and use it here
+ */
+ private fun extractTagsToListOfPairs(text: String): List<Pair<String, String>> =
+ "description $text"
+ .extractKDocSections()
.map { content ->
val contentWithEscapedAts = content.replace("\\@", "@")
val (tag, body) = contentWithEscapedAts.split(" ", limit = 2)
tag to body
}
+
+ /**
+ * Ignore a doc tag inside code spans and blocks
+ * @see org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
+ */
+ private fun CharSequence.extractKDocSections(delimiter: String = "\n@"): List<String> {
+ var countOfBackticks = 0
+ var countOfTildes = 0
+ var countOfBackticksInOpeningFence = 0
+ var countOfTildesInOpeningFence = 0
+
+ var isInCode = false
+ val result = mutableListOf<String>()
+ var rangeStart = 0
+ var rangeEnd = 0
+ var currentOffset = 0
+ while (currentOffset < length) {
+
+ when (get(currentOffset)) {
+ '`' -> {
+ countOfBackticks++
+ countOfTildes = 0
+ }
+ '~' -> {
+ countOfTildes++
+ countOfBackticks = 0
+ }
+ else -> {
+ if (isInCode) {
+ // The closing code fence must be at least as long as the opening fence
+ if(countOfBackticks >= countOfBackticksInOpeningFence
+ || countOfTildes >= countOfTildesInOpeningFence)
+ isInCode = false
+ } else {
+ // as per CommonMark spec, there can be any number of backticks for a code span, not only one or three
+ if (countOfBackticks > 0) {
+ isInCode = true
+ countOfBackticksInOpeningFence = countOfBackticks
+ countOfTildesInOpeningFence = Int.MAX_VALUE
+ }
+ // tildes are only for a code block, not code span
+ if (countOfTildes >= 3) {
+ isInCode = true
+ countOfTildesInOpeningFence = countOfTildes
+ countOfBackticksInOpeningFence = Int.MAX_VALUE
+ }
+ }
+ countOfTildes = 0
+ countOfBackticks = 0
+ }
+ }
+ if (!isInCode && startsWith(delimiter, currentOffset)) {
+ result.add(substring(rangeStart, rangeEnd))
+ currentOffset += delimiter.length
+ rangeStart = currentOffset
+ rangeEnd = currentOffset
+ continue
+ }
+
+ ++rangeEnd
+ ++currentOffset
+ }
+ result.add(substring(rangeStart, rangeEnd))
+ return result
+ }
+
}