[nimsuggest] fix def call on identifier 2 times on the line (#20228)
- apparently TLineInfo's implementation of `==` ignores the column. After I fixed the code to use exact TLineInfo comparison I fixed several other issues hidden by that issue. - Replaced `tuple[sym, info]` with `SymInfoPair`
This commit is contained in:
parent
04e4a5ec0e
commit
d4c0d35b32
5 changed files with 76 additions and 48 deletions
|
|
@ -53,6 +53,10 @@ type
|
||||||
concreteTypes*: seq[FullId]
|
concreteTypes*: seq[FullId]
|
||||||
inst*: PInstantiation
|
inst*: PInstantiation
|
||||||
|
|
||||||
|
SymInfoPair* = object
|
||||||
|
sym*: PSym
|
||||||
|
info*: TLineInfo
|
||||||
|
|
||||||
ModuleGraph* {.acyclic.} = ref object
|
ModuleGraph* {.acyclic.} = ref object
|
||||||
ifaces*: seq[Iface] ## indexed by int32 fileIdx
|
ifaces*: seq[Iface] ## indexed by int32 fileIdx
|
||||||
packed*: PackedModuleGraph
|
packed*: PackedModuleGraph
|
||||||
|
|
@ -83,7 +87,7 @@ type
|
||||||
doStopCompile*: proc(): bool {.closure.}
|
doStopCompile*: proc(): bool {.closure.}
|
||||||
usageSym*: PSym # for nimsuggest
|
usageSym*: PSym # for nimsuggest
|
||||||
owners*: seq[PSym]
|
owners*: seq[PSym]
|
||||||
suggestSymbols*: Table[FileIndex, seq[tuple[sym: PSym, info: TLineInfo]]]
|
suggestSymbols*: Table[FileIndex, seq[SymInfoPair]]
|
||||||
suggestErrors*: Table[FileIndex, seq[Suggest]]
|
suggestErrors*: Table[FileIndex, seq[Suggest]]
|
||||||
methods*: seq[tuple[methods: seq[PSym], dispatcher: PSym]] # needs serialization!
|
methods*: seq[tuple[methods: seq[PSym], dispatcher: PSym]] # needs serialization!
|
||||||
systemModule*: PSym
|
systemModule*: PSym
|
||||||
|
|
@ -374,12 +378,6 @@ template getPContext(): untyped =
|
||||||
|
|
||||||
when defined(nimsuggest):
|
when defined(nimsuggest):
|
||||||
template onUse*(info: TLineInfo; s: PSym) = discard
|
template onUse*(info: TLineInfo; s: PSym) = discard
|
||||||
|
|
||||||
template onDef*(info: TLineInfo; s: PSym) =
|
|
||||||
let c = getPContext()
|
|
||||||
if c.graph.config.suggestVersion == 3:
|
|
||||||
suggestSym(c.graph, info, s, c.graph.usageSym)
|
|
||||||
|
|
||||||
template onDefResolveForward*(info: TLineInfo; s: PSym) = discard
|
template onDefResolveForward*(info: TLineInfo; s: PSym) = discard
|
||||||
else:
|
else:
|
||||||
template onUse*(info: TLineInfo; s: PSym) = discard
|
template onUse*(info: TLineInfo; s: PSym) = discard
|
||||||
|
|
@ -442,7 +440,7 @@ proc initModuleGraphFields(result: ModuleGraph) =
|
||||||
result.importStack = @[]
|
result.importStack = @[]
|
||||||
result.inclToMod = initTable[FileIndex, FileIndex]()
|
result.inclToMod = initTable[FileIndex, FileIndex]()
|
||||||
result.owners = @[]
|
result.owners = @[]
|
||||||
result.suggestSymbols = initTable[FileIndex, seq[tuple[sym: PSym, info: TLineInfo]]]()
|
result.suggestSymbols = initTable[FileIndex, seq[SymInfoPair]]()
|
||||||
result.suggestErrors = initTable[FileIndex, seq[Suggest]]()
|
result.suggestErrors = initTable[FileIndex, seq[Suggest]]()
|
||||||
result.methods = @[]
|
result.methods = @[]
|
||||||
initStrTable(result.compilerprocs)
|
initStrTable(result.compilerprocs)
|
||||||
|
|
@ -641,7 +639,13 @@ func belongsToStdlib*(graph: ModuleGraph, sym: PSym): bool =
|
||||||
## Check if symbol belongs to the 'stdlib' package.
|
## Check if symbol belongs to the 'stdlib' package.
|
||||||
sym.getPackageSymbol.getPackageId == graph.systemModule.getPackageId
|
sym.getPackageSymbol.getPackageId == graph.systemModule.getPackageId
|
||||||
|
|
||||||
iterator suggestSymbolsIter*(g: ModuleGraph): tuple[sym: PSym, info: TLineInfo] =
|
proc `==`*(a, b: SymInfoPair): bool =
|
||||||
|
result = a.sym == b.sym and a.info.exactEquals(b.info)
|
||||||
|
|
||||||
|
proc fileSymbols*(graph: ModuleGraph, fileIdx: FileIndex): seq[SymInfoPair] =
|
||||||
|
result = graph.suggestSymbols.getOrDefault(fileIdx, @[]).deduplicate
|
||||||
|
|
||||||
|
iterator suggestSymbolsIter*(g: ModuleGraph): SymInfoPair =
|
||||||
for xs in g.suggestSymbols.values:
|
for xs in g.suggestSymbols.values:
|
||||||
for x in xs.deduplicate:
|
for x in xs.deduplicate:
|
||||||
yield x
|
yield x
|
||||||
|
|
|
||||||
|
|
@ -503,7 +503,7 @@ proc suggestSym*(g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym; i
|
||||||
## misnamed: should be 'symDeclared'
|
## misnamed: should be 'symDeclared'
|
||||||
let conf = g.config
|
let conf = g.config
|
||||||
when defined(nimsuggest):
|
when defined(nimsuggest):
|
||||||
g.suggestSymbols.mgetOrPut(info.fileIndex, @[]).add (s, info)
|
g.suggestSymbols.mgetOrPut(info.fileIndex, @[]).add SymInfoPair(sym: s, info: info)
|
||||||
|
|
||||||
if conf.suggestVersion == 0:
|
if conf.suggestVersion == 0:
|
||||||
if s.allUsages.len == 0:
|
if s.allUsages.len == 0:
|
||||||
|
|
@ -699,3 +699,16 @@ proc suggestSentinel*(c: PContext) =
|
||||||
|
|
||||||
dec(c.compilesContextId)
|
dec(c.compilesContextId)
|
||||||
produceOutput(outputs, c.config)
|
produceOutput(outputs, c.config)
|
||||||
|
|
||||||
|
when defined(nimsuggest):
|
||||||
|
proc onDef(graph: ModuleGraph, s: PSym, info: TLineInfo) =
|
||||||
|
if graph.config.suggestVersion == 3 and info.exactEquals(s.info):
|
||||||
|
suggestSym(graph, info, s, graph.usageSym)
|
||||||
|
|
||||||
|
template getPContext(): untyped =
|
||||||
|
when c is PContext: c
|
||||||
|
else: c.c
|
||||||
|
|
||||||
|
template onDef*(info: TLineInfo; s: PSym) =
|
||||||
|
let c = getPContext()
|
||||||
|
onDef(c.graph, s, info)
|
||||||
|
|
|
||||||
|
|
@ -711,17 +711,16 @@ proc recompilePartially(graph: ModuleGraph, projectFileIdx = InvalidFileIdx) =
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
myLog fmt "Failed clean recompilation:\n {e.msg} \n\n {e.getStackTrace()}"
|
myLog fmt "Failed clean recompilation:\n {e.msg} \n\n {e.getStackTrace()}"
|
||||||
|
|
||||||
proc fileSymbols(graph: ModuleGraph, fileIdx: FileIndex): seq[tuple[sym: PSym, info: TLineInfo]] =
|
|
||||||
result = graph.suggestSymbols.getOrDefault(fileIdx, @[]).deduplicate
|
|
||||||
|
|
||||||
proc findSymData(graph: ModuleGraph, file: AbsoluteFile; line, col: int):
|
proc findSymData(graph: ModuleGraph, file: AbsoluteFile; line, col: int):
|
||||||
tuple[sym: PSym, info: TLineInfo] =
|
ref SymInfoPair =
|
||||||
let
|
let
|
||||||
fileIdx = fileInfoIdx(graph.config, file)
|
fileIdx = fileInfoIdx(graph.config, file)
|
||||||
trackPos = newLineInfo(fileIdx, line, col)
|
trackPos = newLineInfo(fileIdx, line, col)
|
||||||
for (sym, info) in graph.fileSymbols(fileIdx):
|
for s in graph.fileSymbols(fileIdx):
|
||||||
if isTracked(info, trackPos, sym.name.s.len):
|
if isTracked(s.info, trackPos, s.sym.name.s.len):
|
||||||
return (sym, info)
|
new(result)
|
||||||
|
result[] = s
|
||||||
|
break
|
||||||
|
|
||||||
proc markDirtyIfNeeded(graph: ModuleGraph, file: string, originalFileIdx: FileIndex) =
|
proc markDirtyIfNeeded(graph: ModuleGraph, file: string, originalFileIdx: FileIndex) =
|
||||||
let sha = $sha1.secureHashFile(file)
|
let sha = $sha1.secureHashFile(file)
|
||||||
|
|
@ -735,7 +734,7 @@ proc markDirtyIfNeeded(graph: ModuleGraph, file: string, originalFileIdx: FileIn
|
||||||
proc suggestResult(graph: ModuleGraph, sym: PSym, info: TLineInfo, defaultSection = ideNone) =
|
proc suggestResult(graph: ModuleGraph, sym: PSym, info: TLineInfo, defaultSection = ideNone) =
|
||||||
let section = if defaultSection != ideNone:
|
let section = if defaultSection != ideNone:
|
||||||
defaultSection
|
defaultSection
|
||||||
elif sym.info == info:
|
elif sym.info.exactEquals(info):
|
||||||
ideDef
|
ideDef
|
||||||
else:
|
else:
|
||||||
ideUse
|
ideUse
|
||||||
|
|
@ -800,31 +799,31 @@ proc executeNoHooksV3(cmd: IdeCmd, file: AbsoluteFile, dirtyfile: AbsoluteFile,
|
||||||
|
|
||||||
case cmd
|
case cmd
|
||||||
of ideDef:
|
of ideDef:
|
||||||
let (sym, info) = graph.findSymData(file, line, col)
|
let s = graph.findSymData(file, line, col)
|
||||||
if sym != nil:
|
if not s.isNil:
|
||||||
graph.suggestResult(sym, sym.info)
|
graph.suggestResult(s.sym, s.sym.info)
|
||||||
of ideType:
|
of ideType:
|
||||||
let (sym, _) = graph.findSymData(file, line, col)
|
let s = graph.findSymData(file, line, col)
|
||||||
if sym != nil:
|
if not s.isNil:
|
||||||
let typeSym = sym.typ.sym
|
let typeSym = s.sym.typ.sym
|
||||||
if typeSym != nil:
|
if typeSym != nil:
|
||||||
graph.suggestResult(typeSym, typeSym.info, ideType)
|
graph.suggestResult(typeSym, typeSym.info, ideType)
|
||||||
elif sym.typ.len != 0:
|
elif s.sym.typ.len != 0:
|
||||||
let genericType = sym.typ[0].sym
|
let genericType = s.sym.typ[0].sym
|
||||||
graph.suggestResult(genericType, genericType.info, ideType)
|
graph.suggestResult(genericType, genericType.info, ideType)
|
||||||
of ideUse, ideDus:
|
of ideUse, ideDus:
|
||||||
let symbol = graph.findSymData(file, line, col).sym
|
let symbol = graph.findSymData(file, line, col)
|
||||||
if symbol != nil:
|
if not symbol.isNil:
|
||||||
for (sym, info) in graph.suggestSymbolsIter:
|
for s in graph.suggestSymbolsIter:
|
||||||
if sym == symbol:
|
if s.sym == symbol.sym:
|
||||||
graph.suggestResult(sym, info)
|
graph.suggestResult(s.sym, s.info)
|
||||||
of ideHighlight:
|
of ideHighlight:
|
||||||
let sym = graph.findSymData(file, line, col).sym
|
let sym = graph.findSymData(file, line, col)
|
||||||
if sym != nil:
|
if not sym.isNil:
|
||||||
let usages = graph.fileSymbols(fileIndex).filterIt(it.sym == sym)
|
let usages = graph.fileSymbols(fileIndex).filterIt(it.sym == sym.sym)
|
||||||
myLog fmt "Found {usages.len} usages in {file.string}"
|
myLog fmt "Found {usages.len} usages in {file.string}"
|
||||||
for (sym, info) in usages:
|
for s in usages:
|
||||||
graph.suggestResult(sym, info)
|
graph.suggestResult(s.sym, s.info)
|
||||||
of ideRecompile:
|
of ideRecompile:
|
||||||
graph.recompileFullProject()
|
graph.recompileFullProject()
|
||||||
of ideChanged:
|
of ideChanged:
|
||||||
|
|
@ -837,14 +836,12 @@ proc executeNoHooksV3(cmd: IdeCmd, file: AbsoluteFile, dirtyfile: AbsoluteFile,
|
||||||
let
|
let
|
||||||
module = graph.getModule fileIndex
|
module = graph.getModule fileIndex
|
||||||
symbols = graph.fileSymbols(fileIndex)
|
symbols = graph.fileSymbols(fileIndex)
|
||||||
.filterIt(it.sym.info == it.info and
|
.filterIt(it.sym.info.exactEquals(it.info) and
|
||||||
(it.sym.owner == module or
|
(it.sym.owner == module or
|
||||||
it.sym.kind in searchableSymKinds))
|
it.sym.kind in searchableSymKinds))
|
||||||
for (sym, _) in symbols:
|
|
||||||
suggestResult(
|
for s in symbols:
|
||||||
conf,
|
graph.suggestResult(s.sym, s.info, ideOutline)
|
||||||
symToSuggest(graph, sym, false,
|
|
||||||
ideOutline, sym.info, 100, PrefixMatch.None, false, 0))
|
|
||||||
of ideChk:
|
of ideChk:
|
||||||
myLog fmt "Reporting errors for {graph.suggestErrors.len} file(s)"
|
myLog fmt "Reporting errors for {graph.suggestErrors.len} file(s)"
|
||||||
for sug in graph.suggestErrorsIter:
|
for sug in graph.suggestErrorsIter:
|
||||||
|
|
@ -856,13 +853,12 @@ proc executeNoHooksV3(cmd: IdeCmd, file: AbsoluteFile, dirtyfile: AbsoluteFile,
|
||||||
suggestResult(graph.config, error)
|
suggestResult(graph.config, error)
|
||||||
of ideGlobalSymbols:
|
of ideGlobalSymbols:
|
||||||
var counter = 0
|
var counter = 0
|
||||||
for (sym, info) in graph.suggestSymbolsIter:
|
for s in graph.suggestSymbolsIter:
|
||||||
if sfGlobal in sym.flags or sym.kind in searchableSymKinds:
|
if (sfGlobal in s.sym.flags or s.sym.kind in searchableSymKinds) and
|
||||||
if contains(sym.name.s, file.string):
|
s.sym.info == s.info:
|
||||||
|
if contains(s.sym.name.s, file.string):
|
||||||
inc counter
|
inc counter
|
||||||
suggestResult(conf,
|
graph.suggestResult(s.sym, s.info)
|
||||||
symToSuggest(graph, sym, isLocal=false,
|
|
||||||
ideDef, info, 100, PrefixMatch.None, false, 0))
|
|
||||||
# stop after first 100 results
|
# stop after first 100 results
|
||||||
if counter > 100:
|
if counter > 100:
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ type
|
||||||
proc test(f: Foo) =
|
proc test(f: Foo) =
|
||||||
echo f.ba#[!]#r
|
echo f.ba#[!]#r
|
||||||
|
|
||||||
|
#[!]#
|
||||||
|
|
||||||
discard """
|
discard """
|
||||||
$nimsuggest --v3 --tester $file
|
$nimsuggest --v3 --tester $file
|
||||||
>use $1
|
>use $1
|
||||||
|
|
@ -22,4 +24,8 @@ outline skProc tv3.test proc (f: Foo){.gcsafe, locks: 0.} $file 7 5 "" 100
|
||||||
sug skField bar string $file 5 4 "" 100 Prefix
|
sug skField bar string $file 5 4 "" 100 Prefix
|
||||||
>globalSymbols test
|
>globalSymbols test
|
||||||
def skProc tv3.test proc (f: Foo){.gcsafe, locks: 0.} $file 7 5 "" 100
|
def skProc tv3.test proc (f: Foo){.gcsafe, locks: 0.} $file 7 5 "" 100
|
||||||
|
>globalSymbols Foo
|
||||||
|
def skType tv3.Foo Foo $file 4 2 "" 100
|
||||||
|
>def $2
|
||||||
|
>use $2
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
9
nimsuggest/tests/tv3_definition.nim
Normal file
9
nimsuggest/tests/tv3_definition.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
let foo = 30
|
||||||
|
let bar = foo + fo#[!]#o + foo
|
||||||
|
|
||||||
|
discard """
|
||||||
|
$nimsuggest --v3 --tester $file
|
||||||
|
>def $1
|
||||||
|
def skLet tv3_definition.foo int $file 2 4 "" 100
|
||||||
|
"""
|
||||||
Loading…
Add table
Add a link
Reference in a new issue