aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/main/kotlin/model/WithChildren.kt22
-rw-r--r--test-tools/src/main/kotlin/matchers/content/contentMatchers.kt26
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,