lineinfos.nim 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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, tables, pathutils, hashes
  12. const
  13. explanationsBaseUrl* = "https://nim-lang.github.io/Nim"
  14. # was: "https://nim-lang.org/docs" but we're now usually showing devel docs
  15. # instead of latest release docs.
  16. proc createDocLink*(urlSuffix: string): string =
  17. # os.`/` is not appropriate for urls.
  18. result = explanationsBaseUrl
  19. if urlSuffix.len > 0 and urlSuffix[0] == '/':
  20. result.add urlSuffix
  21. else:
  22. result.add "/" & urlSuffix
  23. type
  24. TMsgKind* = enum
  25. errUnknown, errInternal, errIllFormedAstX, errCannotOpenFile,
  26. errXExpected,
  27. errGridTableNotImplemented,
  28. errMarkdownIllformedTable,
  29. errGeneralParseError,
  30. errNewSectionExpected,
  31. errInvalidDirectiveX,
  32. errProveInit, # deadcode
  33. errGenerated,
  34. errUser,
  35. warnCannotOpenFile = "CannotOpenFile", warnOctalEscape = "OctalEscape",
  36. warnXIsNeverRead = "XIsNeverRead", warnXmightNotBeenInit = "XmightNotBeenInit",
  37. warnDeprecated = "Deprecated", warnConfigDeprecated = "ConfigDeprecated",
  38. warnSmallLshouldNotBeUsed = "SmallLshouldNotBeUsed", warnUnknownMagic = "UnknownMagic",
  39. warnRedefinitionOfLabel = "RedefinitionOfLabel", warnUnknownSubstitutionX = "UnknownSubstitutionX",
  40. warnLanguageXNotSupported = "LanguageXNotSupported", warnFieldXNotSupported = "FieldXNotSupported",
  41. warnCommentXIgnored = "CommentXIgnored", warnTypelessParam = "TypelessParam",
  42. warnUseBase = "UseBase", warnWriteToForeignHeap = "WriteToForeignHeap",
  43. warnUnsafeCode = "UnsafeCode", warnUnusedImportX = "UnusedImport",
  44. warnInheritFromException = "InheritFromException", warnEachIdentIsTuple = "EachIdentIsTuple",
  45. warnUnsafeSetLen = "UnsafeSetLen", warnUnsafeDefault = "UnsafeDefault",
  46. warnProveInit = "ProveInit", warnProveField = "ProveField", warnProveIndex = "ProveIndex",
  47. warnUnreachableElse = "UnreachableElse", warnUnreachableCode = "UnreachableCode",
  48. warnStaticIndexCheck = "IndexCheck", warnGcUnsafe = "GcUnsafe", warnGcUnsafe2 = "GcUnsafe2",
  49. warnUninit = "Uninit", warnGcMem = "GcMem", warnDestructor = "Destructor",
  50. warnLockLevel = "LockLevel", warnResultShadowed = "ResultShadowed",
  51. warnInconsistentSpacing = "Spacing", warnCaseTransition = "CaseTransition",
  52. warnCycleCreated = "CycleCreated", warnObservableStores = "ObservableStores",
  53. warnUser = "User",
  54. hintSuccess = "Success", hintSuccessX = "SuccessX", hintCC = "CC",
  55. hintLineTooLong = "LineTooLong", hintXDeclaredButNotUsed = "XDeclaredButNotUsed",
  56. hintXCannotRaiseY = "XCannotRaiseY", hintConvToBaseNotNeeded = "ConvToBaseNotNeeded",
  57. hintConvFromXtoItselfNotNeeded = "ConvFromXtoItselfNotNeeded", hintExprAlwaysX = "ExprAlwaysX",
  58. hintQuitCalled = "QuitCalled", hintProcessing = "Processing", hintCodeBegin = "CodeBegin",
  59. hintCodeEnd = "CodeEnd", hintConf = "Conf", hintPath = "Path",
  60. hintConditionAlwaysTrue = "CondTrue", hintConditionAlwaysFalse = "CondFalse", hintName = "Name",
  61. hintPattern = "Pattern", hintExecuting = "Exec", hintLinking = "Link", hintDependency = "Dependency",
  62. hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace",
  63. hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro",
  64. hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext",
  65. hintMsgOrigin = "MsgOrigin", # since 1.3.5
  66. hintDeclaredLoc = "DeclaredLoc", # since 1.5.1
  67. const
  68. MsgKindToStr*: array[TMsgKind, string] = [
  69. errUnknown: "unknown error",
  70. errInternal: "internal error: $1",
  71. errIllFormedAstX: "illformed AST: $1",
  72. errCannotOpenFile: "cannot open '$1'",
  73. errXExpected: "'$1' expected",
  74. errGridTableNotImplemented: "grid table is not implemented",
  75. errMarkdownIllformedTable: "illformed delimiter row of a markdown table",
  76. errGeneralParseError: "general parse error",
  77. errNewSectionExpected: "new section expected",
  78. errInvalidDirectiveX: "invalid directive: '$1'",
  79. errProveInit: "Cannot prove that '$1' is initialized.", # deadcode
  80. errGenerated: "$1",
  81. errUser: "$1",
  82. warnCannotOpenFile: "cannot open '$1'",
  83. warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored",
  84. warnXIsNeverRead: "'$1' is never read",
  85. warnXmightNotBeenInit: "'$1' might not have been initialized",
  86. warnDeprecated: "$1",
  87. warnConfigDeprecated: "config file '$1' is deprecated",
  88. warnSmallLshouldNotBeUsed: "'l' should not be used as an identifier; may look like '1' (one)",
  89. warnUnknownMagic: "unknown magic '$1' might crash the compiler",
  90. warnRedefinitionOfLabel: "redefinition of label '$1'",
  91. warnUnknownSubstitutionX: "unknown substitution '$1'",
  92. warnLanguageXNotSupported: "language '$1' not supported",
  93. warnFieldXNotSupported: "field '$1' not supported",
  94. warnCommentXIgnored: "comment '$1' ignored",
  95. warnTypelessParam: "'$1' has no type. Typeless parameters are deprecated; only allowed for 'template'",
  96. warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
  97. warnWriteToForeignHeap: "write to foreign heap",
  98. warnUnsafeCode: "unsafe code: '$1'",
  99. warnUnusedImportX: "imported and not used: '$1'",
  100. warnInheritFromException: "inherit from a more precise exception type like ValueError, " &
  101. "IOError or OSError. If these don't suit, inherit from CatchableError or Defect.",
  102. warnEachIdentIsTuple: "each identifier is a tuple",
  103. warnUnsafeSetLen: "setLen can potentially expand the sequence, " &
  104. "but the element type '$1' doesn't have a valid default value",
  105. warnUnsafeDefault: "The '$1' type doesn't have a valid default value",
  106. warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
  107. warnProveField: "cannot prove that field '$1' is accessible",
  108. warnProveIndex: "cannot prove index '$1' is valid",
  109. warnUnreachableElse: "unreachable else, all cases are already covered",
  110. warnUnreachableCode: "unreachable code after 'return' statement or '{.noReturn.}' proc",
  111. warnStaticIndexCheck: "$1",
  112. warnGcUnsafe: "not GC-safe: '$1'",
  113. warnGcUnsafe2: "$1",
  114. warnUninit: "use explicit initialization of '$1' for clarity",
  115. warnGcMem: "'$1' uses GC'ed memory",
  116. warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future.",
  117. warnLockLevel: "$1",
  118. warnResultShadowed: "Special variable 'result' is shadowed.",
  119. warnInconsistentSpacing: "Number of spaces around '$#' is not consistent",
  120. warnCaseTransition: "Potential object case transition, instantiate new object instead",
  121. warnCycleCreated: "$1",
  122. warnObservableStores: "observable stores to '$1'",
  123. warnUser: "$1",
  124. hintSuccess: "operation successful: $#",
  125. # keep in sync with `testament.isSuccess`
  126. hintSuccessX: "${loc} lines; ${sec}s; $mem; $build build; proj: $project; out: $output",
  127. hintCC: "CC: $1",
  128. hintLineTooLong: "line too long",
  129. hintXDeclaredButNotUsed: "'$1' is declared but not used",
  130. hintXCannotRaiseY: "$1",
  131. hintConvToBaseNotNeeded: "conversion to base object is not needed",
  132. hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless",
  133. hintExprAlwaysX: "expression evaluates always to '$1'",
  134. hintQuitCalled: "quit() called",
  135. hintProcessing: "$1",
  136. hintCodeBegin: "generated code listing:",
  137. hintCodeEnd: "end of listing",
  138. hintConf: "used config file '$1'",
  139. hintPath: "added path: '$1'",
  140. hintConditionAlwaysTrue: "condition is always true: '$1'",
  141. hintConditionAlwaysFalse: "condition is always false: '$1'",
  142. hintName: "$1",
  143. hintPattern: "$1",
  144. hintExecuting: "$1",
  145. hintLinking: "$1",
  146. hintDependency: "$1",
  147. hintSource: "$1",
  148. hintPerformance: "$1",
  149. hintStackTrace: "$1",
  150. hintGCStats: "$1",
  151. hintGlobalVar: "global variable declared here",
  152. hintExpandMacro: "expanded macro: $1",
  153. hintUser: "$1",
  154. hintUserRaw: "$1",
  155. hintExtendedContext: "$1",
  156. hintMsgOrigin: "$1",
  157. hintDeclaredLoc: "$1",
  158. ]
  159. const
  160. fatalMin* = errUnknown
  161. fatalMax* = errInternal
  162. errMin* = errUnknown
  163. errMax* = errUser
  164. warnMin* = warnCannotOpenFile
  165. warnMax* = pred(hintSuccess)
  166. hintMin* = hintSuccess
  167. hintMax* = high(TMsgKind)
  168. type
  169. TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
  170. TNoteKinds* = set[TNoteKind]
  171. proc computeNotesVerbosity(): array[0..3, TNoteKinds] =
  172. result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnObservableStores}
  173. result[2] = result[3] - {hintStackTrace, warnUninit, hintExtendedContext, hintDeclaredLoc}
  174. result[1] = result[2] - {warnProveField, warnProveIndex,
  175. warnGcUnsafe, hintPath, hintDependency, hintCodeBegin, hintCodeEnd,
  176. hintSource, hintGlobalVar, hintGCStats, hintMsgOrigin}
  177. result[0] = result[1] - {hintSuccessX, hintSuccess, hintConf,
  178. hintProcessing, hintPattern, hintExecuting, hintLinking, hintCC}
  179. const
  180. NotesVerbosity* = computeNotesVerbosity()
  181. errXMustBeCompileTime* = "'$1' can only be used in compile-time context"
  182. errArgsNeedRunOption* = "arguments can only be given if the '--run' option is selected"
  183. type
  184. TFileInfo* = object
  185. fullPath*: AbsoluteFile # This is a canonical full filesystem path
  186. projPath*: RelativeFile # This is relative to the project's root
  187. shortName*: string # short name of the module
  188. quotedName*: Rope # cached quoted short name for codegen
  189. # purposes
  190. quotedFullName*: Rope # cached quoted full name for codegen
  191. # purposes
  192. lines*: seq[string] # the source code of the module
  193. # used for better error messages and
  194. # embedding the original source in the
  195. # generated code
  196. dirtyFile*: AbsoluteFile # the file that is actually read into memory
  197. # and parsed; usually "" but is used
  198. # for 'nimsuggest'
  199. hash*: string # the checksum of the file
  200. dirty*: bool # for 'nimfix' / 'nimpretty' like tooling
  201. when defined(nimpretty):
  202. fullContent*: string
  203. FileIndex* = distinct int32
  204. TLineInfo* = object # This is designed to be as small as possible,
  205. # because it is used
  206. # in syntax nodes. We save space here by using
  207. # two int16 and an int32.
  208. # On 64 bit and on 32 bit systems this is
  209. # only 8 bytes.
  210. line*: uint16
  211. col*: int16
  212. fileIndex*: FileIndex
  213. when defined(nimpretty):
  214. offsetA*, offsetB*: int
  215. commentOffsetA*, commentOffsetB*: int
  216. TErrorOutput* = enum
  217. eStdOut
  218. eStdErr
  219. TErrorOutputs* = set[TErrorOutput]
  220. ERecoverableError* = object of ValueError
  221. ESuggestDone* = object of ValueError
  222. proc `==`*(a, b: FileIndex): bool {.borrow.}
  223. proc hash*(i: TLineInfo): Hash =
  224. hash (i.line.int, i.col.int, i.fileIndex.int)
  225. proc raiseRecoverableError*(msg: string) {.noinline.} =
  226. raise newException(ERecoverableError, msg)
  227. const
  228. InvalidFileIdx* = FileIndex(-1)
  229. unknownLineInfo* = TLineInfo(line: 0, col: -1, fileIndex: InvalidFileIdx)
  230. type
  231. Severity* {.pure.} = enum ## VS Code only supports these three
  232. Hint, Warning, Error
  233. const
  234. trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
  235. # are produced within comments and string literals
  236. commandLineIdx* = FileIndex(-3)
  237. type
  238. MsgConfig* = object ## does not need to be stored in the incremental cache
  239. trackPos*: TLineInfo
  240. trackPosAttached*: bool ## whether the tracking position was attached to
  241. ## some close token.
  242. errorOutputs*: TErrorOutputs
  243. msgContext*: seq[tuple[info: TLineInfo, detail: string]]
  244. lastError*: TLineInfo
  245. filenameToIndexTbl*: Table[string, FileIndex]
  246. fileInfos*: seq[TFileInfo]
  247. systemFileIdx*: FileIndex
  248. proc initMsgConfig*(): MsgConfig =
  249. result.msgContext = @[]
  250. result.lastError = unknownLineInfo
  251. result.filenameToIndexTbl = initTable[string, FileIndex]()
  252. result.fileInfos = @[]
  253. result.errorOutputs = {eStdOut, eStdErr}