Nim style checker: document the switch; fixes #9564

This commit is contained in:
Araq 2018-10-30 15:03:19 +01:00
commit e844e536bf
6 changed files with 36 additions and 16 deletions

View file

@ -115,6 +115,7 @@ const
errInvalidCmdLineOption = "invalid command line option: '$1'" errInvalidCmdLineOption = "invalid command line option: '$1'"
errOnOrOffExpectedButXFound = "'on' or 'off' expected, but '$1' found" errOnOrOffExpectedButXFound = "'on' or 'off' expected, but '$1' found"
errOnOffOrListExpectedButXFound = "'on', 'off' or 'list' expected, but '$1' found" errOnOffOrListExpectedButXFound = "'on', 'off' or 'list' expected, but '$1' found"
errOffHintsError = "'off', 'hint' or 'error' expected, but '$1' found"
proc invalidCmdLineOption(conf: ConfigRef; pass: TCmdLinePass, switch: string, info: TLineInfo) = proc invalidCmdLineOption(conf: ConfigRef; pass: TCmdLinePass, switch: string, info: TLineInfo) =
if switch == " ": localError(conf, info, errInvalidCmdLineOption % "-") if switch == " ": localError(conf, info, errInvalidCmdLineOption % "-")
@ -732,8 +733,12 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
doAssert(conf != nil) doAssert(conf != nil)
incl(conf.features, destructor) incl(conf.features, destructor)
defineSymbol(conf.symbols, "nimNewRuntime") defineSymbol(conf.symbols, "nimNewRuntime")
of "nep1": of "stylecheck":
processOnOffSwitchG(conf, {optCheckNep1}, arg, pass, info) case arg.normalize
of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError}
of "hint": conf.globalOptions = conf.globalOptions + {optStyleHint}
of "error": conf.globalOptions = conf.globalOptions + {optStyleError}
else: localError(conf, info, errOffHintsError % arg)
of "cppcompiletonamespace": of "cppcompiletonamespace":
if arg.len > 0: if arg.len > 0:
conf.cppCustomNamespace = arg conf.cppCustomNamespace = arg

View file

@ -7,8 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## This module implements the code "prettifier". This is part of the toolchain ## This module implements the style checker.
## to convert Nim code into a consistent style.
import import
strutils, os, intsets, strtabs strutils, os, intsets, strtabs
@ -23,9 +22,6 @@ proc identLen*(line: string, start: int): int =
while start+result < line.len and line[start+result] in Letters: while start+result < line.len and line[start+result] in Letters:
inc result inc result
when false:
import prettybase
type type
StyleCheck* {.pure.} = enum None, Warn, Auto StyleCheck* {.pure.} = enum None, Warn, Auto
@ -71,9 +67,9 @@ proc beautifyName(s: string, k: TSymKind): string =
if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string", if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string",
"char", "byte", "bool", "openArray", "seq", "array", "void", "char", "byte", "bool", "openArray", "seq", "array", "void",
"pointer", "float", "csize", "cdouble", "cchar", "cschar", "pointer", "float", "csize", "cdouble", "cchar", "cschar",
"cshort", "cu", "nil", "expr", "stmt", "typedesc", "auto", "any", "cshort", "cu", "nil", "typedesc", "auto", "any",
"range", "openarray", "varargs", "set", "cfloat" "range", "openarray", "varargs", "set", "cfloat", "ref", "ptr",
]: "untyped", "typed", "static", "sink", "lent", "type"]:
result.add s[i] result.add s[i]
else: else:
result.add toUpperAscii(s[i]) result.add toUpperAscii(s[i])
@ -122,6 +118,12 @@ proc replaceInFile(conf: ConfigRef; info: TLineInfo; newName: string) =
system.shallowCopy(conf.m.fileInfos[info.fileIndex.int].lines[info.line.int-1], x) system.shallowCopy(conf.m.fileInfos[info.fileIndex.int].lines[info.line.int-1], x)
conf.m.fileInfos[info.fileIndex.int].dirty = true conf.m.fileInfos[info.fileIndex.int].dirty = true
proc lintReport(conf: ConfigRef; info: TLineInfo, beau: string) =
if optStyleError in conf.globalOptions:
localError(conf, info, "name should be: '$1'" % beau)
else:
message(conf, info, hintName, beau)
proc checkStyle(conf: ConfigRef; cache: IdentCache; info: TLineInfo, s: string, k: TSymKind; sym: PSym) = proc checkStyle(conf: ConfigRef; cache: IdentCache; info: TLineInfo, s: string, k: TSymKind; sym: PSym) =
let beau = beautifyName(s, k) let beau = beautifyName(s, k)
if s != beau: if s != beau:
@ -129,7 +131,7 @@ proc checkStyle(conf: ConfigRef; cache: IdentCache; info: TLineInfo, s: string,
sym.name = getIdent(cache, beau) sym.name = getIdent(cache, beau)
replaceInFile(conf, info, beau) replaceInFile(conf, info, beau)
else: else:
message(conf, info, hintName, beau) lintReport(conf, info, beau)
proc styleCheckDefImpl(conf: ConfigRef; cache: IdentCache; info: TLineInfo; s: PSym; k: TSymKind) = proc styleCheckDefImpl(conf: ConfigRef; cache: IdentCache; info: TLineInfo; s: PSym; k: TSymKind) =
# operators stay as they are: # operators stay as they are:
@ -142,12 +144,14 @@ proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
# operators stay as they are: # operators stay as they are:
if k in {skResult, skTemp} or s.name.s[0] notin Letters: return if k in {skResult, skTemp} or s.name.s[0] notin Letters: return
if k in {skType, skGenericParam} and sfAnon in s.flags: return if k in {skType, skGenericParam} and sfAnon in s.flags: return
if s.typ != nil and s.typ.kind == tyTypeDesc: return
if {sfImportc, sfExportc} * s.flags != {}: return
let beau = beautifyName(s.name.s, k) let beau = beautifyName(s.name.s, k)
if s.name.s != beau: if s.name.s != beau:
message(conf, info, hintName, beau) lintReport(conf, info, beau)
template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) = template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
if optCheckNep1 in conf.globalOptions: if {optStyleHint, optStyleError} * conf.globalOptions != {}:
nep1CheckDefImpl(conf, info, s, k) nep1CheckDefImpl(conf, info, s, k)
when defined(nimfix): when defined(nimfix):
if gStyleCheck != StyleCheck.None: styleCheckDefImpl(conf, cache, info, s, k) if gStyleCheck != StyleCheck.None: styleCheckDefImpl(conf, cache, info, s, k)

View file

@ -54,7 +54,8 @@ type # please make sure we have under 32 options
optGenScript, # generate a script file to compile the *.c files optGenScript, # generate a script file to compile the *.c files
optGenMapping, # generate a mapping file optGenMapping, # generate a mapping file
optRun, # run the compiled project optRun, # run the compiled project
optCheckNep1, # check that the names adhere to NEP-1 optStyleHint, # check that the names adhere to NEP-1
optStyleError, # enforce that the names adhere to NEP-1
optSkipSystemConfigFile, # skip the system's cfg/nims config file optSkipSystemConfigFile, # skip the system's cfg/nims config file
optSkipProjConfigFile, # skip the project's cfg/nims config file optSkipProjConfigFile, # skip the project's cfg/nims config file
optSkipUserConfigFile, # skip the users's cfg/nims config file optSkipUserConfigFile, # skip the users's cfg/nims config file

View file

@ -318,7 +318,6 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
if result.owner.kind == skModule: if result.owner.kind == skModule:
incl(result.flags, sfGlobal) incl(result.flags, sfGlobal)
suggestSym(c.config, n.info, result, c.graph.usageSym) suggestSym(c.config, n.info, result, c.graph.usageSym)
styleCheckDef(c.config, result)
proc checkNilable(c: PContext; v: PSym) = proc checkNilable(c: PContext; v: PSym) =
if {sfGlobal, sfImportC} * v.flags == {sfGlobal} and if {sfGlobal, sfImportC} * v.flags == {sfGlobal} and
@ -359,6 +358,7 @@ proc semUsing(c: PContext; n: PNode): PNode =
let typ = semTypeNode(c, a.sons[length-2], nil) let typ = semTypeNode(c, a.sons[length-2], nil)
for j in countup(0, length-3): for j in countup(0, length-3):
let v = semIdentDef(c, a.sons[j], skParam) let v = semIdentDef(c, a.sons[j], skParam)
styleCheckDef(c.config, v)
v.typ = typ v.typ = typ
strTableIncl(c.signatures, v) strTableIncl(c.signatures, v)
else: else:
@ -489,6 +489,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
addToVarSection(c, result, n, a) addToVarSection(c, result, n, a)
continue continue
var v = semIdentDef(c, a.sons[j], symkind) var v = semIdentDef(c, a.sons[j], symkind)
styleCheckDef(c.config, v)
if sfGenSym notin v.flags and not isDiscardUnderscore(v): if sfGenSym notin v.flags and not isDiscardUnderscore(v):
addInterfaceDecl(c, v) addInterfaceDecl(c, v)
when oKeepVariableNames: when oKeepVariableNames:
@ -542,6 +543,7 @@ proc semConst(c: PContext, n: PNode): PNode =
if a.kind != nkConstDef: illFormedAst(a, c.config) if a.kind != nkConstDef: illFormedAst(a, c.config)
checkSonsLen(a, 3, c.config) checkSonsLen(a, 3, c.config)
var v = semIdentDef(c, a.sons[0], skConst) var v = semIdentDef(c, a.sons[0], skConst)
styleCheckDef(c.config, v)
var typ: PType = nil var typ: PType = nil
if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil) if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
@ -873,6 +875,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
let typsym = pkg.tab.strTableGet(typName) let typsym = pkg.tab.strTableGet(typName)
if typsym.isNil: if typsym.isNil:
s = semIdentDef(c, name[1], skType) s = semIdentDef(c, name[1], skType)
styleCheckDef(c.config, s)
s.typ = newTypeS(tyObject, c) s.typ = newTypeS(tyObject, c)
s.typ.sym = s s.typ.sym = s
s.flags.incl sfForward s.flags.incl sfForward
@ -886,6 +889,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
s = typsym s = typsym
else: else:
s = semIdentDef(c, name, skType) s = semIdentDef(c, name, skType)
styleCheckDef(c.config, s)
s.typ = newTypeS(tyForward, c) s.typ = newTypeS(tyForward, c)
s.typ.sym = s # process pragmas: s.typ.sym = s # process pragmas:
if name.kind == nkPragmaExpr: if name.kind == nkPragmaExpr:
@ -1616,6 +1620,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
pragma(c, s, n.sons[pragmasPos], validPragmas) pragma(c, s, n.sons[pragmasPos], validPragmas)
else: else:
implicitPragmas(c, s, n, validPragmas) implicitPragmas(c, s, n, validPragmas)
styleCheckDef(c.config, s)
else: else:
if n.sons[pragmasPos].kind != nkEmpty: if n.sons[pragmasPos].kind != nkEmpty:
pragma(c, s, n.sons[pragmasPos], validPragmas) pragma(c, s, n.sons[pragmasPos], validPragmas)
@ -1628,6 +1633,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if proto.typ.callConv != s.typ.callConv or proto.typ.flags < s.typ.flags: if proto.typ.callConv != s.typ.callConv or proto.typ.flags < s.typ.flags:
localError(c.config, n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProcX % localError(c.config, n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProcX %
("'" & proto.name.s & "' from " & c.config$proto.info)) ("'" & proto.name.s & "' from " & c.config$proto.info))
styleCheckDef(c.config, s)
if sfForward notin proto.flags and proto.magic == mNone: if sfForward notin proto.flags and proto.magic == mNone:
wrongRedefinition(c, n.info, proto.name.s, proto.info) wrongRedefinition(c, n.info, proto.name.s, proto.info)
excl(proto.flags, sfForward) excl(proto.flags, sfForward)

View file

@ -505,7 +505,6 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
else: discard else: discard
else: else:
result = semIdentVis(c, kind, n, allowed) result = semIdentVis(c, kind, n, allowed)
styleCheckDef(c.config, n.info, result)
proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) = proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
let ex = t[branchIndex][currentEx].skipConv let ex = t[branchIndex][currentEx].skipConv
@ -689,6 +688,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
else: rectype.sym else: rectype.sym
for i in countup(0, sonsLen(n)-3): for i in countup(0, sonsLen(n)-3):
var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported}) var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
styleCheckDef(c.config, n.sons[i].info, f)
suggestSym(c.config, n.sons[i].info, f, c.graph.usageSym) suggestSym(c.config, n.sons[i].info, f, c.graph.usageSym)
f.typ = typ f.typ = typ
f.position = pos f.position = pos

View file

@ -25,6 +25,10 @@ Advanced options:
--warning[X]:on|off turn specific warning X on|off --warning[X]:on|off turn specific warning X on|off
--hints:on|off|list turn all hints on|off or list all available --hints:on|off|list turn all hints on|off or list all available
--hint[X]:on|off turn specific hint X on|off --hint[X]:on|off turn specific hint X on|off
--styleCheck:off|hint|error
produce hints or errors for Nim identifiers that
do not adhere to Nim's official style guide
https://nim-lang.org/docs/nep1.html
--lib:PATH set the system library path --lib:PATH set the system library path
--import:PATH add an automatically imported module --import:PATH add an automatically imported module
--include:PATH add an automatically included module --include:PATH add an automatically included module