From de809e8076b3cde06dc29328298112ed4a7026b3 Mon Sep 17 00:00:00 2001 From: Marcin Aman Date: Wed, 19 Aug 2020 20:09:12 +0200 Subject: Draft for improving code formatting #1346 --- .../base/src/main/kotlin/parsers/MarkdownParser.kt | 13 ++- .../src/main/kotlin/renderers/html/HtmlRenderer.kt | 4 +- .../pages/comments/DocTagToContentConverter.kt | 11 +-- .../main/kotlin/translators/psi/JavadocParser.kt | 14 +-- ...efaultDescriptorToDocumentableTranslatorTest.kt | 101 +++++++++++++++++---- .../test/kotlin/translators/JavadocParserTest.kt | 26 +++++- .../renderer/JavadocContentToHtmlTranslator.kt | 15 +-- 7 files changed, 132 insertions(+), 52 deletions(-) diff --git a/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt b/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt index 8422d3be..53ab6bde 100644 --- a/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt +++ b/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt @@ -280,11 +280,13 @@ class MarkdownParser( MarkdownElementTypes.IMAGE -> imagesHandler(node) MarkdownTokenTypes.HARD_LINE_BREAK -> DocTagsFromIElementFactory.getInstance(node.type) MarkdownTokenTypes.CODE_FENCE_CONTENT, - MarkdownTokenTypes.CODE_LINE, + MarkdownTokenTypes.CODE_LINE -> DocTagsFromIElementFactory.getInstance( + MarkdownTokenTypes.TEXT, + body = text.substring(node.startOffset, node.endOffset) + ) MarkdownTokenTypes.TEXT -> DocTagsFromIElementFactory.getInstance( MarkdownTokenTypes.TEXT, - body = text - .substring(node.startOffset, node.endOffset).transform() + body = text.substring(node.startOffset, node.endOffset).transform() ) MarkdownElementTypes.MARKDOWN_FILE -> if (node.children.size == 1) visitNode(node.children.first()) else defaultHandler( node @@ -339,11 +341,12 @@ class MarkdownParser( children += this[index] } else { val startOffset = this[index].startOffset + val type = this[index].type while (index < this.lastIndex) { if (this.isNotLeaf(index + 1) || this[index + 1].startOffset != this[index].endOffset) { val endOffset = this[index].endOffset if (text.substring(startOffset, endOffset).transform().trim().isNotEmpty()) - children += LeafASTNode(MarkdownTokenTypes.TEXT, startOffset, endOffset) + children += LeafASTNode(type, startOffset, endOffset) break } index++ @@ -351,7 +354,7 @@ class MarkdownParser( if (index == this.lastIndex) { val endOffset = this[index].endOffset if (text.substring(startOffset, endOffset).transform().trim().isNotEmpty()) - children += LeafASTNode(MarkdownTokenTypes.TEXT, startOffset, endOffset) + children += LeafASTNode(type, startOffset, endOffset) } } index++ diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt index 0118dcfd..878432b4 100644 --- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt +++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt @@ -604,7 +604,9 @@ open class HtmlRenderer( div("sample-container") { code(code.style.joinToString(" ") { it.toString().toLowerCase() }) { attributes["theme"] = "idea" - code.children.forEach { buildContentNode(it, pageContext) } + pre { + code.children.forEach { buildContentNode(it, pageContext) } + } } } } diff --git a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt index 0c88b3c6..51ab0858 100644 --- a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt +++ b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt @@ -102,7 +102,7 @@ object DocTagToContentConverter : CommentsToContentConverter { styles ) ) - is BlockQuote -> listOf( + is BlockQuote, is Pre, is CodeBlock -> listOf( ContentCodeBlock( buildChildren(docTag), "", @@ -120,15 +120,6 @@ object DocTagToContentConverter : CommentsToContentConverter { styles ) ) - is CodeBlock -> listOf( - ContentCodeBlock( - buildChildren(docTag), - "", - dci, - sourceSets.toDisplaySourceSets(), - styles - ) - ) is Img -> listOf( ContentEmbeddedResource( address = docTag.params["href"]!!, diff --git a/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt b/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt index 8262b3c6..b9c328dc 100644 --- a/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt +++ b/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt @@ -151,7 +151,7 @@ class JavadocParser( is PsiInlineDocTag -> convertInlineDocTag(this) is PsiDocParamRef -> toDocumentationLinkString() is PsiDocTagValue, - is LeafPsiElement -> (if ((prevSibling as? PsiDocToken)?.isLeadingAsterisk() == true) text?.trim() else text)?.takeUnless { it.isBlank() } + is LeafPsiElement -> text else -> null } @@ -190,8 +190,8 @@ class JavadocParser( } } - private fun createBlock(element: Element): DocTag? { - val children = element.childNodes().mapNotNull { convertHtmlNode(it) } + private fun createBlock(element: Element, insidePre: Boolean = false): DocTag? { + val children = element.childNodes().mapNotNull { convertHtmlNode(it, insidePre = insidePre || element.tagName() == "pre") } fun ifChildrenPresent(operation: () -> DocTag): DocTag? { return if (children.isNotEmpty()) operation() else null } @@ -203,11 +203,7 @@ class JavadocParser( "index" -> Index(children) "i" -> ifChildrenPresent { I(children) } "em" -> Em(children) - "code" -> ifChildrenPresent { - if (element.hasAttr("data-inline")) CodeInline(children) else CodeBlock( - children - ) - } + "code" -> ifChildrenPresent { CodeInline(children) } "pre" -> Pre(children) "ul" -> ifChildrenPresent { Ul(children) } "ol" -> ifChildrenPresent { Ol(children) } @@ -224,7 +220,7 @@ class JavadocParser( } override fun invoke(elements: Iterable, asParagraph: Boolean): List = - Jsoup.parseBodyFragment(elements.mapNotNull { it.stringify() }.joinToString(" ", prefix = if (asParagraph) "

" else "")) + Jsoup.parseBodyFragment(elements.mapNotNull { it.stringify() }.joinToString("\n", prefix = if (asParagraph) "

" else "")) .body().childNodes().mapNotNull { convertHtmlNode(it) } } diff --git a/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt b/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt index b0754429..8a8af626 100644 --- a/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt +++ b/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt @@ -1,21 +1,23 @@ package translators +import org.junit.jupiter.api.Assertions.* +import org.jetbrains.dokka.model.doc.CodeBlock +import org.jetbrains.dokka.model.doc.P +import org.jetbrains.dokka.model.doc.Text import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest -import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test class DefaultDescriptorToDocumentableTranslatorTest : AbstractCoreTest() { - - @Test - fun `data class kdocs over generated methods`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } + val configuration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/main/kotlin") } } + } + @Test + fun `data class kdocs over generated methods`() { testInline( """ |/src/main/kotlin/sample/XD.kt @@ -39,7 +41,12 @@ class DefaultDescriptorToDocumentableTranslatorTest : AbstractCoreTest() { ) { documentablesMergingStage = { module -> assert(module.documentationOf("XD", "copy") == "") - assert(module.documentationOf("XD", "equals") == "Memory is not what the heart desires. That is only a mirror.") + assert( + module.documentationOf( + "XD", + "equals" + ) == "Memory is not what the heart desires. That is only a mirror." + ) assert(module.documentationOf("XD", "hashCode") == "") assert(module.documentationOf("XD", "toString") == "") assert(module.documentationOf("XD", "custom") == "But the fat Hobbit, he knows. Eyes always watching.") @@ -49,14 +56,6 @@ class DefaultDescriptorToDocumentableTranslatorTest : AbstractCoreTest() { @Test fun `simple class kdocs`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - testInline( """ |/src/main/kotlin/sample/XD.kt @@ -80,7 +79,71 @@ class DefaultDescriptorToDocumentableTranslatorTest : AbstractCoreTest() { ) { documentablesMergingStage = { module -> assert(module.documentationOf("XD", "custom") == "But the fat Hobbit, he knows. Eyes always watching.") - assert(module.documentationOf("XD", "equals") == "Memory is not what the heart desires. That is only a mirror.") + assert( + module.documentationOf( + "XD", + "equals" + ) == "Memory is not what the heart desires. That is only a mirror." + ) + } + } + } + + @Test + fun `kdocs with code block`() { + testInline( + """ + |/src/main/kotlin/sample/TestForCodeInDocs.kt + |package sample + |/** + | * Utility for building a String that represents an XML document. + | * The XmlBlob object is immutable and the passed values are copied where it makes sense. + | * + | * Note the XML Declaration is not output as part of the XmlBlob + | * + | * + | * val soapAttrs = attrs("soap-env" to "http://www.w3.org/2001/12/soap-envelope", + | * "soap-env:encodingStyle" to "http://www.w3.org/2001/12/soap-encoding") + | * val soapXml = node("soap-env:Envelope", soapAttrs, + | * node("soap-env:Body", attrs("xmlns:m" to "http://example"), + | * node("m:GetExample", + | * node("m:GetExampleName", "BasePair") + | * ) + | * ) + | * ) + | * + | * + | */ + |class TestForCodeInDocs { + |} + """.trimIndent(), configuration + ) { + documentablesMergingStage = { module -> + val description = module.descriptionOf("TestForCodeInDocs") + val expected = listOf( + P( + children = listOf(Text("Utility for building a String that represents an XML document. The XmlBlob object is immutable and the passed values are copied where it makes sense.")) + ), + P( + children = listOf(Text("Note the XML Declaration is not output as part of the XmlBlob")) + ), + CodeBlock( + children = listOf( + Text( + """ val soapAttrs = attrs("soap-env" to "http://www.w3.org/2001/12/soap-envelope", + "soap-env:encodingStyle" to "http://www.w3.org/2001/12/soap-encoding") + val soapXml = node("soap-env:Envelope", soapAttrs, + node("soap-env:Body", attrs("xmlns:m" to "http://example"), + node("m:GetExample", + node("m:GetExampleName", "BasePair") + ) + ) + )""" + ) + ) + ) + ) + assertEquals(expected, description?.root?.children) } } } diff --git a/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt b/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt index a1fbb2a0..8ffcfb3c 100644 --- a/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt +++ b/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt @@ -6,7 +6,6 @@ import org.jetbrains.dokka.model.childrenOfType import org.jetbrains.dokka.model.doc.* import org.jetbrains.dokka.model.firstChildOfType import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest -import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.* import utils.text @@ -100,6 +99,15 @@ class JavadocParserTest : AbstractCoreTest() { | * minute, but this specification follows the date and time conventions | * for ISO C. | * + | *

+            | * <androidx.fragment.app.FragmentContainerView
+            | *        xmlns:android="http://schemas.android.com/apk/res/android"
+            | *        xmlns:app="http://schemas.android.com/apk/res-auto"
+            | *        android:id="@+id/fragment_container_view"
+            | *        android:layout_width="match_parent"
+            | *        android:layout_height="match_parent">
+            | * </androidx.fragment.app.FragmentContainerView>
+            | * 
| *

| * In all cases, arguments given to methods for these purposes need | * not fall within the indicated ranges; for example, a date may be @@ -153,4 +161,20 @@ class JavadocParserTest : AbstractCoreTest() { assertEquals("java.util.Calendar", sees[1].name) } } + + @Test + fun `correctly parsed code block`(){ + performJavadocTest { module -> + val dateDescription = module.descriptionOf("Date2")!! + val preTagContent = dateDescription.firstChildOfType

().firstChildOfType()
+            val expectedText = """
+ """.trimIndent()
+            assertEquals(expectedText.trim(), preTagContent.body.trim())
+        }
+    }
 }
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToHtmlTranslator.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToHtmlTranslator.kt
index 413b6387..7f179f75 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToHtmlTranslator.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToHtmlTranslator.kt
@@ -20,7 +20,7 @@ internal class JavadocContentToHtmlTranslator(
             is ContentText -> htmlForText(node)
             is ContentDRILink -> buildLinkFromNode(node, relative)
             is ContentResolvedLink -> buildLinkFromNode(node, relative)
-            is ContentCode -> htmlForCode(node.children, relative)
+            is ContentCode -> htmlForCode(node, relative)
             is ContentList -> htmlForList(node.children, relative)
             is JavadocSignatureContentNode -> htmlForSignature(node, relative)
             is ContentBreakLine -> "
" @@ -44,16 +44,17 @@ internal class JavadocContentToHtmlTranslator( private fun htmlForParagraph(nodes: List, relative: PageNode?) = "

${htmlForContentNodes(nodes, relative)}

" - private fun htmlForCode(code: List, relative: PageNode?): String { - fun nodeToText(node: ContentNode): String = when (node) { - is ContentText -> node.text - is ContentBreakLine -> "" + private fun htmlForCode(code: ContentCode, relative: PageNode?): String { + fun nodeToText(node: ContentNode, insidePre: Boolean = false): String = when (node) { + is ContentText -> node.text.htmlEscape() + is ContentBreakLine -> if(insidePre) "\n" else "
" is ContentDRILink -> buildLinkFromNode(node, relative) is ContentResolvedLink -> buildLinkFromNode(node, relative) - is ContentCode -> node.children.joinToString("") { nodeToText(it) } + is ContentCodeBlock -> "
${node.children.joinToString("") { nodeToText(it, insidePre = true) }}
" + is ContentCodeInline -> "${node.children.joinToString("") { nodeToText(it) }}" else -> run { context.logger.error("Cannot cast $node as ContentText!"); "" } } - return code.map(::nodeToText).joinToString("
", """""", "") { it } + return nodeToText(code) } private fun htmlForList(elements: List, relative: PageNode?) = -- cgit