diff --git a/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocRenderer.kt b/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocRenderer.kt index 814e0b224465a..ac5b9b11b7071 100644 --- a/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocRenderer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocRenderer.kt @@ -90,7 +90,7 @@ object KDocRenderer { val markdownNode = MarkdownNode(markdownTree, null, markdown) // Avoid wrapping the entire converted contents in a

tag if it's just a single paragraph - val maybeSingleParagraph = markdownNode.children.filter { it.type == MarkdownElementTypes.PARAGRAPH }.singleOrNull() + val maybeSingleParagraph = markdownNode.children.filter { it.type != MarkdownTokenTypes.EOL }.singleOrNull() if (maybeSingleParagraph != null) { return maybeSingleParagraph.children.map { it.toHtml() }.join("") } else { @@ -142,13 +142,13 @@ object KDocRenderer { MarkdownElementTypes.ATX_6 -> wrapChildren("h6") MarkdownElementTypes.BLOCK_QUOTE -> wrapChildren("blockquote") MarkdownElementTypes.PARAGRAPH -> { - while (sb.length() > 0 && sb[sb.length() - 1] == ' ') { - sb.deleteCharAt(sb.length() - 1) - } + sb.trimTrailing() wrapChildren("p", newline = true) } MarkdownElementTypes.CODE_SPAN -> wrapChildren("code") - MarkdownElementTypes.CODE_BLOCK -> { + MarkdownElementTypes.CODE_BLOCK, + MarkdownElementTypes.CODE_FENCE -> { + sb.trimTrailing() sb.append("

")
                     processChildren()
                     sb.append("
")
@@ -159,7 +159,8 @@ object KDocRenderer {
                     if (label != null) {
                         val linkText = node.child(MarkdownElementTypes.LINK_TEXT)?.child(MarkdownTokenTypes.TEXT)?.text ?: label
                         DocumentationManagerUtil.createHyperlink(sb, label, linkText, true)
-                    } else {
+                    }
+                    else {
                         sb.append(node.text)
                     }
                 }
@@ -168,11 +169,13 @@ object KDocRenderer {
                     val destination = node.child(MarkdownElementTypes.LINK_DESTINATION)?.text
                     if (label != null && destination != null) {
                         sb.append("a href=\"${destination}\">${label.htmlEscape()}")
-                    } else {
+                    }
+                    else {
                         sb.append(node.text)
                     }
                 }
                 MarkdownTokenTypes.TEXT,
+                MarkdownTokenTypes.CODE,
                 MarkdownTokenTypes.WHITE_SPACE,
                 MarkdownTokenTypes.COLON,
                 MarkdownTokenTypes.SINGLE_QUOTE,
@@ -184,7 +187,13 @@ object KDocRenderer {
                     sb.append(nodeText)
                 }
                 MarkdownTokenTypes.EOL -> {
-                    sb.append(" ")
+                    val parentType = node.parent?.type
+                    if (parentType == MarkdownElementTypes.CODE_BLOCK || parentType == MarkdownElementTypes.CODE_FENCE) {
+                        sb.append("\n")
+                    }
+                    else {
+                        sb.append(" ")
+                    }
                 }
                 MarkdownTokenTypes.GT -> sb.append(">")
                 MarkdownTokenTypes.LT -> sb.append("<")
@@ -196,5 +205,11 @@ object KDocRenderer {
         return sb.toString()
     }
 
+    fun StringBuilder.trimTrailing() {
+        while (length() > 0 && this[length() - 1] == ' ') {
+            deleteCharAt(length() - 1)
+        }
+    }
+
     fun String.htmlEscape(): String = replace("&", "&").replace("<", "<").replace(">", ">")
 }
diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithCodeBlock.kt b/idea/testData/editor/quickDoc/OnMethodUsageWithCodeBlock.kt
new file mode 100644
index 0000000000000..6a435c6507fc2
--- /dev/null
+++ b/idea/testData/editor/quickDoc/OnMethodUsageWithCodeBlock.kt
@@ -0,0 +1,26 @@
+/**
+ * Some documentation.
+ *
+ * ```
+ * Code block
+ * Second line
+ * ```
+ */
+fun testMethod() {
+
+}
+
+class C {
+}
+
+fun test() {
+    testMethod(1, "value")
+}
+
+//INFO: internal fun testMethod(): Unit defined in root package

+//INFO: Some documentation.

+//INFO:

+//INFO: Code block
+//INFO: Second line
+//INFO: 
+//INFO: 

diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/JetQuickDocProviderTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/JetQuickDocProviderTestGenerated.java index 0980bbdf440bb..0e37d1f28e6ea 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/JetQuickDocProviderTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/JetQuickDocProviderTestGenerated.java @@ -125,6 +125,12 @@ public void testOnMethodUsageWithBracketsInParam() throws Exception { doTest(fileName); } + @TestMetadata("OnMethodUsageWithCodeBlock.kt") + public void testOnMethodUsageWithCodeBlock() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/editor/quickDoc/OnMethodUsageWithCodeBlock.kt"); + doTest(fileName); + } + @TestMetadata("OnMethodUsageWithMarkdown.kt") public void testOnMethodUsageWithMarkdown() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/editor/quickDoc/OnMethodUsageWithMarkdown.kt");