summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/compilerlog.nim9
-rw-r--r--compiler/msgs.nim65
-rw-r--r--compiler/options.nim6
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--compiler/suggest.nim7
5 files changed, 53 insertions, 36 deletions
diff --git a/compiler/compilerlog.nim b/compiler/compilerlog.nim
deleted file mode 100644
index fbf8cd9aa..000000000
--- a/compiler/compilerlog.nim
+++ /dev/null
@@ -1,9 +0,0 @@
-
-from os import getHomeDir, `/`
-
-proc logStr*(line: string) =
-  var f: File
-  if open(f, getHomeDir() / "nimsuggest.log", fmAppend):
-    f.writeLine(line)
-    f.close()
-
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index acf171cbe..c7b97deee 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -631,12 +631,17 @@ proc unknownLineInfo*(): TLineInfo =
   result.col = int16(-1)
   result.fileIndex = -1
 
+type
+  Severity* {.pure.} = enum ## VS Code only supports these three
+    Hint, Warning, Error
+
 var
   msgContext: seq[TLineInfo] = @[]
   lastError = unknownLineInfo()
 
   errorOutputs* = {eStdOut, eStdErr}
   writelnHook*: proc (output: string) {.closure.}
+  structuredErrorHook*: proc (info: TLineInfo; msg: string; severity: Severity) {.closure.}
 
 proc suggestWriteln*(s: string) =
   if eStdOut in errorOutputs:
@@ -745,6 +750,8 @@ proc msgWriteln*(s: string, flags: MsgFlags = {}) =
   ## is present, then it is used to output message rather than stderr/stdout.
   ## This behavior can be altered by given optional flags.
 
+  ## This is used for 'nim dump' etc. where we don't have nimsuggest
+  ## support.
   #if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
 
   if not isNil(writelnHook) and msgSkipHook notin flags:
@@ -833,7 +840,7 @@ proc quit(msg: TMsgKind) =
 
 proc log*(s: string) {.procvar.} =
   var f: File
-  if open(f, "nimsuggest.log", fmAppend):
+  if open(f, getHomeDir() / "nimsuggest.log", fmAppend):
     f.writeLine(s)
     close(f)
 
@@ -858,12 +865,16 @@ proc writeContext(lastinfo: TLineInfo) =
   var info = lastinfo
   for i in countup(0, len(msgContext) - 1):
     if msgContext[i] != lastinfo and msgContext[i] != info:
-      styledMsgWriteln(styleBright,
-                       PosFormat % [toMsgFilename(msgContext[i]),
-                                    coordToStr(msgContext[i].line),
-                                    coordToStr(msgContext[i].col+1)],
-                       resetStyle,
-                       getMessageStr(errInstantiationFrom, ""))
+      if structuredErrorHook != nil:
+        structuredErrorHook(msgContext[i], getMessageStr(errInstantiationFrom, ""),
+                            Severity.Error)
+      else:
+        styledMsgWriteln(styleBright,
+                         PosFormat % [toMsgFilename(msgContext[i]),
+                                      coordToStr(msgContext[i].line),
+                                      coordToStr(msgContext[i].col+1)],
+                         resetStyle,
+                         getMessageStr(errInstantiationFrom, ""))
     info = msgContext[i]
 
 proc ignoreMsgBecauseOfIdeTools(msg: TMsgKind): bool =
@@ -873,13 +884,16 @@ proc rawMessage*(msg: TMsgKind, args: openArray[string]) =
   var
     title: string
     color: ForegroundColor
-    kind:  string
+    kind: string
+    sev: Severity
   case msg
   of errMin..errMax:
+    sev = Severity.Error
     writeContext(unknownLineInfo())
     title = ErrorTitle
     color = ErrorColor
   of warnMin..warnMax:
+    sev = Severity.Warning
     if optWarns notin gOptions: return
     if msg notin gNotes: return
     writeContext(unknownLineInfo())
@@ -888,13 +902,18 @@ proc rawMessage*(msg: TMsgKind, args: openArray[string]) =
     kind = WarningsToStr[ord(msg) - ord(warnMin)]
     inc(gWarnCounter)
   of hintMin..hintMax:
+    sev = Severity.Hint
     if optHints notin gOptions: return
     if msg notin gNotes: return
     title = HintTitle
     color = HintColor
     kind = HintsToStr[ord(msg) - ord(hintMin)]
     inc(gHintCounter)
-  let s = `%`(msgKindToString(msg), args)
+  let s = msgKindToString(msg) % args
+
+  if structuredErrorHook != nil:
+    structuredErrorHook(unknownLineInfo(), s & (if kind != nil: KindFormat % kind else: ""), sev)
+
   if not ignoreMsgBecauseOfIdeTools(msg):
     if kind != nil:
       styledMsgWriteln(color, title, resetStyle, s,
@@ -932,8 +951,10 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
     color: ForegroundColor
     kind:  string
     ignoreMsg = false
+    sev: Severity
   case msg
   of errMin..errMax:
+    sev = Severity.Error
     writeContext(info)
     title = ErrorTitle
     color = ErrorColor
@@ -942,6 +963,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
     #ignoreMsg = lastError == info and eh != doAbort
     lastError = info
   of warnMin..warnMax:
+    sev = Severity.Warning
     ignoreMsg = optWarns notin gOptions or msg notin gNotes
     if not ignoreMsg: writeContext(info)
     title = WarningTitle
@@ -949,6 +971,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
     kind = WarningsToStr[ord(msg) - ord(warnMin)]
     inc(gWarnCounter)
   of hintMin..hintMax:
+    sev = Severity.Hint
     ignoreMsg = optHints notin gOptions or msg notin gNotes
     title = HintTitle
     color = HintColor
@@ -960,14 +983,18 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
   let x = PosFormat % [toMsgFilename(info), coordToStr(info.line),
                        coordToStr(info.col+1)]
   let s = getMessageStr(msg, arg)
-  if not ignoreMsg and not ignoreMsgBecauseOfIdeTools(msg):
-    if kind != nil:
-      styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s,
-                       KindColor, `%`(KindFormat, kind))
-    else:
-      styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s)
-    if msg in errMin..errMax and hintSource in gNotes:
-      info.writeSurroundingSrc
+
+  if not ignoreMsg:
+    if structuredErrorHook != nil:
+      structuredErrorHook(info, s & (if kind != nil: KindFormat % kind else: ""), sev)
+    if not ignoreMsgBecauseOfIdeTools(msg):
+      if kind != nil:
+        styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s,
+                         KindColor, `%`(KindFormat, kind))
+      else:
+        styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s)
+      if msg in errMin..errMax and hintSource in gNotes:
+        info.writeSurroundingSrc
   handleError(msg, eh, s)
 
 proc fatal*(info: TLineInfo, msg: TMsgKind, arg = "") =
@@ -992,12 +1019,12 @@ proc message*(info: TLineInfo, msg: TMsgKind, arg = "") =
   liMessage(info, msg, arg, doNothing)
 
 proc internalError*(info: TLineInfo, errMsg: string) =
-  if gCmd == cmdIdeTools: return
+  if gCmd == cmdIdeTools and structuredErrorHook.isNil: return
   writeContext(info)
   liMessage(info, errInternal, errMsg, doAbort)
 
 proc internalError*(errMsg: string) =
-  if gCmd == cmdIdeTools: return
+  if gCmd == cmdIdeTools and structuredErrorHook.isNil: return
   writeContext(unknownLineInfo())
   rawMessage(errInternal, errMsg)
 
diff --git a/compiler/options.nim b/compiler/options.nim
index 6281980ff..c6d016095 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -100,7 +100,7 @@ type
 
   IdeCmd* = enum
     ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod,
-    ideHighlight, ideOutline, ideKnown
+    ideHighlight, ideOutline, ideKnown, ideMsg
 
   ConfigRef* = ref object ## eventually all global configuration should be moved here
     cppDefines*: HashSet[string]
@@ -349,7 +349,7 @@ proc rawFindFile2(f: string): string =
       # bring to front
       for j in countDown(i,1):
         swap(lazyPaths[j], lazyPaths[j-1])
-      
+
       return result.canonicalizePath
   result = ""
 
@@ -437,6 +437,7 @@ proc parseIdeCmd*(s: string): IdeCmd =
   of "highlight": ideHighlight
   of "outline": ideOutline
   of "known": ideKnown
+  of "msg": ideMsg
   else: ideNone
 
 proc `$`*(c: IdeCmd): string =
@@ -452,3 +453,4 @@ proc `$`*(c: IdeCmd): string =
   of ideHighlight: "highlight"
   of ideOutline: "outline"
   of ideKnown: "known"
+  of ideMsg: "msg"
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 18680864a..7c6e3af6d 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1193,8 +1193,6 @@ type
     stepRegisterSymbol,
     stepDetermineType,
 
-import compilerlog
-
 proc hasObjParam(s: PSym): bool =
   var t = s.typ
   for col in countup(1, sonsLen(t)-1):
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index 41d61c12a..1b102e4fe 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -9,7 +9,7 @@
 
 ## This file implements features required for IDE support.
 ##
-## Due to Nim's natures and the fact that ``system.nim`` is always imported,
+## Due to Nim's nature and the fact that ``system.nim`` is always imported,
 ## there are lots of potential symbols. Furthermore thanks to templates and
 ## macros even context based analysis does not help much: In a context like
 ## ``let x: |`` where a type has to follow, that type might be constructed from
@@ -126,7 +126,8 @@ proc `$`*(suggest: Suggest): string =
   else:
     result.add($suggest.symkind)
     result.add(sep)
-    result.add(suggest.qualifiedPath.join("."))
+    if suggest.qualifiedPath != nil:
+      result.add(suggest.qualifiedPath.join("."))
     result.add(sep)
     result.add(suggest.forth)
     result.add(sep)
@@ -161,8 +162,6 @@ proc filterSym(s: PSym; prefix: PNode): bool {.inline.} =
       if n.len > 0:
         result = prefixMatch(s, n[0])
     else: discard
-    if result:
-      echo "indeed a prefix match ", n
   if s.kind != skModule:
     result = prefix.isNil or prefixMatch(s, prefix)