runnableExamples now show originating location in stacktraces on failure (#18457)

* runnableExamples now show originating location in stacktraces on failure

* PRTEMP

* fix indentation inside multiline strings
This commit is contained in:
Timothee Cour 2021-07-09 02:41:28 -07:00 • committed by GitHub
commit ae7e7756fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 11 deletions

View file

@ -468,6 +468,10 @@ proc runAllExamples(d: PDoc) =
proc quoted(a: string): string = result.addQuoted(a) proc quoted(a: string): string = result.addQuoted(a)
proc toInstantiationInfo(conf: ConfigRef, info: TLineInfo): auto =
# xxx expose in compiler/lineinfos.nim
(conf.toMsgFilename(info), info.line.int, info.col.int + ColOffset)
proc prepareExample(d: PDoc; n: PNode, topLevel: bool): tuple[rdoccmd: string, code: string] = proc prepareExample(d: PDoc; n: PNode, topLevel: bool): tuple[rdoccmd: string, code: string] =
## returns `rdoccmd` and source code for this runnableExamples ## returns `rdoccmd` and source code for this runnableExamples
var rdoccmd = "" var rdoccmd = ""
@ -481,6 +485,7 @@ proc prepareExample(d: PDoc; n: PNode, topLevel: bool): tuple[rdoccmd: string, c
let useRenderModule = false let useRenderModule = false
let loc = d.conf.toFileLineCol(n.info) let loc = d.conf.toFileLineCol(n.info)
let code = extractRunnableExamplesSource(d.conf, n) let code = extractRunnableExamplesSource(d.conf, n)
let codeIndent = extractRunnableExamplesSource(d.conf, n, indent = 2)
if d.conf.errorCounter > 0: if d.conf.errorCounter > 0:
return (rdoccmd, code) return (rdoccmd, code)
@ -489,7 +494,7 @@ proc prepareExample(d: PDoc; n: PNode, topLevel: bool): tuple[rdoccmd: string, c
let outputDir = d.exampleOutputDir let outputDir = d.exampleOutputDir
createDir(outputDir) createDir(outputDir)
inc d.exampleCounter inc d.exampleCounter
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" & ("_examples$1.nim" % $d.exampleCounter))) let outp = outputDir / RelativeFile("$#_examples_$#.nim" % [d.filename.extractFilename.changeFileExt"", $d.exampleCounter])
if useRenderModule: if useRenderModule:
var docComment = newTree(nkCommentStmt) var docComment = newTree(nkCommentStmt)
@ -507,13 +512,21 @@ proc prepareExample(d: PDoc; n: PNode, topLevel: bool): tuple[rdoccmd: string, c
renderModule(runnableExamples, outp.string, conf = d.conf) renderModule(runnableExamples, outp.string, conf = d.conf)
else: else:
let code2 = """ var code2 = code
if code.len > 0 and "codeReordering" notin code:
# hacky but simplest solution, until we devise a way to make `{.line.}`
# work without introducing a scope
code2 = """
{.line: $#.}:
$#
""" % [$toInstantiationInfo(d.conf, n.info), codeIndent]
code2 = """
#[ #[
$1 $#
]# ]#
import $2 import $#
$3 $#
""" % [comment, d.filename.quoted, code] """ % [comment, d.filename.quoted, code2]
writeFile(outp.string, code2) writeFile(outp.string, code2)
if rdoccmd notin d.exampleGroups: if rdoccmd notin d.exampleGroups:

View file

@ -83,7 +83,7 @@ proc startOfLineInsideTriple(ldata: LineData, line: int): bool =
if index >= ldata.lines.len: false if index >= ldata.lines.len: false
else: ldata.lines[index] else: ldata.lines[index]
proc extractRunnableExamplesSource*(conf: ConfigRef; n: PNode): string = proc extractRunnableExamplesSource*(conf: ConfigRef; n: PNode, indent = 0): string =
## TLineInfo.offsetA,offsetB would be cleaner but it's only enabled for nimpretty, ## TLineInfo.offsetA,offsetB would be cleaner but it's only enabled for nimpretty,
## we'd need to check performance impact to enable it for nimdoc. ## we'd need to check performance impact to enable it for nimdoc.
var first = n.lastSon.info var first = n.lastSon.info
@ -102,7 +102,7 @@ proc extractRunnableExamplesSource*(conf: ConfigRef; n: PNode): string =
let last = n.lastNodeRec.info let last = n.lastNodeRec.info
var info = first var info = first
var indent = info.col var indent2 = info.col
let numLines = numLines(conf, info.fileIndex).uint16 let numLines = numLines(conf, info.fileIndex).uint16
var lastNonemptyPos = 0 var lastNonemptyPos = 0
@ -118,14 +118,15 @@ proc extractRunnableExamplesSource*(conf: ConfigRef; n: PNode): string =
info.line = line info.line = line
let src = sourceLine(conf, info) let src = sourceLine(conf, info)
let special = startOfLineInsideTriple(ldata, line.int) let special = startOfLineInsideTriple(ldata, line.int)
if line > last.line and not special and not isInIndentationBlock(src, indent): if line > last.line and not special and not isInIndentationBlock(src, indent2):
break break
if line > first.line: result.add "\n" if line > first.line: result.add "\n"
if special: if special:
result.add src result.add src
lastNonemptyPos = result.len lastNonemptyPos = result.len
elif src.len > indent: elif src.len > indent2:
result.add src[indent..^1] for i in 0..<indent: result.add ' '
result.add src[indent2..^1]
lastNonemptyPos = result.len lastNonemptyPos = result.len
result.setLen lastNonemptyPos result.setLen lastNonemptyPos