support --hint:all:off --hint:x (ditto with --warnings + friends) (#17852)

* select all hints via `--hint:all:on|off`, etc
* simplify code with setutils
* address comment
This commit is contained in:
Timothee Cour 2021-06-20 10:52:22 -07:00 • committed by GitHub
commit 7d5e6b0169
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 44 deletions

View file

@ -429,6 +429,10 @@
- `--hint:CC` now goes to stderr (like all other hints) instead of stdout. - `--hint:CC` now goes to stderr (like all other hints) instead of stdout.
- `--hint:all:on|off` is now supported to select or deselect all hints; it
differs from `--hints:on|off` which acts as a (reversible) gate.
Likewise with `--warning:all:on|off`.
- json build instructions are now generated in `$nimcache/outFileBasename.json` - json build instructions are now generated in `$nimcache/outFileBasename.json`
instead of `$nimcache/projectName.json`. This allows avoiding recompiling a given project instead of `$nimcache/projectName.json`. This allows avoiding recompiling a given project
compiled with different options if the output file differs. compiled with different options if the output file differs.

View file

@ -25,10 +25,10 @@ bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep")
bootSwitch(usedGoGC, defined(gogc), "--gc:go") bootSwitch(usedGoGC, defined(gogc), "--gc:go")
bootSwitch(usedNoGC, defined(nogc), "--gc:none") bootSwitch(usedNoGC, defined(nogc), "--gc:none")
import std/[setutils, os, strutils, parseutils, parseopt, sequtils, strtabs]
import import
os, msgs, options, nversion, condsyms, strutils, extccomp, platform, msgs, options, nversion, condsyms, extccomp, platform,
wordrecg, parseutils, nimblecmd, parseopt, sequtils, lineinfos, wordrecg, nimblecmd, lineinfos, pathutils, pathnorm
pathutils, strtabs, pathnorm
from ast import eqTypeFlags, tfGcSafe, tfNoSideEffect from ast import eqTypeFlags, tfGcSafe, tfNoSideEffect
@ -182,7 +182,7 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
info: TLineInfo; orig: string; conf: ConfigRef) = info: TLineInfo; orig: string; conf: ConfigRef) =
var id = "" # arg = key or [key] or key:val or [key]:val; with val=on|off var id = "" # arg = key or [key] or key:val or [key]:val; with val=on|off
var i = 0 var i = 0
var n = hintMin var notes: set[TMsgKind]
var isBracket = false var isBracket = false
if i < arg.len and arg[i] == '[': if i < arg.len and arg[i] == '[':
isBracket = true isBracket = true
@ -197,37 +197,36 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
if i == arg.len: discard if i == arg.len: discard
elif i < arg.len and (arg[i] in {':', '='}): inc(i) elif i < arg.len and (arg[i] in {':', '='}): inc(i)
else: invalidCmdLineOption(conf, pass, orig, info) else: invalidCmdLineOption(conf, pass, orig, info)
# unfortunately, hintUser and warningUser clash
if state in {wHint, wHintAsError}:
let x = findStr(hintMin, hintMax, id, errUnknown)
if x != errUnknown: n = TNoteKind(x)
else: localError(conf, info, "unknown hint: " & id)
else:
let x = findStr(warnMin, warnMax, id, errUnknown)
if x != errUnknown: n = TNoteKind(x)
else: localError(conf, info, "unknown warning: " & id)
let isSomeHint = state in {wHint, wHintAsError}
template findNote(noteMin, noteMax, name) =
# unfortunately, hintUser and warningUser clash, otherwise implementation would simplify a bit
let x = findStr(noteMin, noteMax, id, errUnknown)
if x != errUnknown: notes = {TNoteKind(x)}
else: localError(conf, info, "unknown $#: $#" % [name, id])
case id.normalize
of "all": # other note groups would be easy to support via additional cases
notes = if isSomeHint: {hintMin..hintMax} else: {warnMin..warnMax}
elif isSomeHint: findNote(hintMin, hintMax, "hint")
else: findNote(warnMin, warnMax, "warning")
var val = substr(arg, i).normalize var val = substr(arg, i).normalize
if val == "": val = "on" if val == "": val = "on"
if val notin ["on", "off"]: if val notin ["on", "off"]:
# xxx in future work we should also allow users to have control over `foreignPackageNotes`
# so that they can enable `hints|warnings|warningAsErrors` for all the code they depend on.
localError(conf, info, errOnOrOffExpectedButXFound % arg) localError(conf, info, errOnOrOffExpectedButXFound % arg)
elif n notin conf.cmdlineNotes or pass == passCmd1: else:
if pass == passCmd1: incl(conf.cmdlineNotes, n) let isOn = val == "on"
incl(conf.modifiedyNotes, n) for n in notes:
case val if n notin conf.cmdlineNotes or pass == passCmd1:
of "on": if pass == passCmd1: incl(conf.cmdlineNotes, n)
if state in {wWarningAsError, wHintAsError}: incl(conf.modifiedyNotes, n)
incl(conf.warningAsErrors, n) # xxx rename warningAsErrors to noteAsErrors if state in {wWarningAsError, wHintAsError}:
else: conf.warningAsErrors[n] = isOn # xxx rename warningAsErrors to noteAsErrors
incl(conf.notes, n) else:
incl(conf.mainPackageNotes, n) conf.notes[n] = isOn
of "off": conf.mainPackageNotes[n] = isOn
if state in {wWarningAsError, wHintAsError}: if not isOn: excl(conf.foreignPackageNotes, n)
excl(conf.warningAsErrors, n)
else:
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
excl(conf.foreignPackageNotes, n)
proc processCompile(conf: ConfigRef; filename: string) = proc processCompile(conf: ConfigRef; filename: string) =
var found = findFile(conf, filename) var found = findFile(conf, filename)

View file

@ -134,5 +134,5 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasUnifiedTuple") defineSymbol("nimHasUnifiedTuple")
defineSymbol("nimHasIterable") defineSymbol("nimHasIterable")
defineSymbol("nimHasTypeofVoid") defineSymbol("nimHasTypeofVoid")
defineSymbol("nimHasDragonBox") defineSymbol("nimHasDragonBox")
defineSymbol("nimHasHintAll")

View file

@ -48,14 +48,15 @@ Advanced options:
--spellSuggest|:num show at most `num >= 0` spelling suggestions on typos. --spellSuggest|:num show at most `num >= 0` spelling suggestions on typos.
if `num` is not specified (or `auto`), return if `num` is not specified (or `auto`), return
an implementation defined set of suggestions. an implementation defined set of suggestions.
-w:on|off|list, --warnings:on|off|list --hints:on|off|list. `on|off` enables or disables hints.
turn all warnings on|off or list all available `list` reports which hints are selected.
--warning:X:on|off turn specific warning X on|off. --hint:X:on|off turn specific hint X on|off. `hint:X` means `hint:X:on`,
`warning:X` means `warning:X:on`, as with similar flags. as with similar flags. `all` can be used for "all hints".
--hints:on|off|list turn all hints on|off or list all available
--hint:X:on|off turn specific hint X on|off.
--warningAsError:X:on|off turn specific warning X into an error on|off
--hintAsError:X:on|off turn specific hint X into an error on|off --hintAsError:X:on|off turn specific hint X into an error on|off
-w:on|off|list, --warnings:on|off|list
same as `--hints` but for warnings.
--warning:X:on|off ditto
--warningAsError:X:on|off ditto
--styleCheck:off|hint|error --styleCheck:off|hint|error
produce hints or errors for Nim identifiers that produce hints or errors for Nim identifiers that
do not adhere to Nim's official style guide do not adhere to Nim's official style guide

View file

@ -23,9 +23,6 @@ proc isDots(a: string): bool =
a.startsWith(".") and a.strip(chars = {'.'}) == "" a.startsWith(".") and a.strip(chars = {'.'}) == ""
const const
defaultHintsOff = "--hint:successx:off --hint:exec:off --hint:link:off --hint:cc:off --hint:conf:off --hint:processing:off --hint:QuitCalled:off"
# useful when you want to turn only some hints on, and some common ones off.
# pending https://github.com/timotheecour/Nim/issues/453, simplify to: `--hints:off`
nim = getCurrentCompilerExe() nim = getCurrentCompilerExe()
mode = querySetting(backend) mode = querySetting(backend)
nimcache = buildDir / "nimcacheTrunner" nimcache = buildDir / "nimcacheTrunner"
@ -236,7 +233,7 @@ sub/mmain.idx""", context
check execCmdEx(cmd) == ("witness\n", 0) check execCmdEx(cmd) == ("witness\n", 0)
block: # config.nims, nim.cfg, hintConf, bug #16557 block: # config.nims, nim.cfg, hintConf, bug #16557
let cmd = fmt"{nim} r {defaultHintsOff} --hint:conf tests/newconfig/bar/mfoo.nim" let cmd = fmt"{nim} r --hint:all:off --hint:conf tests/newconfig/bar/mfoo.nim"
let (outp, exitCode) = execCmdEx(cmd, options = {poStdErrToStdOut}) let (outp, exitCode) = execCmdEx(cmd, options = {poStdErrToStdOut})
doAssert exitCode == 0 doAssert exitCode == 0
let dir = getCurrentDir() let dir = getCurrentDir()
@ -268,7 +265,7 @@ tests/newconfig/bar/mfoo.nims""".splitLines
check fmt"""{nim} r -b:js {opt} --eval:"echo defined(js)"""".execCmdEx == ("true\n", 0) check fmt"""{nim} r -b:js {opt} --eval:"echo defined(js)"""".execCmdEx == ("true\n", 0)
block: # `hintProcessing` dots should not interfere with `static: echo` + friends block: # `hintProcessing` dots should not interfere with `static: echo` + friends
let cmd = fmt"""{nim} r {defaultHintsOff} --hint:processing -f --eval:"static: echo 1+1"""" let cmd = fmt"""{nim} r --hint:all:off --hint:processing -f --eval:"static: echo 1+1""""
let (outp, exitCode) = execCmdEx(cmd, options = {poStdErrToStdOut}) let (outp, exitCode) = execCmdEx(cmd, options = {poStdErrToStdOut})
template check3(cond) = doAssert cond, $(outp,) template check3(cond) = doAssert cond, $(outp,)
doAssert exitCode == 0 doAssert exitCode == 0
@ -282,7 +279,7 @@ tests/newconfig/bar/mfoo.nims""".splitLines
check3 "2" in outp check3 "2" in outp
block: # nim secret block: # nim secret
let opt = fmt"{defaultHintsOff} --hint:processing" let opt = "--hint:all:off --hint:processing"
template check3(cond) = doAssert cond, $(outp,) template check3(cond) = doAssert cond, $(outp,)
for extra in ["", "--stdout"]: for extra in ["", "--stdout"]:
let cmd = fmt"""{nim} secret {opt} {extra}""" let cmd = fmt"""{nim} secret {opt} {extra}"""