# # # The Nim Compiler # (c) Copyright 2021 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## Supports the "nim check --ic:on --defusages:FILE,LINE,COL" ## IDE-like features. It uses the set of .rod files to accomplish ## its task. The set must cover a complete Nim project. import std/[sets, tables] 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: UnpackedLineInfo alreadyEmitted: HashSet[string] outputSep: char # for easier testing, use short filenames and spaces instead of tabs. 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 >= currentCol and col < currentCol+tokenLen: result = true else: result = false else: result = false proc searchLocalSym(c: var NavContext; s: PackedSym; info: PackedLineInfo): bool = result = s.name != LitId(0) and 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(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..= 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[fileId] if c.outputSep == ' ': file = os.extractFilename file 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..