reduce vertical whitespace in rendered KDoc comments

This commit is contained in:
Dmitry Jemerov
2015-07-29 15:49:52 +02:00
parent b483713f2c
commit 6d1ccc22ab
16 changed files with 35 additions and 50 deletions
@@ -130,7 +130,13 @@ public class KotlinQuickDocumentationProvider : AbstractDocumentationProvider()
}
val comment = KDocFinder.findKDoc(declarationDescriptor)
if (comment != null) {
renderedDecl = renderedDecl + "<br/>" + KDocRenderer.renderKDoc(comment)
val renderedComment = KDocRenderer.renderKDoc(comment)
if (renderedComment.startsWith("<p>")) {
renderedDecl += renderedComment
}
else {
renderedDecl = "$renderedDecl<br/>$renderedComment"
}
}
return renderedDecl
@@ -29,8 +29,8 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
object KDocRenderer {
fun renderKDoc(docComment: KDocTag): String {
val content = docComment.getContent()
val result = StringBuilder("<p>")
result.append(markdownToHtml(content))
val result = StringBuilder()
result.append(markdownToHtml(content, allowSingleParagraph = true))
if (docComment is KDocSection) {
result.append("\n")
val paramTags = docComment.findTagsByName("param").filter { it.getSubjectName() != null }
@@ -47,7 +47,6 @@ object KDocRenderer {
renderSeeAlso(docComment, result)
}
result.append("</p>")
return result.toString()
}
@@ -85,13 +84,13 @@ object KDocRenderer {
}
}
fun markdownToHtml(markdown: String): String {
fun markdownToHtml(markdown: String, allowSingleParagraph: Boolean = false): String {
val markdownTree = MarkdownParser(CommonMarkMarkerProcessor.Factory).buildMarkdownTreeFromString(markdown)
val markdownNode = MarkdownNode(markdownTree, null, markdown)
// Avoid wrapping the entire converted contents in a <p> tag if it's just a single paragraph
val maybeSingleParagraph = markdownNode.children.filter { it.type != MarkdownTokenTypes.EOL }.singleOrNull()
if (maybeSingleParagraph != null) {
if (maybeSingleParagraph != null && !allowSingleParagraph) {
return maybeSingleParagraph.children.map { it.toHtml() }.join("")
} else {
return markdownNode.toHtml()
@@ -120,7 +119,6 @@ object KDocRenderer {
visit { node, processChildren ->
fun wrapChildren(tag: String, newline: Boolean = false) {
sb.append("<$tag>")
if (newline) sb.appendln()
processChildren()
sb.append("</$tag>")
if (newline) sb.appendln()
@@ -142,13 +140,13 @@ object KDocRenderer {
MarkdownElementTypes.ATX_6 -> wrapChildren("h6")
MarkdownElementTypes.BLOCK_QUOTE -> wrapChildren("blockquote")
MarkdownElementTypes.PARAGRAPH -> {
sb.trimTrailing()
sb.trimEnd()
wrapChildren("p", newline = true)
}
MarkdownElementTypes.CODE_SPAN -> wrapChildren("code")
MarkdownElementTypes.CODE_BLOCK,
MarkdownElementTypes.CODE_FENCE -> {
sb.trimTrailing()
sb.trimEnd()
sb.append("<pre><code>")
processChildren()
sb.append("</code><pre>")
@@ -168,7 +166,7 @@ object KDocRenderer {
val label = node.child(MarkdownElementTypes.LINK_TEXT)?.child(MarkdownTokenTypes.TEXT)?.text
val destination = node.child(MarkdownElementTypes.LINK_DESTINATION)?.text
if (label != null && destination != null) {
sb.append("a href=\"${destination}\">${label.htmlEscape()}</a>")
sb.append("<a href=\"$destination\">${label.htmlEscape()}</a>")
}
else {
sb.append(node.text)
@@ -202,10 +200,10 @@ object KDocRenderer {
}
}
}
return sb.toString()
return sb.toString().trimEnd()
}
fun StringBuilder.trimTrailing() {
fun StringBuilder.trimEnd() {
while (length() > 0 && this[length() - 1] == ' ') {
deleteCharAt(length() - 1)
}
+1 -2
View File
@@ -6,5 +6,4 @@ class KotlinClassUsedFromJava {
}
}
//INFO: <b>internal</b> <b>final</b> <b>class</b> Test <i>defined in</i> testing<br/><p>Some comment
//INFO: </p>
//INFO: <b>internal</b> <b>final</b> <b>class</b> Test <i>defined in</i> testing<p>Some comment</p>
+1 -2
View File
@@ -2,5 +2,4 @@ fun test() {
listOf(1, 2, 4).<caret>filter { it > 0 }
}
//INFO: inline <b>public</b> <b>fun</b> &lt;T&gt; Iterable&lt;T&gt;.filter(predicate: (T) &rarr; Boolean): List&lt;T&gt; <i>defined in</i> kotlin<br/><p>Returns a list containing all elements matching the given <a href="psi_element://predicate">predicate</a>.
//INFO: </p>
//INFO: inline <b>public</b> <b>fun</b> &lt;T&gt; Iterable&lt;T&gt;.filter(predicate: (T) &rarr; Boolean): List&lt;T&gt; <i>defined in</i> kotlin<p>Returns a list containing all elements matching the given <a href="psi_element://predicate">predicate</a>.</p>
@@ -3,5 +3,4 @@
*/
class <caret>Some
//INFO: <b>internal</b> <b>final</b> <b>class</b> Some <i>defined in</i> root package<br/><p>Usefull comment
//INFO: </p>
//INFO: <b>internal</b> <b>final</b> <b>class</b> Some <i>defined in</i> root package<p>Usefull comment</p>
@@ -12,6 +12,5 @@ package test
*/
fun <caret>testFun(first: String, second: Int) = 12
//INFO: <b>internal</b> <b>fun</b> testFun(first: String, second: Int): Int <i>defined in</i> test<br/><p>Test function
//INFO: <b>internal</b> <b>fun</b> testFun(first: String, second: Int): Int <i>defined in</i> test<p>Test function</p>
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>first</code> - Some</dd><dd><code>second</code> - Other</dd></dl>
//INFO: </p>
+1 -2
View File
@@ -14,5 +14,4 @@ fun test() {
D().f<caret>oo()
}
//INFO: <b>internal</b> <b>open</b> <b>fun</b> foo(): Int <i>defined in</i> D<br/><p>This method returns zero.
//INFO: </p>
//INFO: <b>internal</b> <b>open</b> <b>fun</b> foo(): Int <i>defined in</i> D<p>This method returns zero.</p>
+1 -2
View File
@@ -14,5 +14,4 @@ fun test() {
D().f<caret>oo
}
//INFO: <b>internal</b> <b>open</b> <b>val</b> foo: Int <i>defined in</i> D<br/><p>This property returns zero.
//INFO: </p>
//INFO: <b>internal</b> <b>open</b> <b>val</b> foo: Int <i>defined in</i> D<p>This property returns zero.</p>
+1 -2
View File
@@ -12,6 +12,5 @@ fun test() {
<caret>testMethod(1, "value")
}
//INFO: <b>internal</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package<br/><p>Some documentation
//INFO: <b>internal</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package<p>Some documentation</p>
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>a</code> - Some int</dd><dd><code>b</code> - String</dd></dl>
//INFO: </p>
+1 -2
View File
@@ -10,5 +10,4 @@ fun test() {
<caret>testMethod()
}
//INFO: <b>internal</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package<br/><p>Some documentation on two lines.
//INFO: </p>
//INFO: <b>internal</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package<p>Some documentation on two lines.</p>
@@ -12,6 +12,5 @@ fun test() {
<caret>testMethod(1, "value")
}
//INFO: <b>internal</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package<br/><p>Some documentation
//INFO: <b>internal</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package<p>Some documentation</p>
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>a</code> - Some int</dd><dd><code>b</code> - String</dd></dl>
//INFO: </p>
@@ -17,10 +17,8 @@ fun test() {
<caret>testMethod(1, "value")
}
//INFO: <b>internal</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package<br/><p><p>
//INFO: Some documentation.</p>
//INFO: <pre><code>
//INFO: <b>internal</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package<p>Some documentation.</p>
//INFO: <pre><code>
//INFO: Code block
//INFO: Second line
//INFO: </code><pre>
//INFO: </p>
+4 -10
View File
@@ -18,13 +18,7 @@ fun test() {
<caret>testMethod(1, "value")
}
//INFO: <b>internal</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package<br/><p><p>
//INFO: Some documentation. <strong>Bold</strong> <em>underline</em> <code>code</code> foo: bar (baz) <a href="psi_element://quux">quux</a> 'apos'</p>
//INFO: <p>
//INFO: a href="http://www.kotlinlang.org">Kotlin</a></p>
//INFO: <p>
//INFO: <a href="psi_element://C">C</a></p>
//INFO: <p>
//INFO: <a href="psi_element://C">See this class</a></p>
//INFO:
//INFO: </p>
//INFO: <b>internal</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package<p>Some documentation. <strong>Bold</strong> <em>underline</em> <code>code</code> foo: bar (baz) <a href="psi_element://quux">quux</a> 'apos'</p>
//INFO: <p><a href="http://www.kotlinlang.org">Kotlin</a></p>
//INFO: <p><a href="psi_element://C">C</a></p>
//INFO: <p><a href="psi_element://C">See this class</a></p>
@@ -14,8 +14,7 @@ fun test() {
<caret>testMethod(1, "value")
}
//INFO: <b>internal</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package<br/><p>Some documentation
//INFO: <b>internal</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package<p>Some documentation</p>
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>a</code> - Some int</dd><dd><code>b</code> - String</dd></dl>
//INFO: <dl><dt><b>Returns:</b></dt><dd>Return value</dd></dl>
//INFO: <dl><dt><b>Throws:</b></dt><dd><code>IllegalArgumentException</code> - if the weather is bad</dd></dl>
//INFO: </p>
+2 -2
View File
@@ -16,5 +16,5 @@ fun test() {
<caret>testMethod(1, "value")
}
//INFO: <b>internal</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package<br/><p>
//INFO: <DD><DL><DT><b>See Also:</b><DD><a href="psi_element://C"><code>C</code></a>, <a href="psi_element://D"><code>D</code></a></DD></DL></DD></p>
//INFO: <b>internal</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package<br/>
//INFO: <DD><DL><DT><b>See Also:</b><DD><a href="psi_element://C"><code>C</code></a>, <a href="psi_element://D"><code>D</code></a></DD></DL></DD>
+1 -2
View File
@@ -8,5 +8,4 @@ class Testing {
}
}
//INFO: <b>internal</b> <b>fun</b> foo(bar: Int): Unit <i>defined in</i> some<br/><p>KDoc foo
//INFO: </p>
//INFO: <b>internal</b> <b>fun</b> foo(bar: Int): Unit <i>defined in</i> some<p>KDoc foo</p>