More robust handling of deprecated pragmas (#8696)

Prevent `deprecated` annotations to "slip" up to the parent module and
warn about unsupported annotations.

Accidentally fixes #7867
This commit is contained in:
LemonBoy 2018-08-21 15:07:44 +02:00 • committed by Andreas Rumpf
commit cf20c4460c
5 changed files with 64 additions and 9 deletions

View file

@ -868,11 +868,17 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wExplain: of wExplain:
sym.flags.incl sfExplain sym.flags.incl sfExplain
of wDeprecated: of wDeprecated:
if sym != nil and sym.kind in routineKinds: if sym != nil and sym.kind in routineKinds + {skType}:
if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it) if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it)
incl(sym.flags, sfDeprecated) incl(sym.flags, sfDeprecated)
elif sym != nil and sym.kind != skModule:
# We don't support the extra annotation field
if it.kind in nkPragmaCallKinds:
localError(c.config, it.info, "annotation to deprecated not supported here")
incl(sym.flags, sfDeprecated)
# At this point we're quite sure this is a statement and applies to the
# whole module
elif it.kind in nkPragmaCallKinds: deprecatedStmt(c, it) elif it.kind in nkPragmaCallKinds: deprecatedStmt(c, it)
elif sym != nil: incl(sym.flags, sfDeprecated)
else: incl(c.module.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated)
of wVarargs: of wVarargs:
noVal(c, it) noVal(c, it)

View file

@ -454,14 +454,23 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym;
suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0)) suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))
proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) = proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
var pragmaNode: PNode
if s.kind in routineKinds: if s.kind in routineKinds:
let n = s.ast[pragmasPos] pragmaNode = s.ast[pragmasPos]
if n.kind != nkEmpty: elif s.kind in {skType}:
for it in n: # s.ast = nkTypedef / nkPragmaExpr / [nkSym, nkPragma]
if whichPragma(it) == wDeprecated and it.safeLen == 2 and pragmaNode = s.ast[0][1]
it[1].kind in {nkStrLit..nkTripleStrLit}:
message(conf, info, warnDeprecated, it[1].strVal & "; " & s.name.s) doAssert pragmaNode == nil or pragmaNode.kind == nkPragma
return
if pragmaNode != nil:
for it in pragmaNode:
if whichPragma(it) == wDeprecated and it.safeLen == 2 and
it[1].kind in {nkStrLit..nkTripleStrLit}:
message(conf, info, warnDeprecated, it[1].strVal & "; " & s.name.s)
return
message(conf, info, warnDeprecated, s.name.s) message(conf, info, warnDeprecated, s.name.s)
proc markUsed(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) = proc markUsed(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) =

View file

@ -0,0 +1,10 @@
type
Ty* {.deprecated.} = uint32
Ty1* {.deprecated: "hello".} = uint32
var aVar* {.deprecated.}: char
proc aProc*() {.deprecated.} = discard
proc aProc1*() {.deprecated: "hello".} = discard
{.deprecated: "goodbye".}

View file

@ -0,0 +1,23 @@
discard """
nimout: '''tmodule1.nim(11, 8) Warning: goodbye; importme is deprecated [Deprecated]
tmodule1.nim(14, 10) Warning: Ty is deprecated [Deprecated]
tmodule1.nim(17, 10) Warning: hello; Ty1 is deprecated [Deprecated]
tmodule1.nim(20, 8) Warning: aVar is deprecated [Deprecated]
tmodule1.nim(22, 3) Warning: aProc is deprecated [Deprecated]
tmodule1.nim(23, 3) Warning: hello; aProc1 is deprecated [Deprecated]
'''
"""
import importme
block:
var z: Ty
z = 0
block:
var z: Ty1
z = 0
block:
echo aVar
block:
aProc()
aProc1()

View file

@ -0,0 +1,7 @@
discard """
line: 7
errormsg: "annotation to deprecated not supported here"
"""
var foo* {.deprecated.} = 42
var foo1* {.deprecated: "no".} = 42