Nim style checker: document the switch; fixes #9564
This commit is contained in:
parent
5c25b93898
commit
e844e536bf
6 changed files with 36 additions and 16 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue