diff options
author | Araq <rumpf_a@web.de> | 2018-09-25 00:28:39 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2018-09-25 00:28:39 +0200 |
commit | 548fc778c9b7048f474bf53c5d665bb8425e3343 (patch) | |
tree | bfae68122544db324cbb01b032eab1795ed6e0b8 | |
parent | 8029a649ba2cd394cad1749c017d5758cdcdbd4c (diff) | |
download | Nim-548fc778c9b7048f474bf53c5d665bb8425e3343.tar.gz |
.error for routines now can also have a custom error message; improve error message for 'nil' strings
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/pragmas.nim | 4 | ||||
-rw-r--r-- | compiler/suggest.nim | 31 | ||||
-rw-r--r-- | lib/system.nim | 12 |
4 files changed, 33 insertions, 15 deletions
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index a22b613f0..62c55de3d 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -81,6 +81,7 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimAshr") defineSymbol("nimNoNilSeqs") defineSymbol("nimNoNilSeqs2") + defineSymbol("nimHasUserErrors") defineSymbol("nimHasNilSeqs") for f in low(Feature)..high(Feature): diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 36c79bc9e..9a624fcce 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -954,12 +954,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, recordPragma(c, it, "warning", s) message(c.config, it.info, warnUser, s) of wError: - if sym != nil and sym.isRoutine: + if sym != nil and (sym.isRoutine or sym.kind == skType): # This is subtle but correct: the error *statement* is only # allowed for top level statements. Seems to be easier than # distinguishing properly between # ``proc p() {.error}`` and ``proc p() = {.error: "msg".}`` - noVal(c, it) + if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it) incl(sym.flags, sfError) else: let s = expectStrLit(c, it) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index b6b8d713c..b264415d8 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -33,7 +33,7 @@ # included from sigmatch.nim import algorithm, prefixmatches, lineinfos, pathutils -from wordrecg import wDeprecated +from wordrecg import wDeprecated, wError when defined(nimsuggest): import passes, tables # importer @@ -453,33 +453,42 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym; isDecl: 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 - +proc extractPragma(s: PSym): PNode = if s.kind in routineKinds: - pragmaNode = s.ast[pragmasPos] + result = 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 + result = s.ast[0][1] + doAssert result == nil or result.kind == nkPragma +proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) = + let pragmaNode = extractPragma(s) if pragmaNode != nil: for it in pragmaNode: if whichPragma(it) == wDeprecated and it.safeLen == 2 and - it[1].kind in {nkStrLit..nkTripleStrLit}: + 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 userError(conf: ConfigRef; info: TLineInfo; s: PSym) = + let pragmaNode = extractPragma(s) + + if pragmaNode != nil: + for it in pragmaNode: + if whichPragma(it) == wError and it.safeLen == 2 and + it[1].kind in {nkStrLit..nkTripleStrLit}: + localError(conf, info, it[1].strVal & "; usage of '$1' is a user-defined error" % s.name.s) + return + localError(conf, info, "usage of '$1' is a user-defined error" % s.name.s) + proc markUsed(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) = incl(s.flags, sfUsed) if s.kind == skEnumField and s.owner != nil: incl(s.owner.flags, sfUsed) if {sfDeprecated, sfError} * s.flags != {}: if sfDeprecated in s.flags: warnAboutDeprecated(conf, info, s) - if sfError in s.flags: localError(conf, info, "usage of '$1' is a user-defined error" % s.name.s) + if sfError in s.flags: userError(conf, info, s) when defined(nimsuggest): suggestSym(conf, info, s, usageSym, false) diff --git a/lib/system.nim b/lib/system.nim index 49e6a396d..28c4f62ab 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -4112,8 +4112,16 @@ proc `==`*(x, y: cstring): bool {.magic: "EqCString", noSideEffect, when defined(nimNoNilSeqs2): when not compileOption("nilseqs"): - proc `==`*(x: string; y: type(nil)): bool {.error.} = discard - proc `==`*(x: type(nil); y: string): bool {.error.} = discard + when defined(nimHasUserErrors): + proc `==`*(x: string; y: type(nil)): bool {. + error: "'nil' is now invalid for 'string'; compile with --nilseqs:on for a migration period".} = + discard + proc `==`*(x: type(nil); y: string): bool {. + error: "'nil' is now invalid for 'string'; compile with --nilseqs:on for a migration period".} = + discard + else: + proc `==`*(x: string; y: type(nil)): bool {.error.} = discard + proc `==`*(x: type(nil); y: string): bool {.error.} = discard template closureScope*(body: untyped): untyped = ## Useful when creating a closure in a loop to capture local loop variables by |