Only suggest symbols that could be pragmas when typing a pragma (#23040)

Currently pragmas just fall through to `suggestSentinel` and show
everything which isn't very useful. Now it filters for symbols that
could be pragmas (templates with `{.pragma.}`, macros, user pragmas) and
only shows them
This commit is contained in:
Jake Leahy
2023-12-08 09:05:41 +11:00
committed by GitHub
parent 4fdc6c49bd
commit 0a7094450e
5 changed files with 85 additions and 3 deletions

View File

@@ -14,6 +14,8 @@ import
wordrecg, ropes, options, extccomp, magicsys, trees,
types, lookups, lineinfos, pathutils, linter, modulepaths
from sigmatch import trySuggestPragmas
import std/[os, math, strutils]
when defined(nimPreviewSlimSystem):
@@ -119,6 +121,7 @@ const
proc invalidPragma*(c: PContext; n: PNode) =
localError(c.config, n.info, "invalid pragma: " & renderTree(n, {renderNoComments}))
proc illegalCustomPragma*(c: PContext, n: PNode, s: PSym) =
var msg = "cannot attach a custom pragma to '" & s.name.s & "'"
if s != nil:
@@ -790,6 +793,8 @@ proc semCustomPragma(c: PContext, n: PNode, sym: PSym): PNode =
invalidPragma(c, n)
return n
trySuggestPragmas(c, callNode[0])
let r = c.semOverloadedCall(c, callNode, n, {skTemplate}, {efNoUndeclared})
if r.isNil or sfCustomPragma notin r[0].sym.flags:
invalidPragma(c, n)

View File

@@ -525,6 +525,8 @@ proc semVarMacroPragma(c: PContext, a: PNode, n: PNode): PNode =
let it = pragmas[i]
let key = if it.kind in nkPragmaCallKinds and it.len >= 1: it[0] else: it
trySuggestPragmas(c, key)
if isPossibleMacroPragma(c, it, key):
# we transform ``var p {.m, rest.}`` into ``m(do: var p {.rest.})`` and
# let the semantic checker deal with it:
@@ -1741,6 +1743,8 @@ proc semProcAnnotation(c: PContext, prc: PNode;
let it = n[i]
let key = if it.kind in nkPragmaCallKinds and it.len >= 1: it[0] else: it
trySuggestPragmas(c, key)
if isPossibleMacroPragma(c, it, key):
# we transform ``proc p {.m, rest.}`` into ``m(do: proc p {.rest.})`` and
# let the semantic checker deal with it:

View File

@@ -1741,10 +1741,10 @@ proc applyTypeSectionPragmas(c: PContext; pragmas, operand: PNode): PNode =
result = nil
for p in pragmas:
let key = if p.kind in nkPragmaCallKinds and p.len >= 1: p[0] else: p
if p.kind == nkEmpty or whichPragma(p) != wInvalid:
discard "builtin pragma"
else:
trySuggestPragmas(c, key)
let ident = considerQuotedIdent(c, key)
if strTableGet(c.userPragmas, ident) != nil:
discard "User-defined pragma"

View File

@@ -126,7 +126,7 @@ proc symToSuggest*(g: ModuleGraph; s: PSym, isLocal: bool, section: IdeCmd, info
inTypeContext: bool; scope: int;
useSuppliedInfo = false,
endLine: uint16 = 0,
endCol = 0): Suggest =
endCol = 0, extractDocs = true): Suggest =
new(result)
result.section = section
result.quality = quality
@@ -165,7 +165,8 @@ proc symToSuggest*(g: ModuleGraph; s: PSym, isLocal: bool, section: IdeCmd, info
else:
result.forth = ""
when defined(nimsuggest) and not defined(noDocgen) and not defined(leanCompiler):
result.doc = extractDocComment(g, s)
if extractDocs:
result.doc = extractDocComment(g, s)
if s.kind == skModule and s.ast.len != 0 and section != ideHighlight:
result.filePath = toFullPath(g.config, s.ast[0].info)
result.line = 1
@@ -746,6 +747,38 @@ proc suggestEnum*(c: PContext; n: PNode; t: PType) =
produceOutput(outputs, c.config)
if outputs.len > 0: suggestQuit()
proc suggestPragmas*(c: PContext, n: PNode) =
## Suggests anything that might be a pragma
## - template that has {.pragma.}
## - macros
## - user pragmas
let info = n.info
var outputs: Suggestions = @[]
# First filter for template/macros
wholeSymTab(filterSym(it, n, pm) and
(sfCustomPragma in it.flags or it.kind == skMacro),
ideSug)
# Now show suggestions for user pragmas
for pragma in c.userPragmas:
var pm = default(PrefixMatch)
if filterSym(pragma, n, pm):
outputs &= symToSuggest(c.graph, pragma, isLocal=true, ideSug, info,
pragma.getQuality, pm, c.inTypeContext > 0, 0,
extractDocs=false)
produceOutput(outputs, c.config)
if outputs.len > 0:
suggestQuit()
template trySuggestPragmas*(c: PContext, n: PNode) =
## Runs [suggestPragmas] when compiling nimsuggest and
## we are querying the node
when defined(nimsuggest):
let tmp = n
if c.config.ideCmd == ideSug and exactEquals(c.config.m.trackPos, tmp.info):
suggestPragmas(c, tmp)
proc suggestSentinel*(c: PContext) =
if c.config.ideCmd != ideSug or c.module.position != c.config.m.trackPos.fileIndex.int32: return
if c.compilesContextId > 0: return

View File

@@ -0,0 +1,40 @@
template fooBar1() {.pragma.}
proc fooBar2() = discard
macro fooBar3(x: untyped) = discard
{.pragma: fooBar4 fooBar3.}
proc test1() {.fooBar#[!]#.} = discard
var test2 {.fooBar#[!]#.} = 9
type
Person {.fooBar#[!]#.} = object
hello {.fooBar#[!]#.}: string
Callback = proc () {.fooBar#[!]#.}
# Check only macros/templates/pragmas are suggested
discard """
$nimsuggest --tester $file
>sug $1
sug;;skTemplate;;fooBar4;;;;$file;;4;;8;;"";;100;;Prefix
sug;;skTemplate;;tsug_pragmas.fooBar1;;template ();;$file;;1;;9;;"";;100;;Prefix
sug;;skMacro;;tsug_pragmas.fooBar3;;macro (x: untyped){.noSideEffect, gcsafe.};;$file;;3;;6;;"";;50;;Prefix
>sug $2
sug;;skTemplate;;fooBar4;;;;$file;;4;;8;;"";;100;;Prefix
sug;;skTemplate;;tsug_pragmas.fooBar1;;template ();;$file;;1;;9;;"";;100;;Prefix
sug;;skMacro;;tsug_pragmas.fooBar3;;macro (x: untyped){.noSideEffect, gcsafe.};;$file;;3;;6;;"";;50;;Prefix
>sug $3
sug;;skTemplate;;fooBar4;;;;$file;;4;;8;;"";;100;;Prefix
sug;;skTemplate;;tsug_pragmas.fooBar1;;template ();;$file;;1;;9;;"";;100;;Prefix
sug;;skMacro;;tsug_pragmas.fooBar3;;macro (x: untyped){.noSideEffect, gcsafe.};;$file;;3;;6;;"";;50;;Prefix
>sug $4
sug;;skTemplate;;fooBar4;;;;$file;;4;;8;;"";;100;;Prefix
sug;;skTemplate;;tsug_pragmas.fooBar1;;template ();;$file;;1;;9;;"";;100;;Prefix
sug;;skMacro;;tsug_pragmas.fooBar3;;macro (x: untyped){.noSideEffect, gcsafe.};;$file;;3;;6;;"";;50;;Prefix
>sug $5
sug;;skTemplate;;fooBar4;;;;$file;;4;;8;;"";;100;;Prefix
sug;;skTemplate;;tsug_pragmas.fooBar1;;template ();;$file;;1;;9;;"";;100;;Prefix
sug;;skMacro;;tsug_pragmas.fooBar3;;macro (x: untyped){.noSideEffect, gcsafe.};;$file;;3;;6;;"";;50;;Prefix
"""