msgs.nim 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2013 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. import
  10. options, strutils, os, tables, ropes, platform, terminal, macros,
  11. lineinfos, pathutils
  12. proc toCChar*(c: char; result: var string) =
  13. case c
  14. of '\0'..'\x1F', '\x7F'..'\xFF':
  15. result.add '\\'
  16. result.add toOctal(c)
  17. of '\'', '\"', '\\', '?':
  18. result.add '\\'
  19. result.add c
  20. else:
  21. result.add c
  22. proc makeCString*(s: string): Rope =
  23. const MaxLineLength = 64
  24. result = nil
  25. var res = newStringOfCap(int(s.len.toFloat * 1.1) + 1)
  26. add(res, "\"")
  27. for i in countup(0, len(s) - 1):
  28. if (i + 1) mod MaxLineLength == 0:
  29. add(res, "\"\L\"")
  30. toCChar(s[i], res)
  31. add(res, '\"')
  32. add(result, rope(res))
  33. proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile): TFileInfo =
  34. result.fullPath = fullPath
  35. #shallow(result.fullPath)
  36. result.projPath = projPath
  37. #shallow(result.projPath)
  38. let fileName = fullPath.extractFilename
  39. result.shortName = fileName.changeFileExt("")
  40. result.quotedName = fileName.makeCString
  41. result.quotedFullName = fullPath.string.makeCString
  42. result.lines = @[]
  43. when defined(nimpretty):
  44. if not result.fullPath.isEmpty:
  45. try:
  46. result.fullContent = readFile(result.fullPath.string)
  47. except IOError:
  48. #rawMessage(errCannotOpenFile, result.fullPath)
  49. # XXX fixme
  50. result.fullContent = ""
  51. when defined(nimpretty):
  52. proc fileSection*(conf: ConfigRef; fid: FileIndex; a, b: int): string =
  53. substr(conf.m.fileInfos[fid.int].fullContent, a, b)
  54. proc fileInfoKnown*(conf: ConfigRef; filename: AbsoluteFile): bool =
  55. var
  56. canon: AbsoluteFile
  57. try:
  58. canon = canonicalizePath(conf, filename)
  59. except OSError:
  60. canon = filename
  61. result = conf.m.filenameToIndexTbl.hasKey(canon.string)
  62. proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool): FileIndex =
  63. var
  64. canon: AbsoluteFile
  65. pseudoPath = false
  66. try:
  67. canon = canonicalizePath(conf, filename)
  68. shallow(canon.string)
  69. except OSError:
  70. canon = filename
  71. # The compiler uses "filenames" such as `command line` or `stdin`
  72. # This flag indicates that we are working with such a path here
  73. pseudoPath = true
  74. if conf.m.filenameToIndexTbl.hasKey(canon.string):
  75. result = conf.m.filenameToIndexTbl[canon.string]
  76. else:
  77. isKnownFile = false
  78. result = conf.m.fileInfos.len.FileIndex
  79. conf.m.fileInfos.add(newFileInfo(canon, if pseudoPath: RelativeFile filename
  80. else: relativeTo(canon, conf.projectPath)))
  81. conf.m.filenameToIndexTbl[canon.string] = result
  82. proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile): FileIndex =
  83. var dummy: bool
  84. result = fileInfoIdx(conf, filename, dummy)
  85. proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
  86. result.fileIndex = fileInfoIdx
  87. result.line = uint16(line)
  88. result.col = int16(col)
  89. proc newLineInfo*(conf: ConfigRef; filename: AbsoluteFile, line, col: int): TLineInfo {.inline.} =
  90. result = newLineInfo(fileInfoIdx(conf, filename), line, col)
  91. proc concat(strings: openarray[string]): string =
  92. var totalLen = 0
  93. for s in strings: totalLen += s.len
  94. result = newStringOfCap totalLen
  95. for s in strings: result.add s
  96. proc suggestWriteln*(conf: ConfigRef; s: string) =
  97. if eStdOut in conf.m.errorOutputs:
  98. if isNil(conf.writelnHook):
  99. writeLine(stdout, s)
  100. flushFile(stdout)
  101. else:
  102. conf.writelnHook(s)
  103. proc msgQuit*(x: int8) = quit x
  104. proc msgQuit*(x: string) = quit x
  105. proc suggestQuit*() =
  106. raise newException(ESuggestDone, "suggest done")
  107. # this format is understood by many text editors: it is the same that
  108. # Borland and Freepascal use
  109. const
  110. PosFormat = "$1($2, $3) "
  111. KindFormat = " [$1]"
  112. KindColor = fgCyan
  113. ErrorTitle = "Error: "
  114. ErrorColor = fgRed
  115. WarningTitle = "Warning: "
  116. WarningColor = fgYellow
  117. HintTitle = "Hint: "
  118. HintColor = fgGreen
  119. proc getInfoContextLen*(conf: ConfigRef): int = return conf.m.msgContext.len
  120. proc setInfoContextLen*(conf: ConfigRef; L: int) = setLen(conf.m.msgContext, L)
  121. proc pushInfoContext*(conf: ConfigRef; info: TLineInfo; detail: string = "") =
  122. conf.m.msgContext.add((info, detail))
  123. proc popInfoContext*(conf: ConfigRef) =
  124. setLen(conf.m.msgContext, len(conf.m.msgContext) - 1)
  125. proc getInfoContext*(conf: ConfigRef; index: int): TLineInfo =
  126. let L = conf.m.msgContext.len
  127. let i = if index < 0: L + index else: index
  128. if i >=% L: result = unknownLineInfo()
  129. else: result = conf.m.msgContext[i].info
  130. template toFilename*(conf: ConfigRef; fileIdx: FileIndex): string =
  131. if fileIdx.int32 < 0 or conf == nil:
  132. "???"
  133. else:
  134. conf.m.fileInfos[fileIdx.int32].projPath.string
  135. proc toFullPath*(conf: ConfigRef; fileIdx: FileIndex): string =
  136. if fileIdx.int32 < 0 or conf == nil: result = "???"
  137. else: result = conf.m.fileInfos[fileIdx.int32].fullPath.string
  138. proc setDirtyFile*(conf: ConfigRef; fileIdx: FileIndex; filename: AbsoluteFile) =
  139. assert fileIdx.int32 >= 0
  140. conf.m.fileInfos[fileIdx.int32].dirtyFile = filename
  141. proc setHash*(conf: ConfigRef; fileIdx: FileIndex; hash: string) =
  142. assert fileIdx.int32 >= 0
  143. shallowCopy(conf.m.fileInfos[fileIdx.int32].hash, hash)
  144. proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string =
  145. assert fileIdx.int32 >= 0
  146. shallowCopy(result, conf.m.fileInfos[fileIdx.int32].hash)
  147. proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): AbsoluteFile =
  148. if fileIdx.int32 < 0:
  149. result = AbsoluteFile"???"
  150. elif not conf.m.fileInfos[fileIdx.int32].dirtyFile.isEmpty:
  151. result = conf.m.fileInfos[fileIdx.int32].dirtyFile
  152. else:
  153. result = conf.m.fileInfos[fileIdx.int32].fullPath
  154. template toFilename*(conf: ConfigRef; info: TLineInfo): string =
  155. toFilename(conf, info.fileIndex)
  156. template toFullPath*(conf: ConfigRef; info: TLineInfo): string =
  157. toFullPath(conf, info.fileIndex)
  158. proc toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
  159. if info.fileIndex.int32 < 0:
  160. result = "???"
  161. elif optListFullPaths in conf.globalOptions:
  162. result = conf.m.fileInfos[info.fileIndex.int32].fullPath.string
  163. else:
  164. result = conf.m.fileInfos[info.fileIndex.int32].projPath.string
  165. proc toLinenumber*(info: TLineInfo): int {.inline.} =
  166. result = int info.line
  167. proc toColumn*(info: TLineInfo): int {.inline.} =
  168. result = info.col
  169. proc toFileLine*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
  170. result = toFilename(conf, info) & ":" & $info.line
  171. proc toFileLineCol*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
  172. result = toFilename(conf, info) & "(" & $info.line & ", " & $info.col & ")"
  173. proc `$`*(conf: ConfigRef; info: TLineInfo): string = toFileLineCol(conf, info)
  174. proc `$`*(info: TLineInfo): string {.error.} = discard
  175. proc `??`* (conf: ConfigRef; info: TLineInfo, filename: string): bool =
  176. # only for debugging purposes
  177. result = filename in toFilename(conf, info)
  178. type
  179. MsgFlag* = enum ## flags altering msgWriteln behavior
  180. msgStdout, ## force writing to stdout, even stderr is default
  181. msgSkipHook ## skip message hook even if it is present
  182. MsgFlags* = set[MsgFlag]
  183. proc msgWriteln*(conf: ConfigRef; s: string, flags: MsgFlags = {}) =
  184. ## Writes given message string to stderr by default.
  185. ## If ``--stdout`` option is given, writes to stdout instead. If message hook
  186. ## is present, then it is used to output message rather than stderr/stdout.
  187. ## This behavior can be altered by given optional flags.
  188. ## This is used for 'nim dump' etc. where we don't have nimsuggest
  189. ## support.
  190. #if conf.cmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
  191. if not isNil(conf.writelnHook) and msgSkipHook notin flags:
  192. conf.writelnHook(s)
  193. elif optStdout in conf.globalOptions or msgStdout in flags:
  194. if eStdOut in conf.m.errorOutputs:
  195. writeLine(stdout, s)
  196. flushFile(stdout)
  197. else:
  198. if eStdErr in conf.m.errorOutputs:
  199. writeLine(stderr, s)
  200. # On Windows stderr is fully-buffered when piped, regardless of C std.
  201. when defined(windows):
  202. flushFile(stderr)
  203. macro callIgnoringStyle(theProc: typed, first: typed,
  204. args: varargs[typed]): untyped =
  205. let typForegroundColor = bindSym"ForegroundColor".getType
  206. let typBackgroundColor = bindSym"BackgroundColor".getType
  207. let typStyle = bindSym"Style".getType
  208. let typTerminalCmd = bindSym"TerminalCmd".getType
  209. result = newCall(theProc)
  210. if first.kind != nnkNilLit: result.add(first)
  211. for arg in children(args[0][1]):
  212. if arg.kind == nnkNilLit: continue
  213. let typ = arg.getType
  214. if typ.kind != nnkEnumTy or
  215. typ != typForegroundColor and
  216. typ != typBackgroundColor and
  217. typ != typStyle and
  218. typ != typTerminalCmd:
  219. result.add(arg)
  220. macro callStyledWriteLineStderr(args: varargs[typed]): untyped =
  221. result = newCall(bindSym"styledWriteLine")
  222. result.add(bindSym"stderr")
  223. for arg in children(args[0][1]):
  224. result.add(arg)
  225. template callWritelnHook(args: varargs[string, `$`]) =
  226. conf.writelnHook concat(args)
  227. template styledMsgWriteln*(args: varargs[typed]) =
  228. if not isNil(conf.writelnHook):
  229. callIgnoringStyle(callWritelnHook, nil, args)
  230. elif optStdout in conf.globalOptions:
  231. if eStdOut in conf.m.errorOutputs:
  232. callIgnoringStyle(writeLine, stdout, args)
  233. flushFile(stdout)
  234. else:
  235. if eStdErr in conf.m.errorOutputs:
  236. if optUseColors in conf.globalOptions:
  237. callStyledWriteLineStderr(args)
  238. else:
  239. callIgnoringStyle(writeLine, stderr, args)
  240. # On Windows stderr is fully-buffered when piped, regardless of C std.
  241. when defined(windows):
  242. flushFile(stderr)
  243. proc coordToStr(coord: int): string =
  244. if coord == -1: result = "???"
  245. else: result = $coord
  246. proc msgKindToString*(kind: TMsgKind): string =
  247. # later versions may provide translated error messages
  248. result = MsgKindToStr[kind]
  249. proc getMessageStr(msg: TMsgKind, arg: string): string =
  250. result = msgKindToString(msg) % [arg]
  251. type
  252. TErrorHandling = enum doNothing, doAbort, doRaise
  253. proc log*(s: string) {.procvar.} =
  254. var f: File
  255. if open(f, getHomeDir() / "nimsuggest.log", fmAppend):
  256. f.writeLine(s)
  257. close(f)
  258. proc quit(conf: ConfigRef; msg: TMsgKind) =
  259. if defined(debug) or msg == errInternal or hintStackTrace in conf.notes:
  260. if stackTraceAvailable() and isNil(conf.writelnHook):
  261. writeStackTrace()
  262. else:
  263. styledMsgWriteln(fgRed, "No stack traceback available\n" &
  264. "To create a stacktrace, rerun compilation with ./koch temp " &
  265. conf.command & " <file>")
  266. quit 1
  267. proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string) =
  268. if msg >= fatalMin and msg <= fatalMax:
  269. if conf.cmd == cmdIdeTools: log(s)
  270. quit(conf, msg)
  271. if msg >= errMin and msg <= errMax:
  272. inc(conf.errorCounter)
  273. conf.exitcode = 1'i8
  274. if conf.errorCounter >= conf.errorMax:
  275. quit(conf, msg)
  276. elif eh == doAbort and conf.cmd != cmdIdeTools:
  277. quit(conf, msg)
  278. elif eh == doRaise:
  279. raiseRecoverableError(s)
  280. proc `==`*(a, b: TLineInfo): bool =
  281. result = a.line == b.line and a.fileIndex == b.fileIndex
  282. proc exactEquals*(a, b: TLineInfo): bool =
  283. result = a.fileIndex == b.fileIndex and a.line == b.line and a.col == b.col
  284. proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
  285. const instantiationFrom = "template/generic instantiation from here"
  286. const instantiationOfFrom = "template/generic instantiation of `$1` from here"
  287. var info = lastinfo
  288. for i in 0 ..< len(conf.m.msgContext):
  289. let context = conf.m.msgContext[i]
  290. if context.info != lastinfo and context.info != info:
  291. if conf.structuredErrorHook != nil:
  292. conf.structuredErrorHook(conf, context.info, instantiationFrom,
  293. Severity.Error)
  294. else:
  295. let message = if context.detail == "":
  296. instantiationFrom
  297. else:
  298. instantiationOfFrom.format(context.detail)
  299. styledMsgWriteln(styleBright,
  300. PosFormat % [toMsgFilename(conf, context.info),
  301. coordToStr(context.info.line.int),
  302. coordToStr(context.info.col+1)],
  303. resetStyle,
  304. message)
  305. info = context.info
  306. proc ignoreMsgBecauseOfIdeTools(conf: ConfigRef; msg: TMsgKind): bool =
  307. msg >= errGenerated and conf.cmd == cmdIdeTools and optIdeDebug notin conf.globalOptions
  308. proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
  309. var
  310. title: string
  311. color: ForegroundColor
  312. kind: string
  313. sev: Severity
  314. case msg
  315. of errMin..errMax:
  316. sev = Severity.Error
  317. writeContext(conf, unknownLineInfo())
  318. title = ErrorTitle
  319. color = ErrorColor
  320. of warnMin..warnMax:
  321. sev = Severity.Warning
  322. if optWarns notin conf.options: return
  323. if msg notin conf.notes: return
  324. writeContext(conf, unknownLineInfo())
  325. title = WarningTitle
  326. color = WarningColor
  327. kind = WarningsToStr[ord(msg) - ord(warnMin)]
  328. inc(conf.warnCounter)
  329. of hintMin..hintMax:
  330. sev = Severity.Hint
  331. if optHints notin conf.options: return
  332. if msg notin conf.notes: return
  333. title = HintTitle
  334. color = HintColor
  335. if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
  336. inc(conf.hintCounter)
  337. let s = msgKindToString(msg) % args
  338. if conf.structuredErrorHook != nil:
  339. conf.structuredErrorHook(conf, unknownLineInfo(),
  340. s & (if kind.len > 0: KindFormat % kind else: ""), sev)
  341. if not ignoreMsgBecauseOfIdeTools(conf, msg):
  342. if kind.len > 0:
  343. styledMsgWriteln(color, title, resetStyle, s,
  344. KindColor, `%`(KindFormat, kind))
  345. else:
  346. styledMsgWriteln(color, title, resetStyle, s)
  347. handleError(conf, msg, doAbort, s)
  348. proc rawMessage*(conf: ConfigRef; msg: TMsgKind, arg: string) =
  349. rawMessage(conf, msg, [arg])
  350. proc resetAttributes*(conf: ConfigRef) =
  351. if {optUseColors, optStdout} * conf.globalOptions == {optUseColors}:
  352. terminal.resetAttributes(stderr)
  353. proc addSourceLine(conf: ConfigRef; fileIdx: FileIndex, line: string) =
  354. conf.m.fileInfos[fileIdx.int32].lines.add line
  355. proc sourceLine*(conf: ConfigRef; i: TLineInfo): string =
  356. if i.fileIndex.int32 < 0: return ""
  357. if not optPreserveOrigSource(conf) and conf.m.fileInfos[i.fileIndex.int32].lines.len == 0:
  358. try:
  359. for line in lines(toFullPath(conf, i)):
  360. addSourceLine conf, i.fileIndex, line.string
  361. except IOError:
  362. discard
  363. assert i.fileIndex.int32 < conf.m.fileInfos.len
  364. # can happen if the error points to EOF:
  365. if i.line.int > conf.m.fileInfos[i.fileIndex.int32].lines.len: return ""
  366. result = conf.m.fileInfos[i.fileIndex.int32].lines[i.line.int-1]
  367. proc writeSurroundingSrc(conf: ConfigRef; info: TLineInfo) =
  368. const indent = " "
  369. msgWriteln(conf, indent & $sourceLine(conf, info))
  370. msgWriteln(conf, indent & spaces(info.col) & '^')
  371. proc formatMsg*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string): string =
  372. let title = case msg
  373. of warnMin..warnMax: WarningTitle
  374. of hintMin..hintMax: HintTitle
  375. else: ErrorTitle
  376. result = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
  377. coordToStr(info.col+1)] &
  378. title &
  379. getMessageStr(msg, arg)
  380. proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
  381. eh: TErrorHandling) =
  382. var
  383. title: string
  384. color: ForegroundColor
  385. kind: string
  386. ignoreMsg = false
  387. sev: Severity
  388. case msg
  389. of errMin..errMax:
  390. sev = Severity.Error
  391. writeContext(conf, info)
  392. title = ErrorTitle
  393. color = ErrorColor
  394. # we try to filter error messages so that not two error message
  395. # in the same file and line are produced:
  396. #ignoreMsg = lastError == info and eh != doAbort
  397. conf.m.lastError = info
  398. of warnMin..warnMax:
  399. sev = Severity.Warning
  400. ignoreMsg = optWarns notin conf.options or msg notin conf.notes
  401. if not ignoreMsg: writeContext(conf, info)
  402. title = WarningTitle
  403. color = WarningColor
  404. kind = WarningsToStr[ord(msg) - ord(warnMin)]
  405. inc(conf.warnCounter)
  406. of hintMin..hintMax:
  407. sev = Severity.Hint
  408. ignoreMsg = optHints notin conf.options or msg notin conf.notes
  409. title = HintTitle
  410. color = HintColor
  411. if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
  412. inc(conf.hintCounter)
  413. # NOTE: currently line info line numbers start with 1,
  414. # but column numbers start with 0, however most editors expect
  415. # first column to be 1, so we need to +1 here
  416. let x = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
  417. coordToStr(info.col+1)]
  418. let s = getMessageStr(msg, arg)
  419. if not ignoreMsg:
  420. if conf.structuredErrorHook != nil:
  421. conf.structuredErrorHook(conf, info, s & (if kind.len > 0: KindFormat % kind else: ""), sev)
  422. if not ignoreMsgBecauseOfIdeTools(conf, msg):
  423. if kind.len > 0:
  424. styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s,
  425. KindColor, `%`(KindFormat, kind))
  426. else:
  427. styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s)
  428. if hintSource in conf.notes:
  429. conf.writeSurroundingSrc(info)
  430. handleError(conf, msg, eh, s)
  431. proc fatal*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
  432. # this fixes bug #7080 so that it is at least obvious 'fatal'
  433. # was executed.
  434. conf.m.errorOutputs = {eStdOut, eStdErr}
  435. liMessage(conf, info, msg, arg, doAbort)
  436. proc globalError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
  437. liMessage(conf, info, msg, arg, doRaise)
  438. proc globalError*(conf: ConfigRef; info: TLineInfo, arg: string) =
  439. liMessage(conf, info, errGenerated, arg, doRaise)
  440. proc localError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
  441. liMessage(conf, info, msg, arg, doNothing)
  442. proc localError*(conf: ConfigRef; info: TLineInfo, arg: string) =
  443. liMessage(conf, info, errGenerated, arg, doNothing)
  444. proc localError*(conf: ConfigRef; info: TLineInfo, format: string, params: openarray[string]) =
  445. localError(conf, info, format % params)
  446. proc message*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
  447. liMessage(conf, info, msg, arg, doNothing)
  448. proc internalError*(conf: ConfigRef; info: TLineInfo, errMsg: string) =
  449. if conf.cmd == cmdIdeTools and conf.structuredErrorHook.isNil: return
  450. writeContext(conf, info)
  451. liMessage(conf, info, errInternal, errMsg, doAbort)
  452. proc internalError*(conf: ConfigRef; errMsg: string) =
  453. if conf.cmd == cmdIdeTools and conf.structuredErrorHook.isNil: return
  454. writeContext(conf, unknownLineInfo())
  455. rawMessage(conf, errInternal, errMsg)
  456. template assertNotNil*(conf: ConfigRef; e): untyped =
  457. if e == nil: internalError(conf, $instantiationInfo())
  458. e
  459. template internalAssert*(conf: ConfigRef, e: bool) =
  460. if not e: internalError(conf, $instantiationInfo())
  461. proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
  462. assert i.fileIndex.int32 >= 0
  463. if optExcessiveStackTrace in conf.globalOptions:
  464. result = conf.m.fileInfos[i.fileIndex.int32].quotedFullName
  465. else:
  466. result = conf.m.fileInfos[i.fileIndex.int32].quotedName
  467. proc listWarnings*(conf: ConfigRef) =
  468. msgWriteln(conf, "Warnings:")
  469. for warn in warnMin..warnMax:
  470. msgWriteln(conf, " [$1] $2" % [
  471. if warn in conf.notes: "x" else: " ",
  472. lineinfos.WarningsToStr[ord(warn) - ord(warnMin)]
  473. ])
  474. proc listHints*(conf: ConfigRef) =
  475. msgWriteln(conf, "Hints:")
  476. for hint in hintMin..hintMax:
  477. msgWriteln(conf, " [$1] $2" % [
  478. if hint in conf.notes: "x" else: " ",
  479. lineinfos.HintsToStr[ord(hint) - ord(hintMin)]
  480. ])