Allow customizing the style check messages' format (#567)

* Allow customizing the style check messages' format

Closes #377

* Allow other parts of the code to customize the error format
This commit is contained in:
Frank LENORMAND 2018-03-22 16:51:27 +00:00 committed by BBasile
parent 8e46e787f6
commit 8463973f91
3 changed files with 37 additions and 14 deletions

View File

@ -54,7 +54,7 @@ void assertAnalyzerWarnings(string code, const StaticAnalysisConfig config,
StringCache cache = StringCache(StringCache.defaultBucketCount); StringCache cache = StringCache(StringCache.defaultBucketCount);
RollbackAllocator r; RollbackAllocator r;
const(Token)[] tokens; const(Token)[] tokens;
const(Module) m = parseModule(file, cast(ubyte[]) code, &r, cache, false, tokens); const(Module) m = parseModule(file, cast(ubyte[]) code, &r, defaultErrorFormat, cache, false, tokens);
auto moduleCache = ModuleCache(new CAllocatorImpl!Mallocator); auto moduleCache = ModuleCache(new CAllocatorImpl!Mallocator);

View File

@ -87,9 +87,24 @@ bool first = true;
private alias ASTAllocator = CAllocatorImpl!( private alias ASTAllocator = CAllocatorImpl!(
AllocatorList!(n => Region!Mallocator(1024 * 128), Mallocator)); AllocatorList!(n => Region!Mallocator(1024 * 128), Mallocator));
immutable string defaultErrorFormat = "{filepath}({line}:{column})[{type}]: {message}";
void messageFunctionFormat(string format, string fileName, size_t line, size_t column, string message, bool isError)
{
auto s = format;
s = s.replace("{filepath}", fileName);
s = s.replace("{line}", to!string(line));
s = s.replace("{column}", to!string(column));
s = s.replace("{type}", isError ? "error" : "warn");
s = s.replace("{message}", message);
writefln("%s", s);
}
void messageFunction(string fileName, size_t line, size_t column, string message, bool isError) void messageFunction(string fileName, size_t line, size_t column, string message, bool isError)
{ {
writefln("%s(%d:%d)[%s]: %s", fileName, line, column, isError ? "error" : "warn", message); messageFunctionFormat(defaultErrorFormat, fileName, line, column, message, isError);
} }
void messageFunctionJSON(string fileName, size_t line, size_t column, string message, bool) void messageFunctionJSON(string fileName, size_t line, size_t column, string message, bool)
@ -112,10 +127,10 @@ void writeJSON(string key, string fileName, size_t line, size_t column, string m
write(" }"); write(" }");
} }
bool syntaxCheck(string[] fileNames, ref StringCache stringCache, ref ModuleCache moduleCache) bool syntaxCheck(string[] fileNames, string errorFormat, ref StringCache stringCache, ref ModuleCache moduleCache)
{ {
StaticAnalysisConfig config = defaultStaticAnalysisConfig(); StaticAnalysisConfig config = defaultStaticAnalysisConfig();
return analyze(fileNames, config, stringCache, moduleCache, false); return analyze(fileNames, config, errorFormat, stringCache, moduleCache, false);
} }
void generateReport(string[] fileNames, const StaticAnalysisConfig config, void generateReport(string[] fileNames, const StaticAnalysisConfig config,
@ -134,7 +149,7 @@ void generateReport(string[] fileNames, const StaticAnalysisConfig config,
continue; continue;
RollbackAllocator r; RollbackAllocator r;
const(Token)[] tokens; const(Token)[] tokens;
const Module m = parseModule(fileName, code, &r, cache, true, tokens, &lineOfCodeCount); const Module m = parseModule(fileName, code, &r, defaultErrorFormat, cache, true, tokens, &lineOfCodeCount);
stats.visit(m); stats.visit(m);
MessageSet results = analyze(fileName, m, config, moduleCache, tokens, true); MessageSet results = analyze(fileName, m, config, moduleCache, tokens, true);
foreach (result; results[]) foreach (result; results[])
@ -160,7 +175,7 @@ void generateReport(string[] fileNames, const StaticAnalysisConfig config,
* *
* Returns: true if there were errors or if there were warnings and `staticAnalyze` was true. * Returns: true if there were errors or if there were warnings and `staticAnalyze` was true.
*/ */
bool analyze(string[] fileNames, const StaticAnalysisConfig config, bool analyze(string[] fileNames, const StaticAnalysisConfig config, string errorFormat,
ref StringCache cache, ref ModuleCache moduleCache, bool staticAnalyze = true) ref StringCache cache, ref ModuleCache moduleCache, bool staticAnalyze = true)
{ {
bool hasErrors; bool hasErrors;
@ -174,7 +189,7 @@ bool analyze(string[] fileNames, const StaticAnalysisConfig config,
uint errorCount; uint errorCount;
uint warningCount; uint warningCount;
const(Token)[] tokens; const(Token)[] tokens;
const Module m = parseModule(fileName, code, &r, cache, false, tokens, const Module m = parseModule(fileName, code, &r, errorFormat, cache, false, tokens,
null, &errorCount, &warningCount); null, &errorCount, &warningCount);
assert(m); assert(m);
if (errorCount > 0 || (staticAnalyze && warningCount > 0)) if (errorCount > 0 || (staticAnalyze && warningCount > 0))
@ -185,19 +200,22 @@ bool analyze(string[] fileNames, const StaticAnalysisConfig config,
foreach (result; results[]) foreach (result; results[])
{ {
hasErrors = true; hasErrors = true;
writefln("%s(%d:%d)[warn]: %s", result.fileName, result.line, messageFunctionFormat(errorFormat, result.fileName, result.line, result.column, result.message, false);
result.column, result.message);
} }
} }
return hasErrors; return hasErrors;
} }
const(Module) parseModule(string fileName, ubyte[] code, RollbackAllocator* p, const(Module) parseModule(string fileName, ubyte[] code, RollbackAllocator* p,
ref StringCache cache, bool report, ref const(Token)[] tokens, string errorFormat, ref StringCache cache, bool report, ref const(Token)[] tokens,
ulong* linesOfCode = null, uint* errorCount = null, uint* warningCount = null) ulong* linesOfCode = null, uint* errorCount = null, uint* warningCount = null)
{ {
import stats : isLineOfCode; import stats : isLineOfCode;
auto writeMessages = delegate(string fileName, size_t line, size_t column, string message, bool isError){
return messageFunctionFormat(errorFormat, fileName, line, column, message, isError);
};
LexerConfig config; LexerConfig config;
config.fileName = fileName; config.fileName = fileName;
config.stringBehavior = StringBehavior.source; config.stringBehavior = StringBehavior.source;
@ -205,7 +223,7 @@ const(Module) parseModule(string fileName, ubyte[] code, RollbackAllocator* p,
if (linesOfCode !is null) if (linesOfCode !is null)
(*linesOfCode) += count!(a => isLineOfCode(a.type))(tokens); (*linesOfCode) += count!(a => isLineOfCode(a.type))(tokens);
return dparse.parser.parseModule(tokens, fileName, p, return dparse.parser.parseModule(tokens, fileName, p,
report ? toDelegate(&messageFunctionJSON) : toDelegate(&messageFunction), report ? toDelegate(&messageFunctionJSON) : writeMessages,
errorCount, warningCount); errorCount, warningCount);
} }

View File

@ -67,6 +67,7 @@ else
string[] importPaths; string[] importPaths;
bool printVersion; bool printVersion;
bool explore; bool explore;
string errorFormat;
try try
{ {
@ -94,7 +95,8 @@ else
"version", &printVersion, "version", &printVersion,
"muffinButton", &muffin, "muffinButton", &muffin,
"explore", &explore, "explore", &explore,
"skipTests", &skipTests); "skipTests", &skipTests,
"errorFormat|f", &errorFormat);
//dfmt on //dfmt on
} }
catch (ConvException e) catch (ConvException e)
@ -141,6 +143,9 @@ else
return 0; return 0;
} }
if (!errorFormat.length)
errorFormat = defaultErrorFormat;
const(string[]) absImportPaths = importPaths.map!(a => a.absolutePath() const(string[]) absImportPaths = importPaths.map!(a => a.absolutePath()
.buildNormalizedPath()).array(); .buildNormalizedPath()).array();
@ -234,11 +239,11 @@ else
if (report) if (report)
generateReport(expandArgs(args), config, cache, moduleCache); generateReport(expandArgs(args), config, cache, moduleCache);
else else
return analyze(expandArgs(args), config, cache, moduleCache, true) ? 1 : 0; return analyze(expandArgs(args), config, errorFormat, cache, moduleCache, true) ? 1 : 0;
} }
else if (syntaxCheck) else if (syntaxCheck)
{ {
return .syntaxCheck(usingStdin ? ["stdin"] : expandArgs(args), cache, moduleCache) ? 1 : 0; return .syntaxCheck(usingStdin ? ["stdin"] : expandArgs(args), errorFormat, cache, moduleCache) ? 1 : 0;
} }
else else
{ {