Added basic style checker

This commit is contained in:
Hackerpilot 2014-01-12 15:39:45 +00:00
parent 070f9ac83b
commit 22ca0cd284
3 changed files with 110 additions and 2 deletions

View File

@ -8,6 +8,7 @@ dmd\
astprinter.d\
formatter.d\
outliner.d\
style.d\
stdx/*.d\
stdx/d/*.d\
datapicked/dpick/buffer/*.d\

15
main.d
View File

@ -25,6 +25,7 @@ import ctags;
import astprinter;
import imports;
import outliner;
import style;
int main(string[] args)
{
@ -41,6 +42,7 @@ int main(string[] args)
bool muffin;
bool outline;
bool tokenDump;
bool styleCheck;
try
{
@ -48,7 +50,8 @@ int main(string[] args)
"ctags|c", &ctags, "recursive|r|R", &recursive, "help|h", &help,
"tokenCount|t", &tokenCount, "syntaxCheck|s", &syntaxCheck,
"ast|xml", &ast, "imports|i", &imports, "outline|o", &outline,
"tokenDump", &tokenDump, "muffinButton", &muffin);
"tokenDump", &tokenDump, "styleCheck", &styleCheck,
"muffinButton", &muffin);
}
catch (Exception e)
{
@ -77,7 +80,7 @@ int main(string[] args)
}
auto optionCount = count!"a"([sloc, highlight, ctags, tokenCount,
syntaxCheck, ast, imports, outline, tokenDump]);
syntaxCheck, ast, imports, outline, tokenDump, styleCheck]);
if (optionCount > 1)
{
stderr.writeln("Too many options specified");
@ -112,6 +115,10 @@ int main(string[] args)
{
stdout.printCtags(expandArgs(args, recursive));
}
else if (styleCheck)
{
stdout.styleCheck(expandArgs(args, recursive));
}
else
{
bool usingStdin = args.length == 1;
@ -251,6 +258,10 @@ options:
syntax errors to stdout. One error or warning is printed per line.
If no files are specified, input is read from stdin.
--styleCheck [sourceFiles]
Lexes and parses sourceFiles, printing the line and column number of any
style guideline violations to stdout.
--ctags | -c sourceFile
Generates ctags information from the given source code file. Note that
ctags information requires a filename, so stdin cannot be used in place

96
style.d Normal file
View File

@ -0,0 +1,96 @@
// Copyright Brian Schott (Sir Alaran) 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module style;
import stdx.d.ast;
import stdx.d.lexer;
import stdx.d.parser;
import std.stdio;
import std.regex;
import std.array;
import std.conv;
void doNothing(string, size_t, size_t, string) {}
void styleCheck(File output, string[] fileNames)
{
foreach (fileName; fileNames)
{
File f = File(fileName);
auto bytes = uninitializedArray!(ubyte[])(to!size_t(f.size));
f.rawRead(bytes);
auto tokens = byToken(bytes);
Module m = parseModule(tokens.array, fileName, &doNothing);
auto checker = new StyleChecker;
checker.fileName = fileName;
checker.visit(m);
}
}
class StyleChecker : ASTVisitor
{
enum varFunNameRegex = `^([\p{Ll}_][_\w\d]*|[\p{Lu}_]+)$`;
enum aggregateNameRegex = `^\p{Lu}[\w\d]*$`;
enum moduleNameRegex = `^\p{Ll}+$`;
override void visit(ModuleDeclaration dec)
{
foreach (part; dec.moduleName.identifiers)
{
if (part.text.matchFirst(moduleNameRegex).length == 0)
writeln(fileName, "(", part.line, ":", part.column, ") ",
"Module/package name ", part.text, " does not match style guidelines");
}
}
override void visit(Declarator dec)
{
checkLowercaseName("Variable", dec.name);
}
override void visit(FunctionDeclaration dec)
{
checkLowercaseName("Function", dec.name);
}
void checkLowercaseName(string type, ref Token name)
{
if (name.text.matchFirst(varFunNameRegex).length == 0)
writeln(fileName, "(", name.line, ":", name.column, ") ",
type, " name ", name.text, " does not match style guidelines");
}
override void visit(ClassDeclaration dec)
{
checkAggregateName("Class", dec.name);
dec.accept(this);
}
override void visit(EnumDeclaration dec)
{
if (dec.name.text is null || dec.name.text.length == 0)
return;
checkAggregateName("Enum", dec.name);
dec.accept(this);
}
override void visit(StructDeclaration dec)
{
checkAggregateName("Struct", dec.name);
dec.accept(this);
}
void checkAggregateName(string aggregateType, ref Token name)
{
if (name.text.matchFirst(aggregateNameRegex).length == 0)
writeln(fileName, "(", name.line, ":", name.column, ") ",
aggregateType, " name ", name.text,
" does not match style guidelines");
}
alias ASTVisitor.visit visit;
string fileName;
}