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
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) doAssert(conf != nil)
incl(conf.features, destructor) incl(conf.features, destructor)
defineSymbol(conf.symbols, "nimNewRuntime") defineSymbol(conf.symbols, "nimNewRuntime")
of "nep1":
processOnOffSwitchG(conf, {optCheckNep1}, arg, pass, info)
of "cppcompiletonamespace": of "cppcompiletonamespace":
expectNoArg(conf, switch, arg, pass, info) expectNoArg(conf, switch, arg, pass, info)
incl conf.globalOptions, optUseNimNamespace incl conf.globalOptions, optUseNimNamespace

View file

@ -13,8 +13,17 @@
import import
strutils, os, intsets, strtabs strutils, os, intsets, strtabs
import ".." / [options, ast, astalgo, msgs, semdata, ropes, idents, import options, ast, astalgo, msgs, semdata, ropes, idents,
lineinfos] 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 import prettybase
type type
@ -93,12 +102,16 @@ proc beautifyName(s: string, k: TSymKind): string =
result.add s[i] result.add s[i]
inc 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) = proc replaceInFile(conf: ConfigRef; info: TLineInfo; newName: string) =
let line = conf.m.fileInfos[info.fileIndex.int].lines[info.line.int-1] let line = conf.m.fileInfos[info.fileIndex.int].lines[info.line.int-1]
var first = min(info.col.int, line.len) var first = min(info.col.int, line.len)
if first < 0: return if first < 0: return
#inc first, skipIgnoreCase(line, "proc ", first) #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 first < 0: return
if line[first] == '`': inc first 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) = proc styleCheckDefImpl(conf: ConfigRef; cache: IdentCache; 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 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 k in {skType, skGenericParam} and sfAnon in s.flags: return
if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern: if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern:
checkStyle(conf, cache, info, s.name.s, k, s) 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): when defined(nimfix):
if gStyleCheck != StyleCheck.None: styleCheckDefImpl(conf, cache, info, s, k) if gStyleCheck != StyleCheck.None: styleCheckDefImpl(conf, cache, info, s, k)
template styleCheckDef*(info: TLineInfo; s: PSym) = template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym) =
styleCheckDef(info, s, s.kind) styleCheckDef(conf, info, s, s.kind)
template styleCheckDef*(s: PSym) = template styleCheckDef*(conf: ConfigRef; s: PSym) =
styleCheckDef(s.info, s, s.kind) 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 if info.fileIndex.int < 0: return
# we simply convert it to what it looks like in the definition # we simply convert it to what it looks like in the definition
# for consistency # for consistency
# operators stay as they are: # 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 return
if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return
let newName = s.name.s 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) = template styleCheckUse*(info: TLineInfo; s: PSym) =
when defined(nimfix): 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 strutils, os, parseopt
import compiler/[options, commands, modules, sem, import compiler/[options, commands, modules, sem,
passes, passaux, nimfix/pretty, passes, passaux, linter,
msgs, nimconf, msgs, nimconf,
extccomp, condsyms, extccomp, condsyms,
modulegraphs, idents] modulegraphs, idents]

View file

@ -7,21 +7,11 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
import strutils, lexbase, streams import strutils except Letters
import ".." / [ast, msgs, lineinfos, idents, options] import lexbase, streams
import ".." / [ast, msgs, lineinfos, idents, options, linter]
from os import splitFile 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) = proc replaceDeprecated*(conf: ConfigRef; info: TLineInfo; oldSym, newSym: PIdent) =
let line = sourceLine(conf, info) let line = sourceLine(conf, info)
var first = min(info.col.int, line.len) 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 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
optCaasEnabled # compiler-as-a-service is running optCheckNep1, # check that the names adhere to NEP-1
optSkipConfigFile, # skip the general config file optSkipConfigFile, # skip the general config file
optSkipProjConfigFile, # skip the project's config file optSkipProjConfigFile, # skip the project's config file
optSkipUserConfigFile, # skip the users'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 = template compilationCachePresent*(conf: ConfigRef): untyped =
conf.symbolFiles in {v2Sf, writeOnlySf} conf.symbolFiles in {v2Sf, writeOnlySf}
# {optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
template optPreserveOrigSource*(conf: ConfigRef): untyped = template optPreserveOrigSource*(conf: ConfigRef): untyped =
optEmbedOrigSrc in conf.globalOptions optEmbedOrigSrc in conf.globalOptions

View file

@ -15,7 +15,7 @@ import
magicsys, parser, nversion, nimsets, semfold, modulepaths, importer, magicsys, parser, nversion, nimsets, semfold, modulepaths, importer,
procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch, procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch,
intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting, 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 semparallel, lowerings, pluginsupport, plugins.active, rod, lineinfos
from modulegraphs import ModuleGraph from modulegraphs import ModuleGraph

View file

@ -2161,7 +2161,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
addDecl(c, labl) addDecl(c, labl)
n.sons[0] = newSymNode(labl, n.sons[0].info) n.sons[0] = newSymNode(labl, n.sons[0].info)
suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym) 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.sons[1] = semExpr(c, n.sons[1])
n.typ = n.sons[1].typ n.typ = n.sons[1].typ
if isEmptyType(n.typ): n.kind = nkBlockStmt 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) = proc addTempDecl(c: PContext; n: PNode; kind: TSymKind) =
let s = newSymS(skUnknown, getIdentNode(c, n), c) let s = newSymS(skUnknown, getIdentNode(c, n), c)
addPrelimDecl(c, s) addPrelimDecl(c, s)
styleCheckDef(n.info, s, kind) styleCheckDef(c.config, n.info, s, kind)
proc semGenericStmt(c: PContext, n: PNode, proc semGenericStmt(c: PContext, n: PNode,
flags: TSemGenericFlags, ctx: var GenericCtx): 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: 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(result) 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
@ -627,7 +627,7 @@ proc addForVarDecl(c: PContext, v: PSym) =
proc symForVar(c: PContext, n: PNode): PSym = proc symForVar(c: PContext, n: PNode): PSym =
let m = if n.kind == nkPragmaExpr: n.sons[0] else: n let m = if n.kind == nkPragmaExpr: n.sons[0] else: n
result = newSymG(skForVar, m, c) result = newSymG(skForVar, m, c)
styleCheckDef(result) styleCheckDef(c.config, result)
proc semForVars(c: PContext, n: PNode): PNode = proc semForVars(c: PContext, n: PNode): PNode =
result = n result = n

View file

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

View file

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

View file

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

View file

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