Skip to content

Commit

Permalink
Fix using @ symbol inside code block
Browse files Browse the repository at this point in the history
  • Loading branch information
vmishenev committed Apr 4, 2022
1 parent 2372302 commit 4925335
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 6 deletions.
43 changes: 42 additions & 1 deletion 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 {

Expand Down Expand Up @@ -49,10 +51,49 @@ abstract class Parser {

private fun jkdocToListOfPairs(javadoc: String): List<Pair<String, String>> =
"description $javadoc"
.split("\n@")
.splitIgnoredInsideBackticks("\n@")
.map { content ->
val contentWithEscapedAts = content.replace("\\@", "@")
val (tag, body) = contentWithEscapedAts.split(" ", limit = 2)
tag to body
}

private fun CharSequence.splitIgnoredInsideBackticks(delimiter: String): List<String> {
var countOfBackticks = 0
var countOfBackticksInOpeningFence = 0

var isInCode = false
val result = mutableListOf<String>()
val buf = StringBuilder()
var currentOffset = 0
while (currentOffset < length) {

if (get(currentOffset) == '`') {
countOfBackticks++
} else {
if (isInCode) {
// The closing code fence must be at least as long as the opening fence
isInCode = countOfBackticks < countOfBackticksInOpeningFence
} else {
if (countOfBackticks > 0) {
isInCode = true
countOfBackticksInOpeningFence = countOfBackticks
}
}
countOfBackticks = 0
}
if (!isInCode && startsWith(delimiter, currentOffset)) {
result.add(buf.toString())
buf.clear()
currentOffset += delimiter.length
continue
}

buf.append(get(currentOffset))
++currentOffset
}
result.add(buf.toString())
return result
}

}
2 changes: 2 additions & 0 deletions plugins/base/src/test/kotlin/markdown/ParserTest.kt
Expand Up @@ -951,6 +951,7 @@ class ParserTest : KDocTest() {
fun `Multilined Code Block`() {
val kdoc = """
| ```kotlin
| @Suppress("UNUSED_VARIABLE")
| val x: Int = 0
| val y: String = "Text"
|
Expand All @@ -968,6 +969,7 @@ class ParserTest : KDocTest() {
listOf(
CodeBlock(
listOf(
Text("@Suppress(\"UNUSED_VARIABLE\")"), Br,
Text("val x: Int = 0"), Br,
Text("val y: String = \"Text\""), Br, Br,
Text(" val z: Boolean = true"), Br,
Expand Down
@@ -1,12 +1,11 @@
package parsers

import org.jetbrains.dokka.base.parsers.moduleAndPackage.IllegalModuleAndPackageDocumentation
import org.intellij.markdown.MarkdownElementTypes
import org.jetbrains.dokka.base.parsers.moduleAndPackage.*
import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumentation.Classifier.Module
import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumentation.Classifier.Package
import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumentationFile
import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumentationFragment
import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumentationSource
import org.jetbrains.dokka.base.parsers.moduleAndPackage.parseModuleAndPackageDocumentationFragments
import org.jetbrains.dokka.model.doc.*
import org.jetbrains.dokka.utilities.DokkaLogger
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
Expand Down Expand Up @@ -216,6 +215,64 @@ class ParseModuleAndPackageDocumentationFragmentsTest {
)
}

@Test
fun `at in code block is supported`() {
val fragment = parseModuleAndPackageDocumentationFragments(
source(
"""
# Module My Module
```
@Smth
```
@author Smb
""".trimIndent()
)
)

assertEquals(
"```\n" +
"@Smth\n" +
"```\n" +
"@author Smb", fragment.single().documentation,
"Expected documentation being available"
)

val parsingContext = ModuleAndPackageDocumentationParsingContext(object : DokkaLogger {
override var warningsCount: Int = 0
override var errorsCount: Int = 0
override fun debug(message: String) {}
override fun info(message: String) {}
override fun progress(message: String) {}
override fun warn(message: String) {}
override fun error(message: String) {}
})
val parsedFragment = parseModuleAndPackageDocumentation(parsingContext, fragment.single())
val expectedDocumentationNode = DocumentationNode(
listOf(
Description(
CustomDocTag(
listOf(
CodeBlock(
listOf(
Text("@Smth")
)
)
), name = MarkdownElementTypes.MARKDOWN_FILE.name
)
),
Author(
CustomDocTag(
listOf(
P(listOf(Text("Smb")))
), name = MarkdownElementTypes.MARKDOWN_FILE.name
)
)
)
)
assertEquals(
expectedDocumentationNode, parsedFragment.documentation
)
}

private fun source(documentation: String): ModuleAndPackageDocumentationSource =
object : ModuleAndPackageDocumentationSource() {
Expand Down

0 comments on commit 4925335

Please sign in to comment.