mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-19 01:18:32 +00:00
unittest: show proper stack trace for 'check' (#25212)
(cherry picked from commit c4c51d7e78)
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user