diff --git a/pmd-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDsl.kt b/pmd-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDsl.kt index 88c4beab78..7e2044393f 100644 --- a/pmd-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDsl.kt +++ b/pmd-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDsl.kt @@ -138,10 +138,20 @@ class NWrapper private constructor(val it: N, childType.isInstance(toWrap) } - @Suppress("UNCHECKED_CAST") - val wrapper = NWrapper(toWrap as M, matcherPath + childType, ignoreChildrenMatchers) + val childPath = matcherPath + childType - wrapper.spec() + @Suppress("UNCHECKED_CAST") + val wrapper = NWrapper(toWrap as M, childPath, ignoreChildrenMatchers) + + try { + wrapper.spec() + } catch (e: AssertionError) { + if (e.message?.matches("At (/.*?|):.*".toRegex()) == false) { + // the exception has no path, let's add one + throw AssertionError(formatErrorMessage(childPath, e.message ?: "No explanation provided"), e) + } + throw e + } assertFalse(formatErrorMessage(matcherPath + childType, "Wrong number of children, expected ${wrapper.nextChildMatcherIdx}, actual ${wrapper.it.numChildren}")) { !ignoreChildrenMatchers && wrapper.nextChildMatcherIdx != wrapper.it.numChildren diff --git a/pmd-test/src/test/kotlin/net/sourceforge/pmd/lang/ast/test/DslTest.kt b/pmd-test/src/test/kotlin/net/sourceforge/pmd/lang/ast/test/DslTest.kt index 39833f4d86..e6d9fe245d 100644 --- a/pmd-test/src/test/kotlin/net/sourceforge/pmd/lang/ast/test/DslTest.kt +++ b/pmd-test/src/test/kotlin/net/sourceforge/pmd/lang/ast/test/DslTest.kt @@ -90,6 +90,37 @@ class DslTest : FunSpec({ } } + failureTest("All assertions should have a node path", + messageContains = setOf("At /LocalVariableDeclaration/Type:", "expected: \"bratwurst\"")) { + + parseStatement("int[] i = 0;") should matchNode { + + child { + + // this fails + it.typeImage shouldBe "bratwurst" + + } + + unspecifiedChild() + } + } + + failureTest("Child assertions should have a node path", + messageContains = setOf("At /LocalVariableDeclaration/Type:", "expected", "type", "LambdaExpression")) { + + parseStatement("int[] i = 0;") should matchNode { + + child { + + // this fails + child { } + } + + unspecifiedChild() + } + } + failureTest("Leaf nodes should assert that they have no children", messageContains = setOf("number", "children", "expected 0")) {