diff options
-rw-r--r-- | core/src/main/kotlin/model/WithChildren.kt | 22 | ||||
-rw-r--r-- | test-tools/src/main/kotlin/matchers/content/contentMatchers.kt | 26 |
2 files changed, 43 insertions, 5 deletions
diff --git a/core/src/main/kotlin/model/WithChildren.kt b/core/src/main/kotlin/model/WithChildren.kt index 06ff55b0..4aba51c6 100644 --- a/core/src/main/kotlin/model/WithChildren.kt +++ b/core/src/main/kotlin/model/WithChildren.kt @@ -65,3 +65,25 @@ fun <T> T.dfs(predicate: (T) -> Boolean): T? where T : WithChildren<T> = if (pre } else { children.asSequence().mapNotNull { it.dfs(predicate) }.firstOrNull() } + +fun <T: WithChildren<T>> T.asPrintableTree( + nodeNameBuilder: Appendable.(T) -> Unit = { append(it.toString()) } +): String { + fun Appendable.append(element: T, ownPrefix: String, childPrefix: String) { + append(ownPrefix) + nodeNameBuilder(element) + appendLine() + element.children.takeIf(Collection<*>::isNotEmpty)?.also { children -> + val newOwnPrefix = childPrefix + '\u251c' + '\u2500' + ' ' + val lastOwnPrefix = childPrefix + '\u2514' + '\u2500' + ' ' + val newChildPrefix = childPrefix + '\u2502' + ' ' + ' ' + val lastChildPrefix = childPrefix + ' ' + ' ' + ' ' + children.forEachIndexed { n, e -> + if (n != children.lastIndex) append(e, newOwnPrefix, newChildPrefix) + else append(e, lastOwnPrefix, lastChildPrefix) + } + } + } + + return buildString { append(this@asPrintableTree, "", "") } +}
\ No newline at end of file diff --git a/test-tools/src/main/kotlin/matchers/content/contentMatchers.kt b/test-tools/src/main/kotlin/matchers/content/contentMatchers.kt index 2284c88d..f42e28f3 100644 --- a/test-tools/src/main/kotlin/matchers/content/contentMatchers.kt +++ b/test-tools/src/main/kotlin/matchers/content/contentMatchers.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka.test.tools.matchers.content +import org.jetbrains.dokka.model.asPrintableTree import org.jetbrains.dokka.pages.ContentComposite import org.jetbrains.dokka.pages.ContentNode import org.jetbrains.dokka.pages.ContentText @@ -20,9 +21,13 @@ open class NodeMatcher<T : ContentNode>( try { assertions() } catch (e: AssertionError) { - throw MatcherError(e.message.orEmpty(), this@NodeMatcher, cause = e) + throw MatcherError( + "${e.message.orEmpty()}\nin node:\n${node.debugRepresentation()}", + this@NodeMatcher, + cause = e + ) } - } ?: throw MatcherError("Expected ${kclass.simpleName} but got: $node", this) + } ?: throw MatcherError("Expected ${kclass.simpleName} but got:\n${node.debugRepresentation()}", this) } } @@ -63,7 +68,7 @@ private class TextMatcherState( val anchor: TextMatcher ) : MatchWalkerState() { override fun next(node: ContentNode): MatchWalkerState { - node as? ContentText ?: throw MatcherError("Expected text: \"$text\" but got $node", anchor) + node as? ContentText ?: throw MatcherError("Expected text: \"$text\" but got\n${node.debugRepresentation()}", anchor) val trimmed = node.text.trim() return when { text == trimmed -> rest.pop() @@ -77,7 +82,7 @@ private class TextMatcherState( private class EmptyMatcherState(val parent: CompositeMatcher<*>) : MatchWalkerState() { override fun next(node: ContentNode): MatchWalkerState { - throw MatcherError("Unexpected $node", parent, anchorAfter = true) + throw MatcherError("Unexpected node:\n${node.debugRepresentation()}", parent, anchorAfter = true) } override fun finish() = Unit @@ -121,7 +126,6 @@ private class FurtherSiblings(val list: List<MatcherElement>, val parent: Compos } - internal fun MatcherElement.toDebugString(anchor: MatcherElement?, anchorAfter: Boolean): String { fun Appendable.append(element: MatcherElement, ownPrefix: String, childPrefix: String) { if (anchor != null) { @@ -156,6 +160,18 @@ internal fun MatcherElement.toDebugString(anchor: MatcherElement?, anchorAfter: return buildString { append(this@toDebugString, "", "") } } +private fun ContentNode.debugRepresentation() = asPrintableTree { element -> + append(if (element is ContentText) """"${element.text}"""" else element::class.simpleName) + append( + " { " + + "kind=${element.dci.kind}, " + + "dri=${element.dci.dri}, " + + "style=${element.style}, " + + "sourceSets=${element.sourceSets} " + + "}" + ) +} + data class MatcherError( override val message: String, val anchor: MatcherElement, |