diff options
Diffstat (limited to 'compiler/ic/navigator.nim')
-rw-r--r-- | compiler/ic/navigator.nim | 73 |
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" |