mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-06 04:57:49 +00:00
added missing nimfix files
This commit is contained in:
106
compiler/nimfix/nimfix.nim
Normal file
106
compiler/nimfix/nimfix.nim
Normal file
@@ -0,0 +1,106 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2014 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Nimfix is a tool that helps to convert old-style Nimrod code to Nim code.
|
||||
|
||||
import strutils, os, parseopt
|
||||
import options, commands, modules, sem, passes, passaux, pretty, msgs, nimconf,
|
||||
extccomp, condsyms, lists
|
||||
|
||||
const Usage = """
|
||||
Nimfix - Tool to patch Nim code
|
||||
Usage:
|
||||
nimfix [options] projectflie.nim
|
||||
|
||||
Options:
|
||||
--overwriteFiles:on|off overwrite the original nim files.
|
||||
DEFAULT is ON!
|
||||
--wholeProject overwrite every processed file.
|
||||
--checkExtern:on|off style check also extern names
|
||||
--styleCheck:on|off|auto performs style checking for identifiers
|
||||
and suggests an alternative spelling;
|
||||
'auto' corrects the spelling.
|
||||
|
||||
In addition, all command line options of Nim are supported.
|
||||
"""
|
||||
|
||||
proc mainCommand =
|
||||
#msgs.gErrorMax = high(int) # do not stop after first error
|
||||
registerPass verbosePass
|
||||
registerPass semPass
|
||||
gCmd = cmdPretty
|
||||
appendStr(searchPaths, options.libpath)
|
||||
if gProjectFull.len != 0:
|
||||
# current path is always looked first for modules
|
||||
prependStr(searchPaths, gProjectPath)
|
||||
|
||||
compileProject()
|
||||
pretty.overwriteFiles()
|
||||
|
||||
proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
|
||||
var p = parseopt.initOptParser(cmd)
|
||||
var argsCount = 0
|
||||
gOnlyMainfile = true
|
||||
while true:
|
||||
parseopt.next(p)
|
||||
case p.kind
|
||||
of cmdEnd: break
|
||||
of cmdLongoption, cmdShortOption:
|
||||
case p.key.normalize
|
||||
of "overwritefiles":
|
||||
case p.val.normalize
|
||||
of "on": gOverWrite = true
|
||||
of "off": gOverWrite = false
|
||||
else: localError(gCmdLineInfo, errOnOrOffExpected)
|
||||
of "checkextern":
|
||||
case p.val.normalize
|
||||
of "on": gCheckExtern = true
|
||||
of "off": gCheckExtern = false
|
||||
else: localError(gCmdLineInfo, errOnOrOffExpected)
|
||||
of "stylecheck":
|
||||
case p.val.normalize
|
||||
of "off": gStyleCheck = StyleCheck.None
|
||||
of "on": gStyleCheck = StyleCheck.Warn
|
||||
of "auto": gStyleCheck = StyleCheck.Auto
|
||||
else: localError(gCmdLineInfo, errOnOrOffExpected)
|
||||
of "wholeproject": gOnlyMainfile = false
|
||||
else:
|
||||
processSwitch(pass, p)
|
||||
of cmdArgument:
|
||||
options.gProjectName = unixToNativePath(p.key)
|
||||
# if processArgument(pass, p, argsCount): break
|
||||
|
||||
proc handleCmdLine() =
|
||||
if paramCount() == 0:
|
||||
stdout.writeln(Usage)
|
||||
else:
|
||||
processCmdLine(passCmd1, "")
|
||||
if gProjectName != "":
|
||||
try:
|
||||
gProjectFull = canonicalizePath(gProjectName)
|
||||
except OSError:
|
||||
gProjectFull = gProjectName
|
||||
var p = splitFile(gProjectFull)
|
||||
gProjectPath = p.dir
|
||||
gProjectName = p.name
|
||||
else:
|
||||
gProjectPath = getCurrentDir()
|
||||
loadConfigs(DefaultConfig) # load all config files
|
||||
# now process command line arguments again, because some options in the
|
||||
# command line can overwite the config file's settings
|
||||
extccomp.initVars()
|
||||
processCmdLine(passCmd2, "")
|
||||
mainCommand()
|
||||
|
||||
when compileOption("gc", "v2") or compileOption("gc", "refc"):
|
||||
GC_disableMarkAndSweep()
|
||||
|
||||
condsyms.initDefines()
|
||||
defineSymbol "nimfix"
|
||||
handleCmdline()
|
||||
17
compiler/nimfix/nimfix.nim.cfg
Normal file
17
compiler/nimfix/nimfix.nim.cfg
Normal file
@@ -0,0 +1,17 @@
|
||||
# Special configuration file for the Nim project
|
||||
# gc:markAndSweep
|
||||
|
||||
hint[XDeclaredButNotUsed]:off
|
||||
path:"$projectPath/../.."
|
||||
|
||||
path:"$lib/packages/docutils"
|
||||
path:"$nim/compiler"
|
||||
|
||||
define:useStdoutAsStdmsg
|
||||
symbol:nimfix
|
||||
define:nimfix
|
||||
|
||||
cs:partial
|
||||
#define:useNodeIds
|
||||
define:booting
|
||||
define:noDocgen
|
||||
152
compiler/nimfix/pretty.nim
Normal file
152
compiler/nimfix/pretty.nim
Normal file
@@ -0,0 +1,152 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2014 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements the code "prettifier". This is part of the toolchain
|
||||
## to convert Nim code into a consistent style.
|
||||
|
||||
import
|
||||
strutils, os, options, ast, astalgo, msgs, ropes, idents,
|
||||
intsets, strtabs, semdata, prettybase
|
||||
|
||||
type
|
||||
StyleCheck* {.pure.} = enum None, Warn, Auto
|
||||
|
||||
var
|
||||
gOverWrite* = true
|
||||
gStyleCheck*: StyleCheck
|
||||
gCheckExtern*, gOnlyMainfile*: bool
|
||||
|
||||
proc overwriteFiles*() =
|
||||
let doStrip = options.getConfigVar("pretty.strip").normalize == "on"
|
||||
for i in 0 .. high(gSourceFiles):
|
||||
if gSourceFiles[i].dirty and not gSourceFiles[i].isNimfixFile and
|
||||
(not gOnlyMainfile or gSourceFiles[i].fileIdx == gProjectMainIdx):
|
||||
let newFile = if gOverWrite: gSourceFiles[i].fullpath
|
||||
else: gSourceFiles[i].fullpath.changeFileExt(".pretty.nim")
|
||||
try:
|
||||
var f = open(newFile, fmWrite)
|
||||
for line in gSourceFiles[i].lines:
|
||||
if doStrip:
|
||||
f.write line.strip(leading = false, trailing = true)
|
||||
else:
|
||||
f.write line
|
||||
f.write(gSourceFiles[i].newline)
|
||||
f.close
|
||||
except IOError:
|
||||
rawMessage(errCannotOpenFile, newFile)
|
||||
|
||||
proc `=~`(s: string, a: openArray[string]): bool =
|
||||
for x in a:
|
||||
if s.startsWith(x): return true
|
||||
|
||||
proc beautifyName(s: string, k: TSymKind): string =
|
||||
# minimal set of rules here for transition:
|
||||
# GC_ is allowed
|
||||
|
||||
let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'})
|
||||
if allUpper and k in {skConst, skEnumField, skType}: return s
|
||||
result = newStringOfCap(s.len)
|
||||
var i = 0
|
||||
case k
|
||||
of skType, skGenericParam:
|
||||
# Types should start with a capital unless builtins like 'int' etc.:
|
||||
if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string",
|
||||
"char", "byte", "bool", "openArray", "seq", "array", "void",
|
||||
"pointer", "float", "csize", "cdouble", "cchar", "cschar",
|
||||
"cshort", "cu", "nil", "expr", "stmt", "typedesc", "auto", "any",
|
||||
"range", "openarray", "varargs", "set", "cfloat"
|
||||
]:
|
||||
result.add s[i]
|
||||
else:
|
||||
result.add toUpper(s[i])
|
||||
of skConst, skEnumField:
|
||||
# for 'const' we keep how it's spelt; either upper case or lower case:
|
||||
result.add s[0]
|
||||
else:
|
||||
# as a special rule, don't transform 'L' to 'l'
|
||||
if s.len == 1 and s[0] == 'L': result.add 'L'
|
||||
elif '_' in s: result.add(s[i])
|
||||
else: result.add toLower(s[0])
|
||||
inc i
|
||||
while i < s.len:
|
||||
if s[i] == '_':
|
||||
if i > 0 and s[i-1] in {'A'..'Z'}:
|
||||
# don't skip '_' as it's essential for e.g. 'GC_disable'
|
||||
result.add('_')
|
||||
inc i
|
||||
result.add s[i]
|
||||
else:
|
||||
inc i
|
||||
result.add toUpper(s[i])
|
||||
elif allUpper:
|
||||
result.add toLower(s[i])
|
||||
else:
|
||||
result.add s[i]
|
||||
inc i
|
||||
|
||||
proc replaceInFile(info: TLineInfo; newName: string) =
|
||||
loadFile(info)
|
||||
|
||||
let line = gSourceFiles[info.fileIndex].lines[info.line-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
|
||||
if first < 0: return
|
||||
if line[first] == '`': inc first
|
||||
|
||||
let last = first+identLen(line, first)-1
|
||||
if differ(line, first, last, newName):
|
||||
# last-first+1 != newName.len or
|
||||
var x = line.substr(0, first-1) & newName & line.substr(last+1)
|
||||
system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
|
||||
gSourceFiles[info.fileIndex].dirty = true
|
||||
|
||||
proc checkStyle(info: TLineInfo, s: string, k: TSymKind; sym: PSym) =
|
||||
let beau = beautifyName(s, k)
|
||||
if s != beau:
|
||||
if gStyleCheck == StyleCheck.Auto:
|
||||
sym.name = getIdent(beau)
|
||||
replaceInFile(info, beau)
|
||||
else:
|
||||
message(info, hintName, beau)
|
||||
|
||||
proc styleCheckDefImpl(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 {skType, skGenericParam} and sfAnon in s.flags: return
|
||||
if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern:
|
||||
checkStyle(info, s.name.s, k, s)
|
||||
|
||||
template styleCheckDef*(info: TLineInfo; s: PSym; k: TSymKind) =
|
||||
when defined(nimfix):
|
||||
if gStyleCheck != StyleCheck.None: styleCheckDefImpl(info, s, k)
|
||||
|
||||
template styleCheckDef*(info: TLineInfo; s: PSym) =
|
||||
styleCheckDef(info, s, s.kind)
|
||||
template styleCheckDef*(s: PSym) =
|
||||
styleCheckDef(s.info, s, s.kind)
|
||||
|
||||
proc styleCheckUseImpl(info: TLineInfo; s: PSym) =
|
||||
if info.fileIndex < 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:
|
||||
return
|
||||
if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return
|
||||
let newName = s.name.s
|
||||
|
||||
replaceInFile(info, newName)
|
||||
#if newName == "File": writeStackTrace()
|
||||
|
||||
template styleCheckUse*(info: TLineInfo; s: PSym) =
|
||||
when defined(nimfix):
|
||||
if gStyleCheck != StyleCheck.None: styleCheckUseImpl(info, s)
|
||||
93
compiler/nimfix/prettybase.nim
Normal file
93
compiler/nimfix/prettybase.nim
Normal file
@@ -0,0 +1,93 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2014 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
import ast, msgs, strutils, idents, lexbase, streams
|
||||
from os import splitFile
|
||||
|
||||
type
|
||||
TSourceFile* = object
|
||||
lines*: seq[string]
|
||||
dirty*, isNimfixFile*: bool
|
||||
fullpath*, newline*: string
|
||||
fileIdx*: int32
|
||||
|
||||
var
|
||||
gSourceFiles*: seq[TSourceFile] = @[]
|
||||
|
||||
proc loadFile*(info: TLineInfo) =
|
||||
let i = info.fileIndex
|
||||
if i >= gSourceFiles.len:
|
||||
gSourceFiles.setLen(i+1)
|
||||
if gSourceFiles[i].lines.isNil:
|
||||
gSourceFiles[i].fileIdx = info.fileIndex
|
||||
gSourceFiles[i].lines = @[]
|
||||
let path = info.toFullPath
|
||||
gSourceFiles[i].fullpath = path
|
||||
gSourceFiles[i].isNimfixFile = path.splitFile.ext == ".nimfix"
|
||||
# we want to die here for IOError:
|
||||
for line in lines(path):
|
||||
gSourceFiles[i].lines.add(line)
|
||||
# extract line ending of the file:
|
||||
var lex: TBaseLexer
|
||||
open(lex, newFileStream(path, fmRead))
|
||||
var pos = lex.bufpos
|
||||
while true:
|
||||
case lex.buf[pos]
|
||||
of '\c':
|
||||
gSourceFiles[i].newline = "\c\L"
|
||||
break
|
||||
of '\L', '\0':
|
||||
gSourceFiles[i].newline = "\L"
|
||||
break
|
||||
else: discard
|
||||
inc pos
|
||||
close(lex)
|
||||
|
||||
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*(info: TLineInfo; oldSym, newSym: PIdent) =
|
||||
loadFile(info)
|
||||
|
||||
let line = gSourceFiles[info.fileIndex].lines[info.line-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 Letters: dec first
|
||||
if first < 0: return
|
||||
if line[first] == '`': inc first
|
||||
|
||||
let last = first+identLen(line, first)-1
|
||||
if cmpIgnoreStyle(line[first..last], oldSym.s) == 0:
|
||||
var x = line.substr(0, first-1) & newSym.s & line.substr(last+1)
|
||||
system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
|
||||
gSourceFiles[info.fileIndex].dirty = true
|
||||
#if newSym.s == "File": writeStackTrace()
|
||||
|
||||
proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) =
|
||||
replaceDeprecated(info, oldSym.name, newSym.name)
|
||||
|
||||
proc replaceComment*(info: TLineInfo) =
|
||||
loadFile(info)
|
||||
|
||||
let line = gSourceFiles[info.fileIndex].lines[info.line-1]
|
||||
var first = info.col.int
|
||||
if line[first] != '#': inc first
|
||||
|
||||
var x = line.substr(0, first-1) & "discard " & line.substr(first+1).escape
|
||||
system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
|
||||
gSourceFiles[info.fileIndex].dirty = true
|
||||
Reference in New Issue
Block a user