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:
parent
8e46e787f6
commit
8463973f91
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
src/main.d
11
src/main.d
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue