unittest: show proper stack trace for 'check' (#25212)

(cherry picked from commit c4c51d7e78)
This commit is contained in:
Andreas Rumpf
2025-10-08 19:09:45 +02:00
committed by narimiran
parent 9595e17ba5
commit 47c41955bb

View File

@@ -657,10 +657,6 @@ macro check*(conditions: untyped): untyped =
let checked = callsite()[1]
template asgn(a: untyped, value: typed) =
var a = value # XXX: we need "var: var" here in order to
# preserve the semantics of var params
template print(name: untyped, value: typed) =
when compiles(string($value)):
checkpoint(name & " was " & $value)
@@ -686,8 +682,16 @@ macro check*(conditions: untyped): untyped =
if exp[i].kind in nnkCallKinds + {nnkDotExpr, nnkBracketExpr, nnkPar} and
(exp[i].typeKind notin {ntyTypeDesc} or $exp[0] notin ["is", "isnot"]):
let callVar = newIdentNode(":c" & $counter)
result.assigns.add getAst(asgn(callVar, paramAst))
# Construct AST directly instead of using getAst to preserve line info
let asgnNode = newNimNode(nnkVarSection, exp[i])
let identDef = newNimNode(nnkIdentDefs, exp[i])
identDef.add callVar
identDef.add newEmptyNode()
identDef.add paramAst
asgnNode.add identDef
result.assigns.add asgnNode
result.check[i] = callVar
result.check[^1].setLineInfo exp.lineInfoObj
result.printOuts.add getAst(print(argStr, callVar))
if exp[i].kind == nnkExprEqExpr:
# ExprEqExpr
@@ -696,8 +700,16 @@ macro check*(conditions: untyped): untyped =
result.check[i] = exp[i][1]
if exp[i].typeKind notin {ntyTypeDesc}:
let arg = newIdentNode(":p" & $counter)
result.assigns.add getAst(asgn(arg, paramAst))
# Construct AST directly instead of using getAst to preserve line info
let asgnNode = newNimNode(nnkVarSection, exp[i])
let identDef = newNimNode(nnkIdentDefs, exp[i])
identDef.add arg
identDef.add newEmptyNode()
identDef.add paramAst
asgnNode.add identDef
result.assigns.add asgnNode
result.printOuts.add getAst(print(argStr, arg))
result.printOuts[^1].setLineInfo exp.lineInfoObj
if exp[i].kind != nnkExprEqExpr:
result.check[i] = arg
else:
@@ -709,9 +721,28 @@ macro check*(conditions: untyped): untyped =
let (assigns, check, printOuts) = inspectArgs(checked)
let lineinfo = newStrLitNode(checked.lineInfo)
let callLit = checked.toStrLit
# Wrap assigns in a line pragma block to preserve stack trace location
let pragmaBlock = newNimNode(nnkPragmaBlock)
let pragma = newNimNode(nnkPragma)
let exprColonExpr = newNimNode(nnkExprColonExpr)
exprColonExpr.add newIdentNode("line")
# Create a tuple literal with (filename, line, column) from checked
let lineInfoObj = checked.lineInfoObj
let tupleLit = newNimNode(nnkTupleConstr)
tupleLit.add newLit(lineInfoObj.filename)
tupleLit.add newLit(lineInfoObj.line.int)
tupleLit.add newLit(lineInfoObj.column.int)
exprColonExpr.add tupleLit
pragma.add exprColonExpr
pragmaBlock.add pragma
pragmaBlock.add assigns
result = quote do:
block:
`assigns`
`pragmaBlock`
if `check`:
discard
else: