implements a --nep1:on switch to make the compiler enforce the naming conventions outlined in NEP-1

This commit is contained in:
Andreas Rumpf
2018-06-13 01:44:19 +02:00
parent f555338ce8
commit 5348fef003
13 changed files with 58 additions and 46 deletions

View File

@@ -717,6 +717,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
doAssert(conf != nil)
incl(conf.features, destructor)
defineSymbol(conf.symbols, "nimNewRuntime")
of "nep1":
processOnOffSwitchG(conf, {optCheckNep1}, arg, pass, info)
of "cppcompiletonamespace":
expectNoArg(conf, switch, arg, pass, info)
incl conf.globalOptions, optUseNimNamespace

View File

@@ -13,9 +13,18 @@
import
strutils, os, intsets, strtabs
import ".." / [options, ast, astalgo, msgs, semdata, ropes, idents,
lineinfos]
import prettybase
import options, ast, astalgo, msgs, semdata, ropes, idents,
lineinfos
const
Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
proc identLen*(line: string, start: int): int =
while start+result < line.len and line[start+result] in Letters:
inc result
when false:
import prettybase
type
StyleCheck* {.pure.} = enum None, Warn, Auto
@@ -93,12 +102,16 @@ proc beautifyName(s: string, k: TSymKind): string =
result.add s[i]
inc i
proc differ*(line: string, a, b: int, x: string): bool =
let y = line[a..b]
result = cmpIgnoreStyle(y, x) == 0 and y != x
proc replaceInFile(conf: ConfigRef; info: TLineInfo; newName: string) =
let line = conf.m.fileInfos[info.fileIndex.int].lines[info.line.int-1]
var first = min(info.col.int, line.len)
if first < 0: return
#inc first, skipIgnoreCase(line, "proc ", first)
while first > 0 and line[first-1] in prettybase.Letters: dec first
while first > 0 and line[first-1] in Letters: dec first
if first < 0: return
if line[first] == '`': inc first
@@ -120,27 +133,37 @@ proc checkStyle(conf: ConfigRef; cache: IdentCache; info: TLineInfo, s: string,
proc styleCheckDefImpl(conf: ConfigRef; cache: IdentCache; info: TLineInfo; s: PSym; k: TSymKind) =
# operators stay as they are:
if k in {skResult, skTemp} or s.name.s[0] notin prettybase.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 {sfImportc, sfExportc} * s.flags == {} or gCheckExtern:
checkStyle(conf, cache, info, s.name.s, k, s)
template styleCheckDef*(info: TLineInfo; s: PSym; k: TSymKind) =
proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
# operators stay as they are:
if k in {skResult, skTemp} or s.name.s[0] notin Letters: return
if k in {skType, skGenericParam} and sfAnon in s.flags: return
let beau = beautifyName(s.name.s, k)
if s.name.s != beau:
message(conf, info, hintName, beau)
template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
if optCheckNep1 in conf.globalOptions:
nep1CheckDefImpl(conf, info, s, k)
when defined(nimfix):
if gStyleCheck != StyleCheck.None: styleCheckDefImpl(conf, cache, info, s, k)
template styleCheckDef*(info: TLineInfo; s: PSym) =
styleCheckDef(info, s, s.kind)
template styleCheckDef*(s: PSym) =
styleCheckDef(s.info, s, s.kind)
template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym) =
styleCheckDef(conf, info, s, s.kind)
template styleCheckDef*(conf: ConfigRef; s: PSym) =
styleCheckDef(conf, s.info, s, s.kind)
proc styleCheckUseImpl(conf: ConfigRef; cache: IdentCache; info: TLineInfo; s: PSym) =
proc styleCheckUseImpl(conf: ConfigRef; info: TLineInfo; s: PSym) =
if info.fileIndex.int < 0: return
# we simply convert it to what it looks like in the definition
# for consistency
# operators stay as they are:
if s.kind in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters:
if s.kind in {skResult, skTemp} or s.name.s[0] notin Letters:
return
if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return
let newName = s.name.s
@@ -150,4 +173,4 @@ proc styleCheckUseImpl(conf: ConfigRef; cache: IdentCache; info: TLineInfo; s: P
template styleCheckUse*(info: TLineInfo; s: PSym) =
when defined(nimfix):
if gStyleCheck != StyleCheck.None: styleCheckUseImpl(conf, cache, info, s)
if gStyleCheck != StyleCheck.None: styleCheckUseImpl(conf, info, s)

View File

@@ -11,7 +11,7 @@
import strutils, os, parseopt
import compiler/[options, commands, modules, sem,
passes, passaux, nimfix/pretty,
passes, passaux, linter,
msgs, nimconf,
extccomp, condsyms,
modulegraphs, idents]

View File

@@ -7,21 +7,11 @@
# distribution, for details about the copyright.
#
import strutils, lexbase, streams
import ".." / [ast, msgs, lineinfos, idents, options]
import strutils except Letters
import lexbase, streams
import ".." / [ast, msgs, lineinfos, idents, options, linter]
from os import splitFile
const
Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
proc identLen*(line: string, start: int): int =
while start+result < line.len and line[start+result] in Letters:
inc result
proc differ*(line: string, a, b: int, x: string): bool =
let y = line[a..b]
result = cmpIgnoreStyle(y, x) == 0 and y != x
proc replaceDeprecated*(conf: ConfigRef; info: TLineInfo; oldSym, newSym: PIdent) =
let line = sourceLine(conf, info)
var first = min(info.col.int, line.len)

View File

@@ -54,7 +54,7 @@ type # please make sure we have under 32 options
optGenScript, # generate a script file to compile the *.c files
optGenMapping, # generate a mapping file
optRun, # run the compiled project
optCaasEnabled # compiler-as-a-service is running
optCheckNep1, # check that the names adhere to NEP-1
optSkipConfigFile, # skip the general config file
optSkipProjConfigFile, # skip the project's config file
optSkipUserConfigFile, # skip the users's config file
@@ -372,7 +372,6 @@ proc usesNativeGC*(conf: ConfigRef): bool {.inline.} = conf.selectedGC >= gcRefc
template compilationCachePresent*(conf: ConfigRef): untyped =
conf.symbolFiles in {v2Sf, writeOnlySf}
# {optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
template optPreserveOrigSource*(conf: ConfigRef): untyped =
optEmbedOrigSrc in conf.globalOptions

View File

@@ -15,7 +15,7 @@ import
magicsys, parser, nversion, nimsets, semfold, modulepaths, importer,
procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch,
intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
evaltempl, patterns, parampatterns, sempass2, nimfix.pretty, semmacrosanity,
evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
semparallel, lowerings, pluginsupport, plugins.active, rod, lineinfos
from modulegraphs import ModuleGraph

View File

@@ -2161,7 +2161,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
addDecl(c, labl)
n.sons[0] = newSymNode(labl, n.sons[0].info)
suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym)
styleCheckDef(labl)
styleCheckDef(c.config, labl)
n.sons[1] = semExpr(c, n.sons[1])
n.typ = n.sons[1].typ
if isEmptyType(n.typ): n.kind = nkBlockStmt

View File

@@ -160,7 +160,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
proc addTempDecl(c: PContext; n: PNode; kind: TSymKind) =
let s = newSymS(skUnknown, getIdentNode(c, n), c)
addPrelimDecl(c, s)
styleCheckDef(n.info, s, kind)
styleCheckDef(c.config, n.info, s, kind)
proc semGenericStmt(c: PContext, n: PNode,
flags: TSemGenericFlags, ctx: var GenericCtx): PNode =

View File

@@ -364,7 +364,7 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
if result.owner.kind == skModule:
incl(result.flags, sfGlobal)
suggestSym(c.config, n.info, result, c.graph.usageSym)
styleCheckDef(result)
styleCheckDef(c.config, result)
proc checkNilable(c: PContext; v: PSym) =
if {sfGlobal, sfImportC} * v.flags == {sfGlobal} and
@@ -627,7 +627,7 @@ proc addForVarDecl(c: PContext, v: PSym) =
proc symForVar(c: PContext, n: PNode): PSym =
let m = if n.kind == nkPragmaExpr: n.sons[0] else: n
result = newSymG(skForVar, m, c)
styleCheckDef(result)
styleCheckDef(c.config, result)
proc semForVars(c: PContext, n: PNode): PNode =
result = n

View File

@@ -213,7 +213,7 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
else:
let local = newGenSym(k, ident, c)
addPrelimDecl(c.c, local)
styleCheckDef(n.info, local)
styleCheckDef(c.c.config, n.info, local)
replaceIdentBySym(c.c, n, newSymNode(local, n.info))
else:
replaceIdentBySym(c.c, n, ident)
@@ -260,7 +260,7 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
var s = newGenSym(k, ident, c)
s.ast = n
addPrelimDecl(c.c, s)
styleCheckDef(n.info, s)
styleCheckDef(c.c.config, n.info, s)
n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
else:
n.sons[namePos] = ident
@@ -382,7 +382,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
# labels are always 'gensym'ed:
let s = newGenSym(skLabel, n.sons[0], c)
addPrelimDecl(c.c, s)
styleCheckDef(s)
styleCheckDef(c.c.config, s)
n.sons[0] = newSymNode(s, n.sons[0].info)
n.sons[1] = semTemplBody(c, n.sons[1])
closeScope(c)
@@ -551,7 +551,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
incl(s.flags, sfGlobal)
else:
s = semIdentVis(c, skTemplate, n.sons[0], {})
styleCheckDef(s)
styleCheckDef(c.config, s)
# check parameter list:
#s.scope = c.currentScope
pushOwner(c, s)

View File

@@ -114,8 +114,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
incl(e.flags, sfExported)
if not isPure: strTableAdd(c.module.tab, e)
addSon(result.n, newSymNode(e))
let conf = c.config
styleCheckDef(e)
styleCheckDef(c.config, e)
if sfGenSym notin e.flags:
if not isPure: addDecl(c, e)
else: importPureEnumField(c, e)
@@ -451,7 +450,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
else:
addSon(result.n, newSymNode(field))
addSonSkipIntLit(result, typ)
if c.config.cmd == cmdPretty: styleCheckDef(a.sons[j].info, field)
styleCheckDef(c.config, a.sons[j].info, field)
if result.n.len == 0: result.n = nil
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
@@ -491,7 +490,7 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
else: discard
else:
result = semIdentVis(c, kind, n, allowed)
if c.config.cmd == cmdPretty: styleCheckDef(n.info, result)
styleCheckDef(c.config, n.info, result)
proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
let ex = t[branchIndex][currentEx].skipConv
@@ -685,7 +684,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
localError(c.config, n.sons[i].info, "attempt to redefine: '" & f.name.s & "'")
if a.kind == nkEmpty: addSon(father, newSymNode(f))
else: addSon(a, newSymNode(f))
styleCheckDef(f)
styleCheckDef(c.config, f)
if a.kind != nkEmpty: addSon(father, a)
of nkSym:
# This branch only valid during generic object
@@ -1062,7 +1061,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
addSon(result.n, newSymNode(arg))
rawAddSon(result, finalType)
addParamOrResult(c, arg, kind)
if c.config.cmd == cmdPretty: styleCheckDef(a.sons[j].info, arg)
styleCheckDef(c.config, a.sons[j].info, arg)
var r: PType
if n.sons[0].kind != nkEmpty:

View File

@@ -13,7 +13,7 @@
import
intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees,
nimfix / pretty, lineinfos
linter, lineinfos
when defined(booting) or defined(nimsuggest):
import docgen

View File

@@ -493,7 +493,6 @@ proc mainCommand(graph: ModuleGraph) =
registerPass graph, verbosePass
registerPass graph, semPass
conf.cmd = cmdIdeTools
incl conf.globalOptions, optCaasEnabled
wantMainModule(conf)
if not fileExists(conf.projectFull):