Skip to content

Commit 478773f

Browse files
nickysnAraqringabout
authored
NimSuggest: Fix for the inlay exception hints with generic procs (#23610)
Based on the fix, started by SirOlaf in #23414 --------- Co-authored-by: SirOlaf <> Co-authored-by: Andreas Rumpf <[email protected]> Co-authored-by: ringabout <[email protected]>
1 parent f4ebabb commit 478773f

File tree

8 files changed

+129
-79
lines changed

8 files changed

+129
-79
lines changed

compiler/modulegraphs.nim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,10 +457,10 @@ template getPContext(): untyped =
457457
else: c.c
458458

459459
when defined(nimsuggest):
460-
template onUse*(info: TLineInfo; s: PSym) = discard
460+
template onUse*(info: TLineInfo; s: PSym; isGenericInstance = false) = discard
461461
template onDefResolveForward*(info: TLineInfo; s: PSym) = discard
462462
else:
463-
template onUse*(info: TLineInfo; s: PSym) = discard
463+
template onUse*(info: TLineInfo; s: PSym; isGenericInstance = false) = discard
464464
template onDef*(info: TLineInfo; s: PSym) = discard
465465
template onDefResolveForward*(info: TLineInfo; s: PSym) = discard
466466

compiler/semcall.nim

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -836,9 +836,12 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
836836
assert x.state == csMatch
837837
var finalCallee = x.calleeSym
838838
let info = getCallLineInfo(n)
839-
markUsed(c, info, finalCallee)
840-
onUse(info, finalCallee)
839+
markUsed(c, info, finalCallee, isGenericInstance = false)
840+
onUse(info, finalCallee, isGenericInstance = false)
841841
assert finalCallee.ast != nil
842+
if x.matchedErrorType:
843+
markUsed(c, info, finalCallee, isGenericInstance = true)
844+
onUse(info, finalCallee, isGenericInstance = true)
842845
if x.matchedErrorType:
843846
result = x.call
844847
result[0] = newSymNode(finalCallee, getCallLineInfo(result[0]))
@@ -874,6 +877,8 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
874877
x.call.add tn
875878
else:
876879
internalAssert c.config, false
880+
markUsed(c, info, finalCallee, isGenericInstance = true)
881+
onUse(info, finalCallee, isGenericInstance = true)
877882

878883
result = x.call
879884
instGenericConvertersSons(c, result, x)
@@ -942,8 +947,10 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym, errors: var CandidateErr
942947
var newInst = generateInstance(c, s, m.bindings, n.info)
943948
newInst.typ.flags.excl tfUnresolved
944949
let info = getCallLineInfo(n)
945-
markUsed(c, info, s)
946-
onUse(info, s)
950+
markUsed(c, info, s, isGenericInstance = false)
951+
onUse(info, s, isGenericInstance = false)
952+
markUsed(c, info, newInst, isGenericInstance = true)
953+
onUse(info, newInst, isGenericInstance = true)
947954
result = newSymNode(newInst, info)
948955

949956
proc setGenericParams(c: PContext, n, expectedParams: PNode) =

compiler/sempass2.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ proc checkForSink(tracked: PEffects; n: PNode) =
971971
proc markCaughtExceptions(tracked: PEffects; g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym) =
972972
when defined(nimsuggest):
973973
proc internalMarkCaughtExceptions(tracked: PEffects; q: var SuggestFileSymbolDatabase; info: TLineInfo) =
974-
var si = q.findSymInfoIndex(info)
974+
var si = q.findSymInfoIndex(info, true)
975975
if si != -1:
976976
q.caughtExceptionsSet[si] = true
977977
for w1 in tracked.caughtExceptions.nodes:

compiler/sigmatch.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ const
104104
isNilConversion = isConvertible # maybe 'isIntConv' fits better?
105105
maxInheritancePenalty = high(int) div 2
106106

107-
proc markUsed*(c: PContext; info: TLineInfo, s: PSym; checkStyle = true)
107+
proc markUsed*(c: PContext; info: TLineInfo, s: PSym; checkStyle = true; isGenericInstance = false)
108108
proc markOwnerModuleAsUsed*(c: PContext; s: PSym)
109109

110110
proc initCandidateAux(ctx: PContext,

compiler/suggest.nim

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -624,41 +624,43 @@ proc ensureIdx[T](x: var T, y: int) =
624624
proc ensureSeq[T](x: var seq[T]) =
625625
if x == nil: newSeq(x, 0)
626626

627-
proc suggestSym*(g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym; isDecl=true) {.inline.} =
627+
proc suggestSym*(g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym; isDecl=true; isGenericInstance=false) {.inline.} =
628628
## misnamed: should be 'symDeclared'
629629
let conf = g.config
630630
when defined(nimsuggest):
631-
g.suggestSymbols.add SymInfoPair(sym: s, info: info, isDecl: isDecl), optIdeExceptionInlayHints in g.config.globalOptions
631+
if optIdeExceptionInlayHints in conf.globalOptions or not isGenericInstance:
632+
g.suggestSymbols.add SymInfoPair(sym: s, info: info, isDecl: isDecl, isGenericInstance: isGenericInstance), optIdeExceptionInlayHints in g.config.globalOptions
632633

633-
if conf.suggestVersion == 0:
634-
if s.allUsages.len == 0:
635-
s.allUsages = @[info]
636-
else:
637-
s.addNoDup(info)
638-
639-
if conf.ideCmd == ideUse:
640-
findUsages(g, info, s, usageSym)
641-
elif conf.ideCmd == ideDef:
642-
findDefinition(g, info, s, usageSym)
643-
elif conf.ideCmd == ideDus and s != nil:
644-
if isTracked(info, conf.m.trackPos, s.name.s.len):
645-
suggestResult(conf, symToSuggest(g, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
646-
findUsages(g, info, s, usageSym)
647-
elif conf.ideCmd == ideHighlight and info.fileIndex == conf.m.trackPos.fileIndex:
648-
suggestResult(conf, symToSuggest(g, s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0))
649-
elif conf.ideCmd == ideOutline and isDecl:
650-
# if a module is included then the info we have is inside the include and
651-
# we need to walk up the owners until we find the outer most module,
652-
# which will be the last skModule prior to an skPackage.
653-
var
654-
parentFileIndex = info.fileIndex # assume we're in the correct module
655-
parentModule = s.owner
656-
while parentModule != nil and parentModule.kind == skModule:
657-
parentFileIndex = parentModule.info.fileIndex
658-
parentModule = parentModule.owner
659-
660-
if parentFileIndex == conf.m.trackPos.fileIndex:
661-
suggestResult(conf, symToSuggest(g, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))
634+
if not isGenericInstance:
635+
if conf.suggestVersion == 0:
636+
if s.allUsages.len == 0:
637+
s.allUsages = @[info]
638+
else:
639+
s.addNoDup(info)
640+
641+
if conf.ideCmd == ideUse:
642+
findUsages(g, info, s, usageSym)
643+
elif conf.ideCmd == ideDef:
644+
findDefinition(g, info, s, usageSym)
645+
elif conf.ideCmd == ideDus and s != nil:
646+
if isTracked(info, conf.m.trackPos, s.name.s.len):
647+
suggestResult(conf, symToSuggest(g, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
648+
findUsages(g, info, s, usageSym)
649+
elif conf.ideCmd == ideHighlight and info.fileIndex == conf.m.trackPos.fileIndex:
650+
suggestResult(conf, symToSuggest(g, s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0))
651+
elif conf.ideCmd == ideOutline and isDecl:
652+
# if a module is included then the info we have is inside the include and
653+
# we need to walk up the owners until we find the outer most module,
654+
# which will be the last skModule prior to an skPackage.
655+
var
656+
parentFileIndex = info.fileIndex # assume we're in the correct module
657+
parentModule = s.owner
658+
while parentModule != nil and parentModule.kind == skModule:
659+
parentFileIndex = parentModule.info.fileIndex
660+
parentModule = parentModule.owner
661+
662+
if parentFileIndex == conf.m.trackPos.fileIndex:
663+
suggestResult(conf, symToSuggest(g, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))
662664

663665
proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
664666
var pragmaNode: PNode
@@ -702,26 +704,28 @@ proc markOwnerModuleAsUsed(c: PContext; s: PSym) =
702704
else:
703705
inc i
704706

705-
proc markUsed(c: PContext; info: TLineInfo; s: PSym; checkStyle = true) =
706-
let conf = c.config
707-
incl(s.flags, sfUsed)
708-
if s.kind == skEnumField and s.owner != nil:
709-
incl(s.owner.flags, sfUsed)
710-
if sfDeprecated in s.owner.flags:
711-
warnAboutDeprecated(conf, info, s)
712-
if {sfDeprecated, sfError} * s.flags != {}:
713-
if sfDeprecated in s.flags:
714-
if not (c.lastTLineInfo.line == info.line and
715-
c.lastTLineInfo.col == info.col):
707+
proc markUsed(c: PContext; info: TLineInfo; s: PSym; checkStyle = true; isGenericInstance = false) =
708+
if not isGenericInstance:
709+
let conf = c.config
710+
incl(s.flags, sfUsed)
711+
if s.kind == skEnumField and s.owner != nil:
712+
incl(s.owner.flags, sfUsed)
713+
if sfDeprecated in s.owner.flags:
716714
warnAboutDeprecated(conf, info, s)
717-
c.lastTLineInfo = info
718-
719-
if sfError in s.flags: userError(conf, info, s)
715+
if {sfDeprecated, sfError} * s.flags != {}:
716+
if sfDeprecated in s.flags:
717+
if not (c.lastTLineInfo.line == info.line and
718+
c.lastTLineInfo.col == info.col):
719+
warnAboutDeprecated(conf, info, s)
720+
c.lastTLineInfo = info
721+
722+
if sfError in s.flags: userError(conf, info, s)
720723
when defined(nimsuggest):
721-
suggestSym(c.graph, info, s, c.graph.usageSym, false)
722-
if checkStyle:
723-
styleCheckUse(c, info, s)
724-
markOwnerModuleAsUsed(c, s)
724+
suggestSym(c.graph, info, s, c.graph.usageSym, isDecl = false, isGenericInstance = isGenericInstance)
725+
if not isGenericInstance:
726+
if checkStyle:
727+
styleCheckUse(c, info, s)
728+
markOwnerModuleAsUsed(c, s)
725729

726730
proc safeSemExpr*(c: PContext, n: PNode): PNode =
727731
# use only for idetools support!

compiler/suggestsymdb.nim

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ type
1616
caughtExceptions*: seq[PType]
1717
caughtExceptionsSet*: bool
1818
isDecl*: bool
19+
isGenericInstance*: bool
1920

2021
SuggestFileSymbolDatabase* = object
2122
lineInfo*: seq[TinyLineInfo]
2223
sym*: seq[PSym]
2324
caughtExceptions*: seq[seq[PType]]
2425
caughtExceptionsSet*: PackedBoolArray
2526
isDecl*: PackedBoolArray
27+
isGenericInstance*: PackedBoolArray
2628
fileIndex*: FileIndex
2729
trackCaughtExceptions*: bool
2830
isSorted*: bool
@@ -82,6 +84,11 @@ proc getSymInfoPair*(s: SuggestFileSymbolDatabase; idx: int): SymInfoPair =
8284
s.caughtExceptionsSet[idx]
8385
else:
8486
false,
87+
isGenericInstance:
88+
if s.trackCaughtExceptions:
89+
s.isGenericInstance[idx]
90+
else:
91+
false,
8592
isDecl: s.isDecl[idx]
8693
)
8794

@@ -90,6 +97,7 @@ proc reverse*(s: var SuggestFileSymbolDatabase) =
9097
s.sym.reverse()
9198
s.caughtExceptions.reverse()
9299
s.caughtExceptionsSet.reverse()
100+
s.isGenericInstance.reverse()
93101
s.isDecl.reverse()
94102

95103
proc newSuggestFileSymbolDatabase*(aFileIndex: FileIndex; aTrackCaughtExceptions: bool): SuggestFileSymbolDatabase =
@@ -99,6 +107,7 @@ proc newSuggestFileSymbolDatabase*(aFileIndex: FileIndex; aTrackCaughtExceptions
99107
caughtExceptions: @[],
100108
caughtExceptionsSet: newPackedBoolArray(),
101109
isDecl: newPackedBoolArray(),
110+
isGenericInstance: newPackedBoolArray(),
102111
fileIndex: aFileIndex,
103112
trackCaughtExceptions: aTrackCaughtExceptions,
104113
isSorted: true
@@ -119,6 +128,8 @@ func compare*(s: var SuggestFileSymbolDatabase; i, j: int): int =
119128
result = cmp(s.lineInfo[i], s.lineInfo[j])
120129
if result == 0:
121130
result = cmp(s.isDecl[i], s.isDecl[j])
131+
if result == 0 and s.trackCaughtExceptions:
132+
result = cmp(s.isGenericInstance[i], s.isGenericInstance[j])
122133

123134
proc exchange(s: var SuggestFileSymbolDatabase; i, j: int) =
124135
if i == j:
@@ -133,6 +144,9 @@ proc exchange(s: var SuggestFileSymbolDatabase; i, j: int) =
133144
var tmp3 = s.caughtExceptionsSet[i]
134145
s.caughtExceptionsSet[i] = s.caughtExceptionsSet[j]
135146
s.caughtExceptionsSet[j] = tmp3
147+
var tmp6 = s.isGenericInstance[i]
148+
s.isGenericInstance[i] = s.isGenericInstance[j]
149+
s.isGenericInstance[j] = tmp6
136150
var tmp4 = s.isDecl[i]
137151
s.isDecl[i] = s.isDecl[j]
138152
s.isDecl[j] = tmp4
@@ -196,12 +210,17 @@ proc add*(s: var SuggestFileSymbolDatabase; v: SymInfoPair) =
196210
if s.trackCaughtExceptions:
197211
s.caughtExceptions.add(v.caughtExceptions)
198212
s.caughtExceptionsSet.add(v.caughtExceptionsSet)
213+
s.isGenericInstance.add(v.isGenericInstance)
199214
s.isSorted = false
200215

201216
proc add*(s: var SuggestSymbolDatabase; v: SymInfoPair; trackCaughtExceptions: bool) =
202217
s.mgetOrPut(v.info.fileIndex, newSuggestFileSymbolDatabase(v.info.fileIndex, trackCaughtExceptions)).add(v)
203218

204-
proc findSymInfoIndex*(s: var SuggestFileSymbolDatabase; li: TLineInfo): int =
219+
proc findSymInfoIndex*(s: var SuggestFileSymbolDatabase; li: TLineInfo; isGenericInstance: bool): int =
220+
# if trackCaughtExceptions is false, then all records in the database are not generic instances, so
221+
# if we're searching for a generic instance, we find none
222+
if isGenericInstance and not s.trackCaughtExceptions:
223+
return -1
205224
doAssert(li.fileIndex == s.fileIndex)
206225
if not s.isSorted:
207226
s.sort()
@@ -210,3 +229,17 @@ proc findSymInfoIndex*(s: var SuggestFileSymbolDatabase; li: TLineInfo): int =
210229
col: li.col
211230
)
212231
result = binarySearch(s.lineInfo, q, cmp)
232+
# if trackCaughtExceptions is false, then all records in the database are not generic instances, so
233+
# if we're a searching for a non-generic instance, then we're done, we return what we have found
234+
if not isGenericInstance and not s.trackCaughtExceptions:
235+
return
236+
# in this case trackCaughtExceptions is true, and the database contains both generic and non-generic instances, so we need
237+
# to check the isGenericInstance flag also
238+
if result != -1:
239+
# search through a sequence of equal lineInfos to find a matching isGenericInstance
240+
while result > 0 and s.isGenericInstance[result] != isGenericInstance and cmp(s.lineInfo[result], s.lineInfo[result - 1]) == 0:
241+
dec result
242+
while result < (s.lineInfo.len - 1) and s.isGenericInstance[result] != isGenericInstance and cmp(s.lineInfo[result], s.lineInfo[result + 1]) == 0:
243+
inc result
244+
if s.isGenericInstance[result] != isGenericInstance:
245+
result = -1

compiler/types.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
766766
prag.add("effectsOf: ")
767767
prag.add(effectsOfStr)
768768
if not hasImplicitRaises and prefer == preferInferredEffects and not isNil(t.owner) and not isNil(t.owner.typ) and not isNil(t.owner.typ.n) and (t.owner.typ.n.len > 0):
769-
let effects = t.owner.typ.n[0]
769+
let effects = t.n[0]
770770
if effects.kind == nkEffectList and effects.len == effectListLen:
771771
var inferredRaisesStr = ""
772772
let effs = effects[exceptionEffects]

0 commit comments

Comments
 (0)