lineinfos.nim 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2018 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module contains the `TMsgKind` enum as well as the
  10. ## `TLineInfo` object.
  11. import ropes, pathutils
  12. import std/[hashes, tables]
  13. const
  14. explanationsBaseUrl* = "https://nim-lang.github.io/Nim"
  15. # was: "https://nim-lang.org/docs" but we're now usually showing devel docs
  16. # instead of latest release docs.
  17. proc createDocLink*(urlSuffix: string): string =
  18. # os.`/` is not appropriate for urls.
  19. result = explanationsBaseUrl
  20. if urlSuffix.len > 0 and urlSuffix[0] == '/':
  21. result.add urlSuffix
  22. else:
  23. result.add "/" & urlSuffix
  24. type
  25. TMsgKind* = enum
  26. # fatal errors
  27. errUnknown, errFatal, errInternal,
  28. # non-fatal errors
  29. errIllFormedAstX, errCannotOpenFile,
  30. errXExpected,
  31. errRstMissingClosing,
  32. errRstGridTableNotImplemented,
  33. errRstMarkdownIllformedTable,
  34. errRstIllformedTable,
  35. errRstNewSectionExpected,
  36. errRstGeneralParseError,
  37. errRstInvalidDirectiveX,
  38. errRstInvalidField,
  39. errRstFootnoteMismatch,
  40. errRstSandboxedDirective,
  41. errProveInit, # deadcode
  42. errGenerated,
  43. errFailedMove,
  44. errUser,
  45. # warnings
  46. warnCannotOpenFile = "CannotOpenFile", warnOctalEscape = "OctalEscape",
  47. warnXIsNeverRead = "XIsNeverRead", warnXmightNotBeenInit = "XmightNotBeenInit",
  48. warnDeprecated = "Deprecated", warnConfigDeprecated = "ConfigDeprecated",
  49. warnDotLikeOps = "DotLikeOps",
  50. warnSmallLshouldNotBeUsed = "SmallLshouldNotBeUsed", warnUnknownMagic = "UnknownMagic",
  51. warnRstRedefinitionOfLabel = "RedefinitionOfLabel",
  52. warnRstUnknownSubstitutionX = "UnknownSubstitutionX",
  53. warnRstAmbiguousLink = "AmbiguousLink",
  54. warnRstBrokenLink = "BrokenLink",
  55. warnRstLanguageXNotSupported = "LanguageXNotSupported",
  56. warnRstFieldXNotSupported = "FieldXNotSupported",
  57. warnRstUnusedImportdoc = "UnusedImportdoc",
  58. warnRstStyle = "warnRstStyle",
  59. warnCommentXIgnored = "CommentXIgnored",
  60. warnTypelessParam = "TypelessParam",
  61. warnUseBase = "UseBase", warnWriteToForeignHeap = "WriteToForeignHeap",
  62. warnUnsafeCode = "UnsafeCode", warnUnusedImportX = "UnusedImport",
  63. warnInheritFromException = "InheritFromException", warnEachIdentIsTuple = "EachIdentIsTuple",
  64. warnUnsafeSetLen = "UnsafeSetLen", warnUnsafeDefault = "UnsafeDefault",
  65. warnProveInit = "ProveInit", warnProveField = "ProveField", warnProveIndex = "ProveIndex",
  66. warnUnreachableElse = "UnreachableElse", warnUnreachableCode = "UnreachableCode",
  67. warnStaticIndexCheck = "IndexCheck", warnGcUnsafe = "GcUnsafe", warnGcUnsafe2 = "GcUnsafe2",
  68. warnUninit = "Uninit", warnGcMem = "GcMem", warnDestructor = "Destructor",
  69. warnLockLevel = "LockLevel", # deadcode
  70. warnResultShadowed = "ResultShadowed",
  71. warnInconsistentSpacing = "Spacing", warnCaseTransition = "CaseTransition",
  72. warnCycleCreated = "CycleCreated", warnObservableStores = "ObservableStores",
  73. warnStrictNotNil = "StrictNotNil",
  74. warnResultUsed = "ResultUsed",
  75. warnCannotOpen = "CannotOpen",
  76. warnFileChanged = "FileChanged",
  77. warnSuspiciousEnumConv = "EnumConv",
  78. warnAnyEnumConv = "AnyEnumConv",
  79. warnHoleEnumConv = "HoleEnumConv",
  80. warnCstringConv = "CStringConv",
  81. warnPtrToCstringConv = "PtrToCstringConv",
  82. warnEffect = "Effect",
  83. warnCastSizes = "CastSizes", # deadcode
  84. warnAboveMaxSizeSet = "AboveMaxSizeSet",
  85. warnImplicitTemplateRedefinition = "ImplicitTemplateRedefinition",
  86. warnUnnamedBreak = "UnnamedBreak",
  87. warnStmtListLambda = "StmtListLambda",
  88. warnBareExcept = "BareExcept",
  89. warnImplicitDefaultValue = "ImplicitDefaultValue",
  90. warnIgnoredSymbolInjection = "IgnoredSymbolInjection",
  91. warnStdPrefix = "StdPrefix"
  92. warnUser = "User",
  93. warnGlobalVarConstructorTemporary = "GlobalVarConstructorTemporary",
  94. # hints
  95. hintSuccess = "Success", hintSuccessX = "SuccessX",
  96. hintCC = "CC",
  97. hintXDeclaredButNotUsed = "XDeclaredButNotUsed", hintDuplicateModuleImport = "DuplicateModuleImport",
  98. hintXCannotRaiseY = "XCannotRaiseY", hintConvToBaseNotNeeded = "ConvToBaseNotNeeded",
  99. hintConvFromXtoItselfNotNeeded = "ConvFromXtoItselfNotNeeded", hintExprAlwaysX = "ExprAlwaysX",
  100. hintQuitCalled = "QuitCalled", hintProcessing = "Processing", hintProcessingStmt = "ProcessingStmt", hintCodeBegin = "CodeBegin",
  101. hintCodeEnd = "CodeEnd", hintConf = "Conf", hintPath = "Path",
  102. hintConditionAlwaysTrue = "CondTrue", hintConditionAlwaysFalse = "CondFalse", hintName = "Name",
  103. hintPattern = "Pattern", hintExecuting = "Exec", hintLinking = "Link", hintDependency = "Dependency",
  104. hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace",
  105. hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro",
  106. hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext",
  107. hintMsgOrigin = "MsgOrigin", # since 1.3.5
  108. hintDeclaredLoc = "DeclaredLoc", # since 1.5.1
  109. hintUnknownHint = "UnknownHint"
  110. const
  111. MsgKindToStr*: array[TMsgKind, string] = [
  112. errUnknown: "unknown error",
  113. errFatal: "fatal error: $1",
  114. errInternal: "internal error: $1",
  115. errIllFormedAstX: "illformed AST: $1",
  116. errCannotOpenFile: "cannot open '$1'",
  117. errXExpected: "'$1' expected",
  118. errRstMissingClosing: "$1",
  119. errRstGridTableNotImplemented: "grid table is not implemented",
  120. errRstMarkdownIllformedTable: "illformed delimiter row of a markdown table",
  121. errRstIllformedTable: "Illformed table: $1",
  122. errRstNewSectionExpected: "new section expected $1",
  123. errRstGeneralParseError: "general parse error",
  124. errRstInvalidDirectiveX: "invalid directive: '$1'",
  125. errRstInvalidField: "invalid field: $1",
  126. errRstFootnoteMismatch: "number of footnotes and their references don't match: $1",
  127. errRstSandboxedDirective: "disabled directive: '$1'",
  128. errProveInit: "Cannot prove that '$1' is initialized.", # deadcode
  129. errGenerated: "$1",
  130. errFailedMove: "$1",
  131. errUser: "$1",
  132. warnCannotOpenFile: "cannot open '$1'",
  133. warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored",
  134. warnXIsNeverRead: "'$1' is never read",
  135. warnXmightNotBeenInit: "'$1' might not have been initialized",
  136. warnDeprecated: "$1",
  137. warnConfigDeprecated: "config file '$1' is deprecated",
  138. warnDotLikeOps: "$1",
  139. warnSmallLshouldNotBeUsed: "'l' should not be used as an identifier; may look like '1' (one)",
  140. warnUnknownMagic: "unknown magic '$1' might crash the compiler",
  141. warnRstRedefinitionOfLabel: "redefinition of label '$1'",
  142. warnRstUnknownSubstitutionX: "unknown substitution '$1'",
  143. warnRstAmbiguousLink: "ambiguous doc link $1",
  144. warnRstBrokenLink: "broken link '$1'",
  145. warnRstLanguageXNotSupported: "language '$1' not supported",
  146. warnRstFieldXNotSupported: "field '$1' not supported",
  147. warnRstUnusedImportdoc: "importdoc for '$1' is not used",
  148. warnRstStyle: "RST style: $1",
  149. warnCommentXIgnored: "comment '$1' ignored",
  150. warnTypelessParam: "", # deadcode
  151. warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
  152. warnWriteToForeignHeap: "write to foreign heap",
  153. warnUnsafeCode: "unsafe code: '$1'",
  154. warnUnusedImportX: "imported and not used: '$1'",
  155. warnInheritFromException: "inherit from a more precise exception type like ValueError, " &
  156. "IOError or OSError. If these don't suit, inherit from CatchableError or Defect.",
  157. warnEachIdentIsTuple: "each identifier is a tuple",
  158. warnUnsafeSetLen: "setLen can potentially expand the sequence, " &
  159. "but the element type '$1' doesn't have a valid default value",
  160. warnUnsafeDefault: "The '$1' type doesn't have a valid default value",
  161. warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
  162. warnProveField: "cannot prove that field '$1' is accessible",
  163. warnProveIndex: "cannot prove index '$1' is valid",
  164. warnUnreachableElse: "unreachable else, all cases are already covered",
  165. warnUnreachableCode: "unreachable code after 'return' statement or '{.noReturn.}' proc",
  166. warnStaticIndexCheck: "$1",
  167. warnGcUnsafe: "not GC-safe: '$1'",
  168. warnGcUnsafe2: "$1",
  169. warnUninit: "use explicit initialization of '$1' for clarity",
  170. warnGcMem: "'$1' uses GC'ed memory",
  171. warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future.",
  172. warnLockLevel: "$1", # deadcode
  173. warnResultShadowed: "Special variable 'result' is shadowed.",
  174. warnInconsistentSpacing: "Number of spaces around '$#' is not consistent",
  175. warnCaseTransition: "Potential object case transition, instantiate new object instead",
  176. warnCycleCreated: "$1",
  177. warnObservableStores: "observable stores to '$1'",
  178. warnStrictNotNil: "$1",
  179. warnResultUsed: "used 'result' variable",
  180. warnCannotOpen: "cannot open: $1",
  181. warnFileChanged: "file changed: $1",
  182. warnSuspiciousEnumConv: "$1",
  183. warnAnyEnumConv: "$1",
  184. warnHoleEnumConv: "$1",
  185. warnCstringConv: "$1",
  186. warnPtrToCstringConv: "unsafe conversion to 'cstring' from '$1'; Use a `cast` operation like `cast[cstring](x)`; this will become a compile time error in the future",
  187. warnEffect: "$1",
  188. warnCastSizes: "$1", # deadcode
  189. warnAboveMaxSizeSet: "$1",
  190. warnImplicitTemplateRedefinition: "template '$1' is implicitly redefined; this is deprecated, add an explicit .redefine pragma",
  191. warnUnnamedBreak: "Using an unnamed break in a block is deprecated; Use a named block with a named break instead",
  192. warnStmtListLambda: "statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead",
  193. warnBareExcept: "$1",
  194. warnImplicitDefaultValue: "$1",
  195. warnIgnoredSymbolInjection: "$1",
  196. warnStdPrefix: "$1 needs the 'std' prefix",
  197. warnUser: "$1",
  198. warnGlobalVarConstructorTemporary: "global variable '$1' initialization requires a temporary variable",
  199. hintSuccess: "operation successful: $#",
  200. # keep in sync with `testament.isSuccess`
  201. hintSuccessX: "$build\n$loc lines; ${sec}s; $mem; proj: $project; out: $output",
  202. hintCC: "CC: $1",
  203. hintXDeclaredButNotUsed: "'$1' is declared but not used",
  204. hintDuplicateModuleImport: "$1",
  205. hintXCannotRaiseY: "$1",
  206. hintConvToBaseNotNeeded: "conversion to base object is not needed",
  207. hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless",
  208. hintExprAlwaysX: "expression evaluates always to '$1'",
  209. hintQuitCalled: "quit() called",
  210. hintProcessing: "$1",
  211. hintProcessingStmt: "$1",
  212. hintCodeBegin: "generated code listing:",
  213. hintCodeEnd: "end of listing",
  214. hintConf: "used config file '$1'",
  215. hintPath: "added path: '$1'",
  216. hintConditionAlwaysTrue: "condition is always true: '$1'",
  217. hintConditionAlwaysFalse: "condition is always false: '$1'",
  218. hintName: "$1",
  219. hintPattern: "$1",
  220. hintExecuting: "$1",
  221. hintLinking: "$1",
  222. hintDependency: "$1",
  223. hintSource: "$1",
  224. hintPerformance: "$1",
  225. hintStackTrace: "$1",
  226. hintGCStats: "$1",
  227. hintGlobalVar: "global variable declared here",
  228. hintExpandMacro: "expanded macro: $1",
  229. hintUser: "$1",
  230. hintUserRaw: "$1",
  231. hintExtendedContext: "$1",
  232. hintMsgOrigin: "$1",
  233. hintDeclaredLoc: "$1",
  234. hintUnknownHint: "unknown hint: $1"
  235. ]
  236. const
  237. fatalMsgs* = {errUnknown..errInternal}
  238. errMin* = errUnknown
  239. errMax* = errUser
  240. warnMin* = warnCannotOpenFile
  241. warnMax* = pred(hintSuccess)
  242. hintMin* = hintSuccess
  243. hintMax* = high(TMsgKind)
  244. rstWarnings* = {warnRstRedefinitionOfLabel..warnRstStyle}
  245. type
  246. TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
  247. TNoteKinds* = set[TNoteKind]
  248. proc computeNotesVerbosity(): array[0..3, TNoteKinds] =
  249. result = default(array[0..3, TNoteKinds])
  250. result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnObservableStores, warnResultUsed, warnAnyEnumConv, warnBareExcept, warnStdPrefix}
  251. result[2] = result[3] - {hintStackTrace, hintExtendedContext, hintDeclaredLoc, hintProcessingStmt}
  252. result[1] = result[2] - {warnProveField, warnProveIndex,
  253. warnGcUnsafe, hintPath, hintDependency, hintCodeBegin, hintCodeEnd,
  254. hintSource, hintGlobalVar, hintGCStats, hintMsgOrigin, hintPerformance}
  255. result[0] = result[1] - {hintSuccessX, hintSuccess, hintConf,
  256. hintProcessing, hintPattern, hintExecuting, hintLinking, hintCC}
  257. const
  258. NotesVerbosity* = computeNotesVerbosity()
  259. errXMustBeCompileTime* = "'$1' can only be used in compile-time context"
  260. errArgsNeedRunOption* = "arguments can only be given if the '--run' option is selected"
  261. type
  262. TFileInfo* = object
  263. fullPath*: AbsoluteFile # This is a canonical full filesystem path
  264. projPath*: RelativeFile # This is relative to the project's root
  265. shortName*: string # short name of the module
  266. quotedName*: Rope # cached quoted short name for codegen
  267. # purposes
  268. quotedFullName*: Rope # cached quoted full name for codegen
  269. # purposes
  270. lines*: seq[string] # the source code of the module
  271. # used for better error messages and
  272. # embedding the original source in the
  273. # generated code
  274. dirtyFile*: AbsoluteFile # the file that is actually read into memory
  275. # and parsed; usually "" but is used
  276. # for 'nimsuggest'
  277. hash*: string # the checksum of the file
  278. dirty*: bool # for 'nimpretty' like tooling
  279. when defined(nimpretty):
  280. fullContent*: string
  281. FileIndex* = distinct int32
  282. TLineInfo* = object # This is designed to be as small as possible,
  283. # because it is used
  284. # in syntax nodes. We save space here by using
  285. # two int16 and an int32.
  286. # On 64 bit and on 32 bit systems this is
  287. # only 8 bytes.
  288. line*: uint16
  289. col*: int16
  290. fileIndex*: FileIndex
  291. when defined(nimpretty):
  292. offsetA*, offsetB*: int
  293. commentOffsetA*, commentOffsetB*: int
  294. TErrorOutput* = enum
  295. eStdOut
  296. eStdErr
  297. TErrorOutputs* = set[TErrorOutput]
  298. ERecoverableError* = object of ValueError
  299. ESuggestDone* = object of ValueError
  300. proc `==`*(a, b: FileIndex): bool {.borrow.}
  301. proc hash*(i: TLineInfo): Hash =
  302. hash (i.line.int, i.col.int, i.fileIndex.int)
  303. proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} =
  304. raise newException(ERecoverableError, msg)
  305. const
  306. InvalidFileIdx* = FileIndex(-1)
  307. unknownLineInfo* = TLineInfo(line: 0, col: -1, fileIndex: InvalidFileIdx)
  308. type
  309. Severity* {.pure.} = enum ## VS Code only supports these three
  310. Hint, Warning, Error
  311. const
  312. trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
  313. # are produced within comments and string literals
  314. commandLineIdx* = FileIndex(-3)
  315. type
  316. MsgConfig* = object ## does not need to be stored in the incremental cache
  317. trackPos*: TLineInfo
  318. trackPosAttached*: bool ## whether the tracking position was attached to
  319. ## some close token.
  320. errorOutputs*: TErrorOutputs
  321. msgContext*: seq[tuple[info: TLineInfo, detail: string]]
  322. lastError*: TLineInfo
  323. filenameToIndexTbl*: Table[string, FileIndex]
  324. fileInfos*: seq[TFileInfo]
  325. systemFileIdx*: FileIndex
  326. proc initMsgConfig*(): MsgConfig =
  327. result = MsgConfig(msgContext: @[], lastError: unknownLineInfo,
  328. filenameToIndexTbl: initTable[string, FileIndex](),
  329. fileInfos: @[], errorOutputs: {eStdOut, eStdErr}
  330. )
  331. result.filenameToIndexTbl["???"] = FileIndex(-1)