Skip to content

Commit

Permalink
Support code fence of tildes
Browse files Browse the repository at this point in the history
  • Loading branch information
vmishenev committed Apr 11, 2022
1 parent 0dca3df commit 4666462
Showing 1 changed file with 46 additions and 16 deletions.
62 changes: 46 additions & 16 deletions plugins/base/src/main/kotlin/parsers/Parser.kt
Expand Up @@ -11,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) {
Expand Down Expand Up @@ -49,18 +49,29 @@ abstract class Parser {
else -> CustomTagWrapper(parseStringToDocNode(content), tagName)
}

private fun jkdocToListOfPairs(javadoc: String): List<Pair<String, String>> =
"description $javadoc"
.splitIgnoredInsideBackticks("\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 parse KDoc without the asterisks and use it here
*/
private fun extractTagsToListOfPairs(text: String): List<Pair<String, String>> =
"description $text"
.extractKDocSections("\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> {
/**
* Ignore a doc tag inside code spans and blocks
* @see org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
*/
private fun CharSequence.extractKDocSections(delimiter: String): List<String> {
var countOfBackticks = 0
var countOfTildes = 0
var countOfBackticksInOpeningFence = 0
var countOfTildesInOpeningFence = 0

var isInCode = false
val result = mutableListOf<String>()
Expand All @@ -69,19 +80,38 @@ abstract class Parser {
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
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
}
countOfBackticks = 0
}
if (!isInCode && startsWith(delimiter, currentOffset)) {
result.add(substring(rangeStart, rangeEnd))
Expand Down

0 comments on commit 4666462

Please sign in to comment.