mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-22 15:25:22 +00:00
+ added nimsuggest support for exception inlay hints (#23202)
This adds nimsuggest support for displaying inlay hints for exceptions. An inlay hint is displayed around function calls, that can raise an exception, which isn't handled in the current subroutine (in other words, exceptions that can propagate back to the caller). On mouse hover on top of the hint, a list of exceptions that could propagate is shown. The changes, required to support this are already commited to nimlangserver and the VS code extension. The extension and the server allow configuration for whether these new exception hints are enabled (they can be enabled or disabled independently from the type hints), as well as the inlay strings that are inserted before and after the name of the function, around the function call. Potentially, one of these strings can be empty, for example, the user can choose to add an inlay hint only before the name of the function, or only after the name of the function.
This commit is contained in:
@@ -11,9 +11,9 @@
|
||||
## represents a complete Nim project. Single modules can either be kept in RAM
|
||||
## or stored in a rod-file.
|
||||
|
||||
import std/[intsets, tables, hashes, strtabs]
|
||||
import std/[intsets, tables, hashes, strtabs, algorithm]
|
||||
import ../dist/checksums/src/checksums/md5
|
||||
import ast, astalgo, options, lineinfos,idents, btrees, ropes, msgs, pathutils, packages
|
||||
import ast, astalgo, options, lineinfos,idents, btrees, ropes, msgs, pathutils, packages, suggestsymdb
|
||||
import ic / [packed_ast, ic]
|
||||
|
||||
|
||||
@@ -55,11 +55,6 @@ type
|
||||
concreteTypes*: seq[FullId]
|
||||
inst*: PInstantiation
|
||||
|
||||
SymInfoPair* = object
|
||||
sym*: PSym
|
||||
info*: TLineInfo
|
||||
isDecl*: bool
|
||||
|
||||
PipelinePass* = enum
|
||||
NonePass
|
||||
SemPass
|
||||
@@ -108,7 +103,7 @@ type
|
||||
doStopCompile*: proc(): bool {.closure.}
|
||||
usageSym*: PSym # for nimsuggest
|
||||
owners*: seq[PSym]
|
||||
suggestSymbols*: Table[FileIndex, seq[SymInfoPair]]
|
||||
suggestSymbols*: SuggestSymbolDatabase
|
||||
suggestErrors*: Table[FileIndex, seq[Suggest]]
|
||||
methods*: seq[tuple[methods: seq[PSym], dispatcher: PSym]] # needs serialization!
|
||||
bucketTable*: CountTable[ItemId]
|
||||
@@ -506,7 +501,7 @@ proc initModuleGraphFields(result: ModuleGraph) =
|
||||
result.importStack = @[]
|
||||
result.inclToMod = initTable[FileIndex, FileIndex]()
|
||||
result.owners = @[]
|
||||
result.suggestSymbols = initTable[FileIndex, seq[SymInfoPair]]()
|
||||
result.suggestSymbols = initTable[FileIndex, SuggestFileSymbolDatabase]()
|
||||
result.suggestErrors = initTable[FileIndex, seq[Suggest]]()
|
||||
result.methods = @[]
|
||||
result.compilerprocs = initStrTable()
|
||||
@@ -712,16 +707,14 @@ func belongsToStdlib*(graph: ModuleGraph, sym: PSym): bool =
|
||||
## Check if symbol belongs to the 'stdlib' package.
|
||||
sym.getPackageSymbol.getPackageId == graph.systemModule.getPackageId
|
||||
|
||||
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, @[])
|
||||
proc fileSymbols*(graph: ModuleGraph, fileIdx: FileIndex): SuggestFileSymbolDatabase =
|
||||
result = graph.suggestSymbols.getOrDefault(fileIdx, newSuggestFileSymbolDatabase(fileIdx, optIdeExceptionInlayHints in graph.config.globalOptions))
|
||||
doAssert(result.fileIndex == fileIdx)
|
||||
|
||||
iterator suggestSymbolsIter*(g: ModuleGraph): SymInfoPair =
|
||||
for xs in g.suggestSymbols.values:
|
||||
for x in xs:
|
||||
yield x
|
||||
for i in xs.lineInfo.low..xs.lineInfo.high:
|
||||
yield xs.getSymInfoPair(i)
|
||||
|
||||
iterator suggestErrorsIter*(g: ModuleGraph): Suggest =
|
||||
for xs in g.suggestErrors.values:
|
||||
|
||||
@@ -86,6 +86,7 @@ type # please make sure we have under 32 options
|
||||
# also: generate header file
|
||||
optIdeDebug # idetools: debug mode
|
||||
optIdeTerse # idetools: use terse descriptions
|
||||
optIdeExceptionInlayHints
|
||||
optExcessiveStackTrace # fully qualified module filenames
|
||||
optShowAllMismatches # show all overloading resolution candidates
|
||||
optWholeProject # for 'doc': output any dependency
|
||||
@@ -298,6 +299,7 @@ type
|
||||
SuggestInlayHintKind* = enum
|
||||
sihkType = "Type",
|
||||
sihkParameter = "Parameter"
|
||||
sihkException = "Exception"
|
||||
|
||||
SuggestInlayHint* = ref object
|
||||
kind*: SuggestInlayHintKind
|
||||
|
||||
@@ -11,9 +11,9 @@ import
|
||||
ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
||||
wordrecg, options, guards, lineinfos, semfold, semdata,
|
||||
modulegraphs, varpartitions, typeallowed, nilcheck, errorhandling,
|
||||
semstrictfuncs
|
||||
semstrictfuncs, suggestsymdb
|
||||
|
||||
import std/[tables, intsets, strutils]
|
||||
import std/[tables, intsets, strutils, sequtils]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
@@ -66,8 +66,12 @@ discard """
|
||||
"""
|
||||
|
||||
type
|
||||
CaughtExceptionsStack = object
|
||||
nodes: seq[seq[PType]]
|
||||
TEffects = object
|
||||
exc: PNode # stack of exceptions
|
||||
when defined(nimsuggest):
|
||||
caughtExceptions: CaughtExceptionsStack
|
||||
tags: PNode # list of tags
|
||||
forbids: PNode # list of tags
|
||||
bottom, inTryStmt, inExceptOrFinallyStmt, leftPartOfAsgn, inIfStmt, currentBlock: int
|
||||
@@ -411,7 +415,7 @@ proc throws(tracked, n, orig: PNode) =
|
||||
else:
|
||||
tracked.add n
|
||||
|
||||
proc getEbase(g: ModuleGraph; info: TLineInfo): PType =
|
||||
proc getEbase*(g: ModuleGraph; info: TLineInfo): PType =
|
||||
result = g.sysTypeFromName(info, "Exception")
|
||||
|
||||
proc excType(g: ModuleGraph; n: PNode): PType =
|
||||
@@ -492,6 +496,18 @@ proc catchesAll(tracked: PEffects) =
|
||||
if tracked.exc.len > 0:
|
||||
setLen(tracked.exc.sons, tracked.bottom)
|
||||
|
||||
proc push(s: var CaughtExceptionsStack) =
|
||||
s.nodes.add(@[])
|
||||
|
||||
proc pop(s: var CaughtExceptionsStack) =
|
||||
s.nodes.del(high(s.nodes))
|
||||
|
||||
proc addCatch(s: var CaughtExceptionsStack, e: PType) =
|
||||
s.nodes[high(s.nodes)].add(e)
|
||||
|
||||
proc addCatchAll(s: var CaughtExceptionsStack) =
|
||||
s.nodes[high(s.nodes)].add(nil)
|
||||
|
||||
proc track(tracked: PEffects, n: PNode)
|
||||
proc trackTryStmt(tracked: PEffects, n: PNode) =
|
||||
let oldBottom = tracked.bottom
|
||||
@@ -500,12 +516,33 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
|
||||
let oldState = tracked.init.len
|
||||
var inter: TIntersection = @[]
|
||||
|
||||
when defined(nimsuggest):
|
||||
tracked.caughtExceptions.push
|
||||
for i in 1..<n.len:
|
||||
let b = n[i]
|
||||
if b.kind == nkExceptBranch:
|
||||
if b.len == 1:
|
||||
tracked.caughtExceptions.addCatchAll
|
||||
else:
|
||||
for j in 0..<b.len - 1:
|
||||
if b[j].isInfixAs():
|
||||
assert(b[j][1].kind == nkType)
|
||||
tracked.caughtExceptions.addCatch(b[j][1].typ)
|
||||
else:
|
||||
assert(b[j].kind == nkType)
|
||||
tracked.caughtExceptions.addCatch(b[j].typ)
|
||||
else:
|
||||
assert b.kind == nkFinally
|
||||
|
||||
inc tracked.inTryStmt
|
||||
track(tracked, n[0])
|
||||
dec tracked.inTryStmt
|
||||
for i in oldState..<tracked.init.len:
|
||||
addToIntersection(inter, tracked.init[i], bsNone)
|
||||
|
||||
when defined(nimsuggest):
|
||||
tracked.caughtExceptions.pop
|
||||
|
||||
var branches = 1
|
||||
var hasFinally = false
|
||||
inc tracked.inExceptOrFinallyStmt
|
||||
@@ -917,6 +954,19 @@ proc checkForSink(tracked: PEffects; n: PNode) =
|
||||
if tracked.inIfStmt == 0 and optSinkInference in tracked.config.options:
|
||||
checkForSink(tracked.config, tracked.c.idgen, tracked.owner, n)
|
||||
|
||||
proc markCaughtExceptions(tracked: PEffects; g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym) =
|
||||
when defined(nimsuggest):
|
||||
proc internalMarkCaughtExceptions(tracked: PEffects; q: var SuggestFileSymbolDatabase; info: TLineInfo) =
|
||||
var si = q.findSymInfoIndex(info)
|
||||
if si != -1:
|
||||
q.caughtExceptionsSet[si] = true
|
||||
for w1 in tracked.caughtExceptions.nodes:
|
||||
for w2 in w1:
|
||||
q.caughtExceptions[si].add(w2)
|
||||
|
||||
if optIdeExceptionInlayHints in tracked.config.globalOptions:
|
||||
internalMarkCaughtExceptions(tracked, g.suggestSymbols.mgetOrPut(info.fileIndex, newSuggestFileSymbolDatabase(info.fileIndex, true)), info)
|
||||
|
||||
proc trackCall(tracked: PEffects; n: PNode) =
|
||||
template gcsafeAndSideeffectCheck() =
|
||||
if notGcSafe(op) and not importedFromC(a):
|
||||
@@ -937,6 +987,13 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
createTypeBoundOps(tracked, n.typ, n.info)
|
||||
|
||||
when defined(nimsuggest):
|
||||
var actualLoc = a.info
|
||||
if n.kind == nkHiddenCallConv:
|
||||
actualLoc = n.info
|
||||
if a.kind == nkSym:
|
||||
markCaughtExceptions(tracked, tracked.graph, actualLoc, a.sym, tracked.graph.usageSym)
|
||||
|
||||
let notConstExpr = getConstExpr(tracked.ownerModule, n, tracked.c.idgen, tracked.graph) == nil
|
||||
if notConstExpr:
|
||||
if a.kind == nkCast and a[1].typ.kind == tyProc:
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
# included from sigmatch.nim
|
||||
|
||||
import prefixmatches
|
||||
import prefixmatches, suggestsymdb
|
||||
from wordrecg import wDeprecated, wError, wAddr, wYield
|
||||
|
||||
import std/[algorithm, sets, parseutils, tables]
|
||||
@@ -114,6 +114,10 @@ proc getTokenLenFromSource(conf: ConfigRef; ident: string; info: TLineInfo; skip
|
||||
result = skipUntil(line, '`', column)
|
||||
if cmpIgnoreStyle(line[column..column + result - 1], ident) != 0:
|
||||
result = 0
|
||||
elif column >= 0 and line[column] == '`' and isOpeningBacktick(column):
|
||||
result = skipUntil(line, '`', column + 1) + 2
|
||||
if cmpIgnoreStyle(line[column + 1..column + result - 2], ident) != 0:
|
||||
result = 0
|
||||
elif ident[0] in linter.Letters and ident[^1] != '=':
|
||||
result = identLen(line, column)
|
||||
if cmpIgnoreStyle(line[column..column + result - 1], ident[0..min(result-1,len(ident)-1)]) != 0:
|
||||
@@ -265,7 +269,7 @@ proc `$`*(suggest: Suggest): string =
|
||||
result.add(sep)
|
||||
result.add($suggest.endCol)
|
||||
|
||||
proc suggestToSuggestInlayHint*(sug: Suggest): SuggestInlayHint =
|
||||
proc suggestToSuggestInlayTypeHint*(sug: Suggest): SuggestInlayHint =
|
||||
SuggestInlayHint(
|
||||
kind: sihkType,
|
||||
line: sug.line,
|
||||
@@ -277,6 +281,30 @@ proc suggestToSuggestInlayHint*(sug: Suggest): SuggestInlayHint =
|
||||
tooltip: ""
|
||||
)
|
||||
|
||||
proc suggestToSuggestInlayExceptionHintLeft*(sug: Suggest, propagatedExceptions: seq[PType]): SuggestInlayHint =
|
||||
SuggestInlayHint(
|
||||
kind: sihkException,
|
||||
line: sug.line,
|
||||
column: sug.column,
|
||||
label: "try ",
|
||||
paddingLeft: false,
|
||||
paddingRight: false,
|
||||
allowInsert: false,
|
||||
tooltip: "propagated exceptions: " & $propagatedExceptions
|
||||
)
|
||||
|
||||
proc suggestToSuggestInlayExceptionHintRight*(sug: Suggest, propagatedExceptions: seq[PType]): SuggestInlayHint =
|
||||
SuggestInlayHint(
|
||||
kind: sihkException,
|
||||
line: sug.line,
|
||||
column: sug.column + sug.tokenLen,
|
||||
label: "!",
|
||||
paddingLeft: false,
|
||||
paddingRight: false,
|
||||
allowInsert: false,
|
||||
tooltip: "propagated exceptions: " & $propagatedExceptions
|
||||
)
|
||||
|
||||
proc suggestResult*(conf: ConfigRef; s: Suggest) =
|
||||
if not isNil(conf.suggestionResultHook):
|
||||
conf.suggestionResultHook(s)
|
||||
@@ -534,6 +562,16 @@ proc isTracked*(current, trackPos: TLineInfo, tokenLen: int): bool =
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc isTracked*(current, trackPos: TinyLineInfo, tokenLen: int): bool =
|
||||
if current.line==trackPos.line:
|
||||
let col = trackPos.col
|
||||
if col >= current.col and col <= current.col+tokenLen-1:
|
||||
result = true
|
||||
else:
|
||||
result = false
|
||||
else:
|
||||
result = false
|
||||
|
||||
when defined(nimsuggest):
|
||||
# Since TLineInfo defined a == operator that doesn't include the column,
|
||||
# we map TLineInfo to a unique int here for this lookup table:
|
||||
@@ -584,7 +622,7 @@ proc suggestSym*(g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym; i
|
||||
## misnamed: should be 'symDeclared'
|
||||
let conf = g.config
|
||||
when defined(nimsuggest):
|
||||
g.suggestSymbols.mgetOrPut(info.fileIndex, @[]).add SymInfoPair(sym: s, info: info, isDecl: isDecl)
|
||||
g.suggestSymbols.add SymInfoPair(sym: s, info: info, isDecl: isDecl), optIdeExceptionInlayHints in g.config.globalOptions
|
||||
|
||||
if conf.suggestVersion == 0:
|
||||
if s.allUsages.len == 0:
|
||||
|
||||
212
compiler/suggestsymdb.nim
Normal file
212
compiler/suggestsymdb.nim
Normal file
@@ -0,0 +1,212 @@
|
||||
import std/[intsets, tables, algorithm, assertions]
|
||||
import ast, lineinfos, msgs
|
||||
|
||||
type
|
||||
PackedBoolArray* = object
|
||||
s: IntSet
|
||||
len: int
|
||||
|
||||
TinyLineInfo* = object
|
||||
line*: uint16
|
||||
col*: int16
|
||||
|
||||
SymInfoPair* = object
|
||||
sym*: PSym
|
||||
info*: TLineInfo
|
||||
caughtExceptions*: seq[PType]
|
||||
caughtExceptionsSet*: bool
|
||||
isDecl*: bool
|
||||
|
||||
SuggestFileSymbolDatabase* = object
|
||||
lineInfo*: seq[TinyLineInfo]
|
||||
sym*: seq[PSym]
|
||||
caughtExceptions*: seq[seq[PType]]
|
||||
caughtExceptionsSet*: PackedBoolArray
|
||||
isDecl*: PackedBoolArray
|
||||
fileIndex*: FileIndex
|
||||
trackCaughtExceptions*: bool
|
||||
isSorted*: bool
|
||||
|
||||
SuggestSymbolDatabase* = Table[FileIndex, SuggestFileSymbolDatabase]
|
||||
|
||||
|
||||
func newPackedBoolArray*(): PackedBoolArray =
|
||||
PackedBoolArray(
|
||||
s: initIntSet(),
|
||||
len: 0
|
||||
)
|
||||
|
||||
func low*(s: PackedBoolArray): int =
|
||||
0
|
||||
|
||||
func high*(s: PackedBoolArray): int =
|
||||
s.len - 1
|
||||
|
||||
func `[]`*(s: PackedBoolArray; idx: int): bool =
|
||||
s.s.contains(idx)
|
||||
|
||||
proc `[]=`*(s: var PackedBoolArray; idx: int; v: bool) =
|
||||
if v:
|
||||
s.s.incl(idx)
|
||||
else:
|
||||
s.s.excl(idx)
|
||||
|
||||
proc add*(s: var PackedBoolArray; v: bool) =
|
||||
inc(s.len)
|
||||
if v:
|
||||
s.s.incl(s.len - 1)
|
||||
|
||||
proc reverse*(s: var PackedBoolArray) =
|
||||
var
|
||||
reversedSet = initIntSet()
|
||||
for i in 0..s.high:
|
||||
if s.s.contains(i):
|
||||
reversedSet.incl(s.high - i)
|
||||
s.s = reversedSet
|
||||
|
||||
proc getSymInfoPair*(s: SuggestFileSymbolDatabase; idx: int): SymInfoPair =
|
||||
SymInfoPair(
|
||||
sym: s.sym[idx],
|
||||
info: TLineInfo(
|
||||
line: s.lineInfo[idx].line,
|
||||
col: s.lineInfo[idx].col,
|
||||
fileIndex: s.fileIndex
|
||||
),
|
||||
caughtExceptions:
|
||||
if s.trackCaughtExceptions:
|
||||
s.caughtExceptions[idx]
|
||||
else:
|
||||
@[],
|
||||
caughtExceptionsSet:
|
||||
if s.trackCaughtExceptions:
|
||||
s.caughtExceptionsSet[idx]
|
||||
else:
|
||||
false,
|
||||
isDecl: s.isDecl[idx]
|
||||
)
|
||||
|
||||
proc reverse*(s: var SuggestFileSymbolDatabase) =
|
||||
s.lineInfo.reverse()
|
||||
s.sym.reverse()
|
||||
s.caughtExceptions.reverse()
|
||||
s.caughtExceptionsSet.reverse()
|
||||
s.isDecl.reverse()
|
||||
|
||||
proc newSuggestFileSymbolDatabase*(aFileIndex: FileIndex; aTrackCaughtExceptions: bool): SuggestFileSymbolDatabase =
|
||||
SuggestFileSymbolDatabase(
|
||||
lineInfo: @[],
|
||||
sym: @[],
|
||||
caughtExceptions: @[],
|
||||
caughtExceptionsSet: newPackedBoolArray(),
|
||||
isDecl: newPackedBoolArray(),
|
||||
fileIndex: aFileIndex,
|
||||
trackCaughtExceptions: aTrackCaughtExceptions,
|
||||
isSorted: true
|
||||
)
|
||||
|
||||
proc exactEquals*(a, b: TinyLineInfo): bool =
|
||||
result = a.line == b.line and a.col == b.col
|
||||
|
||||
proc `==`*(a, b: SymInfoPair): bool =
|
||||
result = a.sym == b.sym and a.info.exactEquals(b.info)
|
||||
|
||||
func cmp*(a: TinyLineInfo; b: TinyLineInfo): int =
|
||||
result = cmp(a.line, b.line)
|
||||
if result == 0:
|
||||
result = cmp(a.col, b.col)
|
||||
|
||||
func compare*(s: var SuggestFileSymbolDatabase; i, j: int): int =
|
||||
result = cmp(s.lineInfo[i], s.lineInfo[j])
|
||||
if result == 0:
|
||||
result = cmp(s.isDecl[i], s.isDecl[j])
|
||||
|
||||
proc exchange(s: var SuggestFileSymbolDatabase; i, j: int) =
|
||||
if i == j:
|
||||
return
|
||||
var tmp1 = s.lineInfo[i]
|
||||
s.lineInfo[i] = s.lineInfo[j]
|
||||
s.lineInfo[j] = tmp1
|
||||
if s.trackCaughtExceptions:
|
||||
var tmp2 = s.caughtExceptions[i]
|
||||
s.caughtExceptions[i] = s.caughtExceptions[j]
|
||||
s.caughtExceptions[j] = tmp2
|
||||
var tmp3 = s.caughtExceptionsSet[i]
|
||||
s.caughtExceptionsSet[i] = s.caughtExceptionsSet[j]
|
||||
s.caughtExceptionsSet[j] = tmp3
|
||||
var tmp4 = s.isDecl[i]
|
||||
s.isDecl[i] = s.isDecl[j]
|
||||
s.isDecl[j] = tmp4
|
||||
var tmp5 = s.sym[i]
|
||||
s.sym[i] = s.sym[j]
|
||||
s.sym[j] = tmp5
|
||||
|
||||
proc quickSort(s: var SuggestFileSymbolDatabase; ll, rr: int) =
|
||||
var
|
||||
i, j, pivotIdx: int
|
||||
l = ll
|
||||
r = rr
|
||||
while true:
|
||||
i = l
|
||||
j = r
|
||||
pivotIdx = l + ((r - l) shr 1)
|
||||
while true:
|
||||
while (i < pivotIdx) and (s.compare(pivotIdx, i) > 0):
|
||||
inc i
|
||||
while (j > pivotIdx) and (s.compare(pivotIdx, j) < 0):
|
||||
dec j
|
||||
if i < j:
|
||||
s.exchange(i, j)
|
||||
if pivotIdx == i:
|
||||
pivotIdx = j
|
||||
inc i
|
||||
elif pivotIdx == j:
|
||||
pivotIdx = i
|
||||
dec j
|
||||
else:
|
||||
inc i
|
||||
dec j
|
||||
else:
|
||||
break
|
||||
if (pivotIdx - l) < (r - pivotIdx):
|
||||
if (l + 1) < pivotIdx:
|
||||
s.quickSort(l, pivotIdx - 1)
|
||||
l = pivotIdx + 1
|
||||
else:
|
||||
if (pivotIdx + 1) < r:
|
||||
s.quickSort(pivotIdx + 1, r)
|
||||
if (l + 1) < pivotIdx:
|
||||
r = pivotIdx - 1
|
||||
else:
|
||||
break
|
||||
if l >= r:
|
||||
break
|
||||
|
||||
proc sort*(s: var SuggestFileSymbolDatabase) =
|
||||
s.quickSort(s.lineInfo.low, s.lineInfo.high)
|
||||
s.isSorted = true
|
||||
|
||||
proc add*(s: var SuggestFileSymbolDatabase; v: SymInfoPair) =
|
||||
doAssert(v.info.fileIndex == s.fileIndex)
|
||||
s.lineInfo.add(TinyLineInfo(
|
||||
line: v.info.line,
|
||||
col: v.info.col
|
||||
))
|
||||
s.sym.add(v.sym)
|
||||
s.isDecl.add(v.isDecl)
|
||||
if s.trackCaughtExceptions:
|
||||
s.caughtExceptions.add(v.caughtExceptions)
|
||||
s.caughtExceptionsSet.add(v.caughtExceptionsSet)
|
||||
s.isSorted = false
|
||||
|
||||
proc add*(s: var SuggestSymbolDatabase; v: SymInfoPair; trackCaughtExceptions: bool) =
|
||||
s.mgetOrPut(v.info.fileIndex, newSuggestFileSymbolDatabase(v.info.fileIndex, trackCaughtExceptions)).add(v)
|
||||
|
||||
proc findSymInfoIndex*(s: var SuggestFileSymbolDatabase; li: TLineInfo): int =
|
||||
doAssert(li.fileIndex == s.fileIndex)
|
||||
if not s.isSorted:
|
||||
s.sort()
|
||||
var q = TinyLineInfo(
|
||||
line: li.line,
|
||||
col: li.col
|
||||
)
|
||||
result = binarySearch(s.lineInfo, q, cmp)
|
||||
Reference in New Issue
Block a user