From 7d5e6b0169fb83c7682bfad5d675c21db785c324 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Sun, 20 Jun 2021 10:52:22 -0700 Subject: [PATCH] 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 --- changelog.md | 4 +++ compiler/commands.nim | 59 +++++++++++++++++++++--------------------- compiler/condsyms.nim | 2 +- doc/advopt.txt | 15 ++++++----- tests/misc/trunner.nim | 9 +++---- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/changelog.md b/changelog.md index 5af195e599..570aff5422 100644 --- a/changelog.md +++ b/changelog.md @@ -429,6 +429,10 @@ - `--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` instead of `$nimcache/projectName.json`. This allows avoiding recompiling a given project compiled with different options if the output file differs. diff --git a/compiler/commands.nim b/compiler/commands.nim index 8f8df71a78..4c1db8ead0 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -25,10 +25,10 @@ bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep") bootSwitch(usedGoGC, defined(gogc), "--gc:go") bootSwitch(usedNoGC, defined(nogc), "--gc:none") +import std/[setutils, os, strutils, parseutils, parseopt, sequtils, strtabs] import - os, msgs, options, nversion, condsyms, strutils, extccomp, platform, - wordrecg, parseutils, nimblecmd, parseopt, sequtils, lineinfos, - pathutils, strtabs, pathnorm + msgs, options, nversion, condsyms, extccomp, platform, + wordrecg, nimblecmd, lineinfos, pathutils, pathnorm from ast import eqTypeFlags, tfGcSafe, tfNoSideEffect @@ -182,7 +182,7 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass, info: TLineInfo; orig: string; conf: ConfigRef) = var id = "" # arg = key or [key] or key:val or [key]:val; with val=on|off var i = 0 - var n = hintMin + var notes: set[TMsgKind] var isBracket = false if i < arg.len and arg[i] == '[': isBracket = true @@ -197,37 +197,36 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass, if i == arg.len: discard elif i < arg.len and (arg[i] in {':', '='}): inc(i) 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 if val == "": val = "on" 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) - elif n notin conf.cmdlineNotes or pass == passCmd1: - if pass == passCmd1: incl(conf.cmdlineNotes, n) - incl(conf.modifiedyNotes, n) - case val - of "on": - if state in {wWarningAsError, wHintAsError}: - incl(conf.warningAsErrors, n) # xxx rename warningAsErrors to noteAsErrors - else: - incl(conf.notes, n) - incl(conf.mainPackageNotes, n) - of "off": - if state in {wWarningAsError, wHintAsError}: - excl(conf.warningAsErrors, n) - else: - excl(conf.notes, n) - excl(conf.mainPackageNotes, n) - excl(conf.foreignPackageNotes, n) + else: + let isOn = val == "on" + for n in notes: + if n notin conf.cmdlineNotes or pass == passCmd1: + if pass == passCmd1: incl(conf.cmdlineNotes, n) + incl(conf.modifiedyNotes, n) + if state in {wWarningAsError, wHintAsError}: + conf.warningAsErrors[n] = isOn # xxx rename warningAsErrors to noteAsErrors + else: + conf.notes[n] = isOn + conf.mainPackageNotes[n] = isOn + if not isOn: excl(conf.foreignPackageNotes, n) proc processCompile(conf: ConfigRef; filename: string) = var found = findFile(conf, filename) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index ff0c603cb3..b3f8465f01 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -134,5 +134,5 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimHasUnifiedTuple") defineSymbol("nimHasIterable") defineSymbol("nimHasTypeofVoid") - defineSymbol("nimHasDragonBox") + defineSymbol("nimHasHintAll") diff --git a/doc/advopt.txt b/doc/advopt.txt index e5b4c95686..b56649a864 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -48,14 +48,15 @@ Advanced options: --spellSuggest|:num show at most `num >= 0` spelling suggestions on typos. if `num` is not specified (or `auto`), return an implementation defined set of suggestions. - -w:on|off|list, --warnings:on|off|list - turn all warnings on|off or list all available - --warning:X:on|off turn specific warning X on|off. - `warning:X` means `warning:X:on`, as with similar flags. - --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 + --hints:on|off|list. `on|off` enables or disables hints. + `list` reports which hints are selected. + --hint:X:on|off turn specific hint X on|off. `hint:X` means `hint:X:on`, + as with similar flags. `all` can be used for "all hints". --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 produce hints or errors for Nim identifiers that do not adhere to Nim's official style guide diff --git a/tests/misc/trunner.nim b/tests/misc/trunner.nim index f2ea1d040d..77ae10f3de 100644 --- a/tests/misc/trunner.nim +++ b/tests/misc/trunner.nim @@ -23,9 +23,6 @@ proc isDots(a: string): bool = a.startsWith(".") and a.strip(chars = {'.'}) == "" 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() mode = querySetting(backend) nimcache = buildDir / "nimcacheTrunner" @@ -236,7 +233,7 @@ sub/mmain.idx""", context check execCmdEx(cmd) == ("witness\n", 0) 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}) doAssert exitCode == 0 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) 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}) template check3(cond) = doAssert cond, $(outp,) doAssert exitCode == 0 @@ -282,7 +279,7 @@ tests/newconfig/bar/mfoo.nims""".splitLines check3 "2" in outp block: # nim secret - let opt = fmt"{defaultHintsOff} --hint:processing" + let opt = "--hint:all:off --hint:processing" template check3(cond) = doAssert cond, $(outp,) for extra in ["", "--stdout"]: let cmd = fmt"""{nim} secret {opt} {extra}"""