diff options
author | Jake Leahy <jake@leahy.dev> | 2023-12-08 09:05:41 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-07 23:05:41 +0100 |
commit | 0a7094450ec059e10da67d47a76d004d4972b368 (patch) | |
tree | f0e3e5abe4197b53b922c17835cf8323b20136da | |
parent | 4fdc6c49bd2a9085d40590bd9ba9696b1e6066d9 (diff) | |
download | Nim-0a7094450ec059e10da67d47a76d004d4972b368.tar.gz |
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
-rw-r--r-- | compiler/pragmas.nim | 5 | ||||
-rw-r--r-- | compiler/semstmts.nim | 4 | ||||
-rw-r--r-- | compiler/semtypes.nim | 2 | ||||
-rw-r--r-- | compiler/suggest.nim | 37 | ||||
-rw-r--r-- | nimsuggest/tests/tsug_pragmas.nim | 40 |
5 files changed, 85 insertions, 3 deletions
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index fe4ef2b87..0e434e6f7 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -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) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 4b08767c0..70818bb67 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index be33114f5..7968122ed 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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" diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 5053fe669..802da1c3e 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -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 diff --git a/nimsuggest/tests/tsug_pragmas.nim b/nimsuggest/tests/tsug_pragmas.nim new file mode 100644 index 000000000..03a9cba4c --- /dev/null +++ b/nimsuggest/tests/tsug_pragmas.nim @@ -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 +""" + + |