summary refs log tree commit diff stats
path: root/compiler/ic/navigator.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/ic/navigator.nim')
-rw-r--r--compiler/ic/navigator.nim73
1 files changed, 41 insertions, 32 deletions
diff --git a/compiler/ic/navigator.nim b/compiler/ic/navigator.nim
index ab49b3b7a..39037b94f 100644
--- a/compiler/ic/navigator.nim
+++ b/compiler/ic/navigator.nim
@@ -11,29 +11,34 @@
 ## IDE-like features. It uses the set of .rod files to accomplish
 ## its task. The set must cover a complete Nim project.
 
-import sets
+import std/[sets, tables]
 
-from os import nil
+from std/os import nil
 from std/private/miscdollars import toLocation
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
 import ".." / [ast, modulegraphs, msgs, options]
+import iclineinfos
 import packed_ast, bitabs, ic
 
 type
+  UnpackedLineInfo = object
+    file: LitId
+    line, col: int
   NavContext = object
     g: ModuleGraph
     thisModule: int32
-    trackPos: PackedLineInfo
+    trackPos: UnpackedLineInfo
     alreadyEmitted: HashSet[string]
     outputSep: char # for easier testing, use short filenames and spaces instead of tabs.
 
-proc isTracked(current, trackPos: PackedLineInfo, tokenLen: int): bool =
-  if current.file == trackPos.file and current.line == trackPos.line:
+proc isTracked(man: LineInfoManager; current: PackedLineInfo, trackPos: UnpackedLineInfo, tokenLen: int): bool =
+  let (currentFile, currentLine, currentCol) = man.unpack(current)
+  if currentFile == trackPos.file and currentLine == trackPos.line:
     let col = trackPos.col
-    if col >= current.col and col < current.col+tokenLen:
+    if col >= currentCol and col < currentCol+tokenLen:
       result = true
     else:
       result = false
@@ -42,32 +47,34 @@ proc isTracked(current, trackPos: PackedLineInfo, tokenLen: int): bool =
 
 proc searchLocalSym(c: var NavContext; s: PackedSym; info: PackedLineInfo): bool =
   result = s.name != LitId(0) and
-    isTracked(info, c.trackPos, c.g.packed[c.thisModule].fromDisk.strings[s.name].len)
+    isTracked(c.g.packed[c.thisModule].fromDisk.man, info, c.trackPos, c.g.packed[c.thisModule].fromDisk.strings[s.name].len)
 
 proc searchForeignSym(c: var NavContext; s: ItemId; info: PackedLineInfo): bool =
   let name = c.g.packed[s.module].fromDisk.syms[s.item].name
   result = name != LitId(0) and
-    isTracked(info, c.trackPos, c.g.packed[s.module].fromDisk.strings[name].len)
+    isTracked(c.g.packed[c.thisModule].fromDisk.man, info, c.trackPos, c.g.packed[s.module].fromDisk.strings[name].len)
 
 const
   EmptyItemId = ItemId(module: -1'i32, item: -1'i32)
 
 proc search(c: var NavContext; tree: PackedTree): ItemId =
   # We use the linear representation here directly:
-  for i in 0..high(tree.nodes):
-    case tree.nodes[i].kind
+  for i in 0..<len(tree):
+    let i = NodePos(i)
+    case tree[i].kind
     of nkSym:
-      let item = tree.nodes[i].operand
-      if searchLocalSym(c, c.g.packed[c.thisModule].fromDisk.syms[item], tree.nodes[i].info):
+      let item = tree[i].soperand
+      if searchLocalSym(c, c.g.packed[c.thisModule].fromDisk.syms[item], tree[i].info):
         return ItemId(module: c.thisModule, item: item)
     of nkModuleRef:
-      if tree.nodes[i].info.line == c.trackPos.line and tree.nodes[i].info.file == c.trackPos.file:
-        let (n1, n2) = sons2(tree, NodePos i)
+      let (currentFile, currentLine, currentCol) = c.g.packed[c.thisModule].fromDisk.man.unpack(tree[i].info)
+      if currentLine == c.trackPos.line and currentFile == c.trackPos.file:
+        let (n1, n2) = sons2(tree, i)
         assert n1.kind == nkInt32Lit
         assert n2.kind == nkInt32Lit
-        let pId = PackedItemId(module: n1.litId, item: tree.nodes[n2.int].operand)
+        let pId = PackedItemId(module: n1.litId, item: tree[n2].soperand)
         let itemId = translateId(pId, c.g.packed, c.thisModule, c.g.config)
-        if searchForeignSym(c, itemId, tree.nodes[i].info):
+        if searchForeignSym(c, itemId, tree[i].info):
           return itemId
     else: discard
   return EmptyItemId
@@ -77,36 +84,38 @@ proc isDecl(tree: PackedTree; n: NodePos): bool =
   const declarativeNodes = procDefs + {nkMacroDef, nkTemplateDef,
     nkLetSection, nkVarSection, nkUsingStmt, nkConstSection, nkTypeSection,
     nkIdentDefs, nkEnumTy, nkVarTuple}
-  result = n.int >= 0 and tree[n.int].kind in declarativeNodes
+  result = n.int >= 0 and tree[n].kind in declarativeNodes
 
 proc usage(c: var NavContext; info: PackedLineInfo; isDecl: bool) =
+  let (fileId, line, col) = unpack(c.g.packed[c.thisModule].fromDisk.man, info)
   var m = ""
-  var file = c.g.packed[c.thisModule].fromDisk.strings[info.file]
+  var file = c.g.packed[c.thisModule].fromDisk.strings[fileId]
   if c.outputSep == ' ':
     file = os.extractFilename file
-  toLocation(m, file, info.line.int, info.col.int + ColOffset)
+  toLocation(m, file, line, col + ColOffset)
   if not c.alreadyEmitted.containsOrIncl(m):
     msgWriteln c.g.config, (if isDecl: "def" else: "usage") & c.outputSep & m
 
 proc list(c: var NavContext; tree: PackedTree; sym: ItemId) =
-  for i in 0..high(tree.nodes):
-    case tree.nodes[i].kind
+  for i in 0..<len(tree):
+    let i = NodePos(i)
+    case tree[i].kind
     of nkSym:
-      let item = tree.nodes[i].operand
+      let item = tree[i].soperand
       if sym.item == item and sym.module == c.thisModule:
-        usage(c, tree.nodes[i].info, isDecl(tree, parent(NodePos i)))
+        usage(c, tree[i].info, isDecl(tree, parent(i)))
     of nkModuleRef:
-      let (n1, n2) = sons2(tree, NodePos i)
-      assert n1.kind == nkInt32Lit
-      assert n2.kind == nkInt32Lit
-      let pId = PackedItemId(module: n1.litId, item: tree.nodes[n2.int].operand)
+      let (n1, n2) = sons2(tree, i)
+      assert n1.kind == nkNone
+      assert n2.kind == nkNone
+      let pId = PackedItemId(module: n1.litId, item: tree[n2].soperand)
       let itemId = translateId(pId, c.g.packed, c.thisModule, c.g.config)
       if itemId.item == sym.item and sym.module == itemId.module:
-        usage(c, tree.nodes[i].info, isDecl(tree, parent(NodePos i)))
+        usage(c, tree[i].info, isDecl(tree, parent(i)))
     else: discard
 
 proc searchForIncludeFile(g: ModuleGraph; fullPath: string): int =
-  for i in 0..high(g.packed):
+  for i in 0..<len(g.packed):
     for k in 1..high(g.packed[i].fromDisk.includes):
       # we start from 1 because the first "include" file is
       # the module's filename.
@@ -138,7 +147,7 @@ proc nav(g: ModuleGraph) =
   var c = NavContext(
     g: g,
     thisModule: int32 mid,
-    trackPos: PackedLineInfo(line: unpacked.line, col: unpacked.col, file: fileId),
+    trackPos: UnpackedLineInfo(line: unpacked.line.int, col: unpacked.col.int, file: fileId),
     outputSep: if isDefined(g.config, "nimIcNavigatorTests"): ' ' else: '\t'
   )
   var symId = search(c, g.packed[mid].fromDisk.topLevel)
@@ -149,7 +158,7 @@ proc nav(g: ModuleGraph) =
     localError(g.config, unpacked, "no symbol at this position")
     return
 
-  for i in 0..high(g.packed):
+  for i in 0..<len(g.packed):
     # case statement here to enforce exhaustive checks.
     case g.packed[i].status
     of undefined:
@@ -166,7 +175,7 @@ proc navUsages*(g: ModuleGraph) = nav(g)
 proc navDefusages*(g: ModuleGraph) = nav(g)
 
 proc writeRodFiles*(g: ModuleGraph) =
-  for i in 0..high(g.packed):
+  for i in 0..<len(g.packed):
     case g.packed[i].status
     of undefined, loading, stored, loaded:
       discard "nothing to do"