From cf20c4460c5b495a97b3f1f1d091f77832b89384 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 21 Aug 2018 15:07:44 +0200 Subject: [PATCH] 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 --- compiler/pragmas.nim | 10 ++++++++-- compiler/suggest.nim | 23 ++++++++++++++++------- tests/deprecated/importme.nim | 10 ++++++++++ tests/deprecated/tmodule1.nim | 23 +++++++++++++++++++++++ tests/deprecated/tnoannot.nim | 7 +++++++ 5 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 tests/deprecated/importme.nim create mode 100644 tests/deprecated/tmodule1.nim create mode 100644 tests/deprecated/tnoannot.nim diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index a067f2074a..263068344d 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -868,11 +868,17 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, of wExplain: sym.flags.incl sfExplain 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) 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 sym != nil: incl(sym.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated) of wVarargs: noVal(c, it) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index a21d643389..b52632c67b 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -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)) proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) = + var pragmaNode: PNode + if s.kind in routineKinds: - let n = s.ast[pragmasPos] - if n.kind != nkEmpty: - for it in n: - 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 + pragmaNode = s.ast[pragmasPos] + elif s.kind in {skType}: + # s.ast = nkTypedef / nkPragmaExpr / [nkSym, nkPragma] + pragmaNode = s.ast[0][1] + + doAssert pragmaNode == nil or pragmaNode.kind == nkPragma + + 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) proc markUsed(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) = diff --git a/tests/deprecated/importme.nim b/tests/deprecated/importme.nim new file mode 100644 index 0000000000..0a9c6e37da --- /dev/null +++ b/tests/deprecated/importme.nim @@ -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".} diff --git a/tests/deprecated/tmodule1.nim b/tests/deprecated/tmodule1.nim new file mode 100644 index 0000000000..9548368890 --- /dev/null +++ b/tests/deprecated/tmodule1.nim @@ -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() diff --git a/tests/deprecated/tnoannot.nim b/tests/deprecated/tnoannot.nim new file mode 100644 index 0000000000..9cc5c7e062 --- /dev/null +++ b/tests/deprecated/tnoannot.nim @@ -0,0 +1,7 @@ +discard """ + line: 7 + errormsg: "annotation to deprecated not supported here" +""" + +var foo* {.deprecated.} = 42 +var foo1* {.deprecated: "no".} = 42