From 5ee12092aee698d1b65ad1d8088f3c3514ac7eee Mon Sep 17 00:00:00 2001 From: Zach Klippenstein Date: Thu, 13 Aug 2020 20:11:34 -0700 Subject: [PATCH] Correctly render nodes whose descriptions are more than one line. --- .../main/java/radiography/RenderTreeString.kt | 26 +++++++++++++------ .../java/radiography/RenderTreeStringTest.kt | 24 +++++++++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/radiography/src/main/java/radiography/RenderTreeString.kt b/radiography/src/main/java/radiography/RenderTreeString.kt index e4df0a1..fd04285 100644 --- a/radiography/src/main/java/radiography/RenderTreeString.kt +++ b/radiography/src/main/java/radiography/RenderTreeString.kt @@ -58,16 +58,21 @@ private fun StringBuilder.renderRecursively( depth: Int, lastChildMask: Long ) { - appendLinePrefix(depth, lastChildMask) - // Collect the children before actually visiting them. This ensures we know the full list of // children before we start iterating, which we need in order to be able to render the correct // line prefix for the last child. val children = mutableListOf>>() - val scope = RenderingScope(this@renderRecursively, children) + + // Render node into a separate buffer to append a prefix to every line. + val nodeDescription = StringBuilder() + val scope = RenderingScope(nodeDescription, children) with(visitor) { scope.visitNode(node) } - @Suppress("DEPRECATION") - appendln() + + nodeDescription.lineSequence().forEachIndexed { index, line -> + appendLinePrefix(depth, continuePreviousLine = index > 0, lastChildMask = lastChildMask) + @Suppress("DEPRECATION") + appendln(line) + } if (children.isEmpty()) return @@ -87,6 +92,7 @@ private fun StringBuilder.renderRecursively( private fun StringBuilder.appendLinePrefix( depth: Int, + continuePreviousLine: Boolean, lastChildMask: Long ) { val lastDepth = depth - 1 @@ -98,13 +104,13 @@ private fun StringBuilder.appendLinePrefix( } val lastChild = lastChildMask and (1 shl parentDepth).toLong() != 0L if (lastChild) { - if (parentDepth == lastDepth) { + if (parentDepth == lastDepth && !continuePreviousLine) { append('`') } else { append(' ') } } else { - if (parentDepth == lastDepth) { + if (parentDepth == lastDepth && !continuePreviousLine) { append('+') } else { append('|') @@ -112,6 +118,10 @@ private fun StringBuilder.appendLinePrefix( } } if (depth > 0) { - append("-") + if (continuePreviousLine) { + append(" ") + } else { + append("-") + } } } diff --git a/radiography/src/test/java/radiography/RenderTreeStringTest.kt b/radiography/src/test/java/radiography/RenderTreeStringTest.kt index 71add19..efaf1fd 100644 --- a/radiography/src/test/java/radiography/RenderTreeStringTest.kt +++ b/radiography/src/test/java/radiography/RenderTreeStringTest.kt @@ -133,6 +133,30 @@ class RenderTreeStringTest { ) } + @Test fun `renderTreeString handles multiline nodes`() { + val tree = Node( + "root1\nroot2", + Node("1\n1", Node("11\n11")), + Node("2\n2") + ) + + val rendering = buildString { renderTreeString(tree, NodeVisitor) } + + assertThat(rendering).isEqualTo( + """ + |${BLANK}root1 + |${BLANK}root2 + |$BLANK+-1 + |$BLANK| 1 + |$BLANK| `-11 + |$BLANK| 11 + |$BLANK`-2 + |$BLANK 2 + | + """.trimMargin() + ) + } + @Test fun `addChildToVisit with different visitor`() { val tree = Node( "root",