fix js stacktraces, unify all file,line,col formatting into a single function (#14230)
* fix https://github.com/timotheecour/Nim/issues/135 ; unify all file,line,col formatting into a single function
This commit is contained in:
parent
6b7b5fb4fa
commit
c28a057a6b
7 changed files with 68 additions and 46 deletions
|
|
@ -2243,7 +2243,7 @@ proc genProcBody(p: PProc, prc: PSym): Rope =
|
||||||
if hasFrameInfo(p):
|
if hasFrameInfo(p):
|
||||||
result = frameCreate(p,
|
result = frameCreate(p,
|
||||||
makeJSString(prc.owner.name.s & '.' & prc.name.s),
|
makeJSString(prc.owner.name.s & '.' & prc.name.s),
|
||||||
makeJSString(toFilename(p.config, prc.info)))
|
makeJSString(toFilenameOption(p.config, prc.info.fileIndex, foStacktrace)))
|
||||||
else:
|
else:
|
||||||
result = nil
|
result = nil
|
||||||
if p.beforeRetNeeded:
|
if p.beforeRetNeeded:
|
||||||
|
|
@ -2583,7 +2583,7 @@ proc genModule(p: PProc, n: PNode) =
|
||||||
if optStackTrace in p.options:
|
if optStackTrace in p.options:
|
||||||
p.body.add(frameCreate(p,
|
p.body.add(frameCreate(p,
|
||||||
makeJSString("module " & p.module.module.name.s),
|
makeJSString("module " & p.module.module.name.s),
|
||||||
makeJSString(toFilename(p.config, p.module.module.info))))
|
makeJSString(toFilenameOption(p.config, p.module.module.info.fileIndex, foStacktrace))))
|
||||||
var transformedN = transformStmt(p.module.graph, p.module.module, n)
|
var transformedN = transformStmt(p.module.graph, p.module.module, n)
|
||||||
if sfInjectDestructors in p.module.module.flags:
|
if sfInjectDestructors in p.module.module.flags:
|
||||||
transformedN = injectDestructorCalls(p.module.graph, p.module.module, transformedN)
|
transformedN = injectDestructorCalls(p.module.graph, p.module.module, transformedN)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import
|
import
|
||||||
options, strutils, os, tables, ropes, terminal, macros,
|
options, strutils, os, tables, ropes, terminal, macros,
|
||||||
lineinfos, pathutils
|
lineinfos, pathutils
|
||||||
|
import std/private/miscdollars
|
||||||
|
|
||||||
proc toCChar*(c: char; result: var string) =
|
proc toCChar*(c: char; result: var string) =
|
||||||
case c
|
case c
|
||||||
|
|
@ -132,7 +133,6 @@ proc suggestQuit*() =
|
||||||
# this format is understood by many text editors: it is the same that
|
# this format is understood by many text editors: it is the same that
|
||||||
# Borland and Freepascal use
|
# Borland and Freepascal use
|
||||||
const
|
const
|
||||||
PosFormat = "$1($2, $3) "
|
|
||||||
KindFormat = " [$1]"
|
KindFormat = " [$1]"
|
||||||
KindColor = fgCyan
|
KindColor = fgCyan
|
||||||
ErrorTitle = "Error: "
|
ErrorTitle = "Error: "
|
||||||
|
|
@ -213,16 +213,38 @@ template toFullPath*(conf: ConfigRef; info: TLineInfo): string =
|
||||||
template toFullPathConsiderDirty*(conf: ConfigRef; info: TLineInfo): string =
|
template toFullPathConsiderDirty*(conf: ConfigRef; info: TLineInfo): string =
|
||||||
string toFullPathConsiderDirty(conf, info.fileIndex)
|
string toFullPathConsiderDirty(conf, info.fileIndex)
|
||||||
|
|
||||||
|
type FilenameOption* = enum
|
||||||
|
foAbs # absolute path, eg: /pathto/bar/foo.nim
|
||||||
|
foRelProject # relative to project path, eg: ../foo.nim
|
||||||
|
foMagicSauce # magic sauce, shortest of (foAbs, foRelProject)
|
||||||
|
foName # lastPathPart, eg: foo.nim
|
||||||
|
foShort # foName without extension, eg: foo
|
||||||
|
foStacktrace # if optExcessiveStackTrace: foAbs else: foName
|
||||||
|
|
||||||
|
proc toFilenameOption*(conf: ConfigRef, fileIdx: FileIndex, opt: FilenameOption): string =
|
||||||
|
case opt
|
||||||
|
of foAbs: result = toFullPath(conf, fileIdx)
|
||||||
|
of foRelProject: result = toProjPath(conf, fileIdx)
|
||||||
|
of foMagicSauce:
|
||||||
|
let
|
||||||
|
absPath = toFullPath(conf, fileIdx)
|
||||||
|
relPath = toProjPath(conf, fileIdx)
|
||||||
|
result = if (optListFullPaths in conf.globalOptions) or
|
||||||
|
(relPath.len > absPath.len) or
|
||||||
|
(relPath.count("..") > 2):
|
||||||
|
absPath
|
||||||
|
else:
|
||||||
|
relPath
|
||||||
|
of foName: result = toProjPath(conf, fileIdx).lastPathPart
|
||||||
|
of foShort: result = toFilename(conf, fileIdx)
|
||||||
|
of foStacktrace:
|
||||||
|
if optExcessiveStackTrace in conf.globalOptions:
|
||||||
|
result = toFilenameOption(conf, fileIdx, foAbs)
|
||||||
|
else:
|
||||||
|
result = toFilenameOption(conf, fileIdx, foName)
|
||||||
|
|
||||||
proc toMsgFilename*(conf: ConfigRef; info: FileIndex): string =
|
proc toMsgFilename*(conf: ConfigRef; info: FileIndex): string =
|
||||||
let
|
toFilenameOption(conf, info, foMagicSauce)
|
||||||
absPath = toFullPath(conf, info)
|
|
||||||
relPath = toProjPath(conf, info)
|
|
||||||
result = if (optListFullPaths in conf.globalOptions) or
|
|
||||||
(relPath.len > absPath.len) or
|
|
||||||
(relPath.count("..") > 2):
|
|
||||||
absPath
|
|
||||||
else:
|
|
||||||
relPath
|
|
||||||
|
|
||||||
template toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
|
template toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
|
||||||
toMsgFilename(conf, info.fileIndex)
|
toMsgFilename(conf, info.fileIndex)
|
||||||
|
|
@ -234,9 +256,7 @@ proc toColumn*(info: TLineInfo): int {.inline.} =
|
||||||
result = info.col
|
result = info.col
|
||||||
|
|
||||||
proc toFileLineCol*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
|
proc toFileLineCol*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
|
||||||
# consider calling `helpers.lineInfoToString` instead
|
result.toLocation(toMsgFilename(conf, info), info.line.int, info.col.int + ColOffset)
|
||||||
result = toMsgFilename(conf, info) & "(" & $info.line & ", " &
|
|
||||||
$(info.col + ColOffset) & ")"
|
|
||||||
|
|
||||||
proc `$`*(conf: ConfigRef; info: TLineInfo): string = toFileLineCol(conf, info)
|
proc `$`*(conf: ConfigRef; info: TLineInfo): string = toFileLineCol(conf, info)
|
||||||
|
|
||||||
|
|
@ -322,10 +342,6 @@ template styledMsgWriteln*(args: varargs[typed]) =
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
flushFile(stderr)
|
flushFile(stderr)
|
||||||
|
|
||||||
proc coordToStr(coord: int): string =
|
|
||||||
if coord == -1: result = "???"
|
|
||||||
else: result = $coord
|
|
||||||
|
|
||||||
proc msgKindToString*(kind: TMsgKind): string =
|
proc msgKindToString*(kind: TMsgKind): string =
|
||||||
# later versions may provide translated error messages
|
# later versions may provide translated error messages
|
||||||
result = MsgKindToStr[kind]
|
result = MsgKindToStr[kind]
|
||||||
|
|
@ -389,12 +405,7 @@ proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
|
||||||
instantiationFrom
|
instantiationFrom
|
||||||
else:
|
else:
|
||||||
instantiationOfFrom.format(context.detail)
|
instantiationOfFrom.format(context.detail)
|
||||||
styledMsgWriteln(styleBright,
|
styledMsgWriteln(styleBright, conf.toFileLineCol(context.info), " ", resetStyle, message)
|
||||||
PosFormat % [toMsgFilename(conf, context.info),
|
|
||||||
coordToStr(context.info.line.int),
|
|
||||||
coordToStr(context.info.col+ColOffset)],
|
|
||||||
resetStyle,
|
|
||||||
message)
|
|
||||||
info = context.info
|
info = context.info
|
||||||
|
|
||||||
proc ignoreMsgBecauseOfIdeTools(conf: ConfigRef; msg: TMsgKind): bool =
|
proc ignoreMsgBecauseOfIdeTools(conf: ConfigRef; msg: TMsgKind): bool =
|
||||||
|
|
@ -473,10 +484,7 @@ proc formatMsg*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string): s
|
||||||
of warnMin..warnMax: WarningTitle
|
of warnMin..warnMax: WarningTitle
|
||||||
of hintMin..hintMax: HintTitle
|
of hintMin..hintMax: HintTitle
|
||||||
else: ErrorTitle
|
else: ErrorTitle
|
||||||
result = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
|
conf.toFileLineCol(info) & " " & title & getMessageStr(msg, arg)
|
||||||
coordToStr(info.col+ColOffset)] &
|
|
||||||
title &
|
|
||||||
getMessageStr(msg, arg)
|
|
||||||
|
|
||||||
proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
|
proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
|
||||||
eh: TErrorHandling) =
|
eh: TErrorHandling) =
|
||||||
|
|
@ -511,8 +519,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
|
||||||
color = HintColor
|
color = HintColor
|
||||||
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
|
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
|
||||||
inc(conf.hintCounter)
|
inc(conf.hintCounter)
|
||||||
let x = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
|
let x = conf.toFileLineCol(info) & " "
|
||||||
coordToStr(info.col+ColOffset)]
|
|
||||||
let s = getMessageStr(msg, arg)
|
let s = getMessageStr(msg, arg)
|
||||||
|
|
||||||
if not ignoreMsg:
|
if not ignoreMsg:
|
||||||
|
|
|
||||||
15
lib/std/private/miscdollars.nim
Normal file
15
lib/std/private/miscdollars.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
template toLocation*(result: var string, file: string | cstring, line: int, col: int) =
|
||||||
|
## avoids spurious allocations
|
||||||
|
# Hopefully this can be re-used everywhere so that if a user needs to customize,
|
||||||
|
# it can be done in a single place.
|
||||||
|
result.add file
|
||||||
|
if line > 0:
|
||||||
|
result.add "("
|
||||||
|
# simplify this after moving moving `include strmantle` above import assertions`
|
||||||
|
when declared(addInt): result.addInt line
|
||||||
|
else: result.add $line
|
||||||
|
if col > 0:
|
||||||
|
result.add ", "
|
||||||
|
when declared(addInt): result.addInt col
|
||||||
|
else: result.add $col
|
||||||
|
result.add ")"
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
when not declared(sysFatal):
|
when not declared(sysFatal):
|
||||||
include "system/fatal"
|
include "system/fatal"
|
||||||
|
|
||||||
|
import std/private/miscdollars
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# helpers
|
# helpers
|
||||||
|
|
||||||
type InstantiationInfo = tuple[filename: string, line: int, column: int]
|
type InstantiationInfo = tuple[filename: string, line: int, column: int]
|
||||||
|
|
||||||
proc `$`(x: int): string {.magic: "IntToStr", noSideEffect.}
|
proc `$`(x: int): string {.magic: "IntToStr", noSideEffect.}
|
||||||
|
|
||||||
proc `$`(info: InstantiationInfo): string =
|
proc `$`(info: InstantiationInfo): string =
|
||||||
# The +1 is needed here
|
# The +1 is needed here
|
||||||
# instead of overriding `$` (and changing its meaning), consider explicit name.
|
# instead of overriding `$` (and changing its meaning), consider explicit name.
|
||||||
info.filename & "(" & $info.line & ", " & $(info.column+1) & ")"
|
result.toLocation(info.filename, info.line, info.column+1)
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
# Exception handling code. Carefully coded so that tiny programs which do not
|
# Exception handling code. Carefully coded so that tiny programs which do not
|
||||||
# use the heap (and nor exceptions) do not include the GC or memory allocator.
|
# use the heap (and nor exceptions) do not include the GC or memory allocator.
|
||||||
|
|
||||||
|
import std/private/miscdollars
|
||||||
|
|
||||||
var
|
var
|
||||||
errorMessageWriter*: (proc(msg: string) {.tags: [WriteIOEffect], benign,
|
errorMessageWriter*: (proc(msg: string) {.tags: [WriteIOEffect], benign,
|
||||||
nimcall.})
|
nimcall.})
|
||||||
|
|
@ -240,11 +242,7 @@ proc auxWriteStackTrace(f: PFrame; s: var seq[StackTraceEntry]) =
|
||||||
|
|
||||||
template addFrameEntry(s: var string, f: StackTraceEntry|PFrame) =
|
template addFrameEntry(s: var string, f: StackTraceEntry|PFrame) =
|
||||||
var oldLen = s.len
|
var oldLen = s.len
|
||||||
add(s, f.filename)
|
s.toLocation(f.filename, f.line, 0)
|
||||||
if f.line > 0:
|
|
||||||
add(s, '(')
|
|
||||||
add(s, $f.line)
|
|
||||||
add(s, ')')
|
|
||||||
for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
|
for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
|
||||||
add(s, f.procname)
|
add(s, f.procname)
|
||||||
when NimStackTraceMsgs:
|
when NimStackTraceMsgs:
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
include system/indexerrors
|
include system/indexerrors
|
||||||
|
import std/private/miscdollars
|
||||||
|
|
||||||
proc log*(s: cstring) {.importc: "console.log", varargs, nodecl.}
|
proc log*(s: cstring) {.importc: "console.log", varargs, nodecl.}
|
||||||
|
|
||||||
|
|
@ -70,7 +71,7 @@ proc getCurrentExceptionMsg*(): string =
|
||||||
|
|
||||||
proc auxWriteStackTrace(f: PCallFrame): string =
|
proc auxWriteStackTrace(f: PCallFrame): string =
|
||||||
type
|
type
|
||||||
TempFrame = tuple[procname: cstring, line: int]
|
TempFrame = tuple[procname: cstring, line: int, filename: cstring]
|
||||||
var
|
var
|
||||||
it = f
|
it = f
|
||||||
i = 0
|
i = 0
|
||||||
|
|
@ -79,6 +80,7 @@ proc auxWriteStackTrace(f: PCallFrame): string =
|
||||||
while it != nil and i <= high(tempFrames):
|
while it != nil and i <= high(tempFrames):
|
||||||
tempFrames[i].procname = it.procname
|
tempFrames[i].procname = it.procname
|
||||||
tempFrames[i].line = it.line
|
tempFrames[i].line = it.line
|
||||||
|
tempFrames[i].filename = it.filename
|
||||||
inc(i)
|
inc(i)
|
||||||
inc(total)
|
inc(total)
|
||||||
it = it.prev
|
it = it.prev
|
||||||
|
|
@ -92,10 +94,9 @@ proc auxWriteStackTrace(f: PCallFrame): string =
|
||||||
add(result, $(total-i))
|
add(result, $(total-i))
|
||||||
add(result, " calls omitted) ...\n")
|
add(result, " calls omitted) ...\n")
|
||||||
for j in countdown(i-1, 0):
|
for j in countdown(i-1, 0):
|
||||||
|
result.toLocation($tempFrames[j].filename, tempFrames[j].line, 0)
|
||||||
|
add(result, " at ")
|
||||||
add(result, tempFrames[j].procname)
|
add(result, tempFrames[j].procname)
|
||||||
if tempFrames[j].line > 0:
|
|
||||||
add(result, ", line: ")
|
|
||||||
add(result, $tempFrames[j].line)
|
|
||||||
add(result, "\n")
|
add(result, "\n")
|
||||||
|
|
||||||
proc rawWriteStackTrace(): string =
|
proc rawWriteStackTrace(): string =
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
discard """
|
discard """
|
||||||
cmd: "nim $target $options --stackTrace:on --lineTrace:on $file"
|
cmd: "nim $target $options --stackTrace:on --lineTrace:on $file"
|
||||||
outputsub: '''
|
outputsub: '''
|
||||||
t7224.aaa, line: 21
|
t7224.nim(25) at module t7224
|
||||||
t7224.bbb, line: 18
|
t7224.nim(22) at t7224.aaa
|
||||||
t7224.ccc, line: 15
|
t7224.nim(19) at t7224.bbb
|
||||||
t7224.ddd, line: 12
|
t7224.nim(16) at t7224.ccc
|
||||||
|
t7224.nim(13) at t7224.ddd
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue