Replace libdparse with DMD in AllManCheck (#125)
* Replace libdparse with DMD in AllManCheck * Test assertAnalyzerDmd without writing to file * Revert "Test assertAnalyzerDmd without writing to file" This reverts commit 9f50f38a11d97df960c05d5a128059b13e7dcab4. * Fix windows ci bug --------- Co-authored-by: Eduard Staniloiu <edi33416@gmail.com>
This commit is contained in:
parent
2f46a0021c
commit
d99ada2581
|
|
@ -4,13 +4,10 @@
|
|||
|
||||
module dscanner.analysis.allman;
|
||||
|
||||
import dparse.lexer;
|
||||
import dparse.ast;
|
||||
import dscanner.analysis.base;
|
||||
import dsymbol.scope_ : Scope;
|
||||
|
||||
import std.algorithm;
|
||||
import std.range;
|
||||
import dmd.tokens : Token, TOK;
|
||||
import std.algorithm : canFind, until;
|
||||
import std.range : retro;
|
||||
|
||||
/**
|
||||
Checks for the allman style (braces should be on their own line)
|
||||
|
|
@ -25,50 +22,85 @@ if (param < 0)
|
|||
}
|
||||
------------
|
||||
*/
|
||||
final class AllManCheck : BaseAnalyzer
|
||||
extern (C++) class AllManCheck : BaseAnalyzerDmd
|
||||
{
|
||||
mixin AnalyzerInfo!"allman_braces_check";
|
||||
|
||||
///
|
||||
this(BaseAnalyzerArguments args)
|
||||
private enum string KEY = "dscanner.style.allman";
|
||||
private enum string MESSAGE = "Braces should be on their own line";
|
||||
|
||||
private Token[] tokens;
|
||||
|
||||
extern (D) this(string fileName, bool skipTests = false)
|
||||
{
|
||||
super(args);
|
||||
foreach (i; 1 .. tokens.length - 1)
|
||||
{
|
||||
const curLine = tokens[i].line;
|
||||
const prevTokenLine = tokens[i-1].line;
|
||||
if (tokens[i].type == tok!"{" && curLine == prevTokenLine)
|
||||
{
|
||||
// ignore struct initialization
|
||||
if (tokens[i-1].type == tok!"=")
|
||||
continue;
|
||||
// ignore duplicate braces
|
||||
if (tokens[i-1].type == tok!"{" && tokens[i - 2].line != curLine)
|
||||
continue;
|
||||
// ignore inline { } braces
|
||||
if (curLine != tokens[i + 1].line)
|
||||
addErrorMessage(tokens[i], KEY, MESSAGE);
|
||||
}
|
||||
if (tokens[i].type == tok!"}" && curLine == prevTokenLine)
|
||||
{
|
||||
// ignore duplicate braces
|
||||
if (tokens[i-1].type == tok!"}" && tokens[i - 2].line != curLine)
|
||||
continue;
|
||||
// ignore inline { } braces
|
||||
if (!tokens[0 .. i].retro.until!(t => t.line != curLine).canFind!(t => t.type == tok!"{"))
|
||||
addErrorMessage(tokens[i], KEY, MESSAGE);
|
||||
}
|
||||
}
|
||||
super(fileName, skipTests);
|
||||
lexFile();
|
||||
checkBraces();
|
||||
}
|
||||
|
||||
enum string KEY = "dscanner.style.allman";
|
||||
enum string MESSAGE = "Braces should be on their own line";
|
||||
private void lexFile()
|
||||
{
|
||||
import dscanner.utils : readFile;
|
||||
import dmd.errorsink : ErrorSinkNull;
|
||||
import dmd.globals : global;
|
||||
import dmd.lexer : Lexer;
|
||||
|
||||
auto bytes = readFile(fileName) ~ '\0';
|
||||
|
||||
__gshared ErrorSinkNull errorSinkNull;
|
||||
if (!errorSinkNull)
|
||||
errorSinkNull = new ErrorSinkNull;
|
||||
|
||||
scope lexer = new Lexer(null, cast(char*) bytes, 0, bytes.length, 0, 0, errorSinkNull, &global.compileEnv);
|
||||
|
||||
do
|
||||
{
|
||||
lexer.nextToken();
|
||||
tokens ~= lexer.token;
|
||||
}
|
||||
while (lexer.token.value != TOK.endOfFile);
|
||||
}
|
||||
|
||||
private void checkBraces()
|
||||
{
|
||||
foreach (i; 1 .. tokens.length - 1)
|
||||
{
|
||||
const curLine = tokens[i].loc.linnum;
|
||||
const prevTokenLine = tokens[i - 1].loc.linnum;
|
||||
|
||||
if (tokens[i].value == TOK.leftCurly && curLine == prevTokenLine)
|
||||
{
|
||||
// ignore struct initialization
|
||||
if (tokens[i - 1].value == TOK.assign)
|
||||
continue;
|
||||
|
||||
// ignore duplicate braces
|
||||
if (tokens[i - 1].value == TOK.leftCurly && tokens[i - 2].loc.linnum != curLine)
|
||||
continue;
|
||||
|
||||
// ignore inline { } braces
|
||||
if (curLine != tokens[i + 1].loc.linnum)
|
||||
addErrorMessage(cast(ulong) tokens[i].loc.linnum, cast(ulong) tokens[i].loc.charnum, KEY, MESSAGE);
|
||||
}
|
||||
|
||||
if (tokens[i].value == TOK.rightCurly && curLine == prevTokenLine)
|
||||
{
|
||||
// ignore duplicate braces
|
||||
if (tokens[i-1].value == TOK.rightCurly && tokens[i - 2].loc.linnum != curLine)
|
||||
continue;
|
||||
|
||||
// ignore inline { } braces
|
||||
if (!tokens[0 .. i].retro.until!(t => t.loc.linnum != curLine).canFind!(t => t.value == TOK.leftCurly))
|
||||
addErrorMessage(cast(ulong) tokens[i].loc.linnum, cast(ulong) tokens[i].loc.charnum, KEY, MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
|
||||
import dscanner.analysis.helpers : assertAnalyzerWarnings;
|
||||
import dscanner.analysis.helpers : assertAnalyzerWarningsDMD;
|
||||
import std.format : format;
|
||||
import std.stdio : stderr;
|
||||
|
||||
|
|
@ -76,11 +108,10 @@ unittest
|
|||
sac.allman_braces_check = Check.enabled;
|
||||
|
||||
// check common allman style violation
|
||||
assertAnalyzerWarnings(q{
|
||||
assertAnalyzerWarningsDMD(`
|
||||
void testAllman()
|
||||
{
|
||||
while (true) { /+
|
||||
^ [warn]: %s +/
|
||||
while (true) { // [warn]: %s
|
||||
auto f = 1;
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +146,7 @@ unittest
|
|||
}
|
||||
}
|
||||
}
|
||||
}c.format(
|
||||
`c.format(
|
||||
AllManCheck.MESSAGE,
|
||||
AllManCheck.MESSAGE,
|
||||
AllManCheck.MESSAGE,
|
||||
|
|
@ -128,7 +159,7 @@ unittest
|
|||
), sac);
|
||||
|
||||
// check struct initialization
|
||||
assertAnalyzerWarnings(q{
|
||||
assertAnalyzerWarningsDMD(q{
|
||||
unittest
|
||||
{
|
||||
struct Foo { int a; }
|
||||
|
|
@ -139,12 +170,11 @@ unittest
|
|||
}, sac);
|
||||
|
||||
// allow duplicate braces
|
||||
assertAnalyzerWarnings(q{
|
||||
assertAnalyzerWarningsDMD(q{
|
||||
unittest
|
||||
{{
|
||||
}}
|
||||
}, sac);
|
||||
|
||||
|
||||
stderr.writeln("Unittest for Allman passed.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ import dscanner.analysis.properly_documented_public_functions;
|
|||
import dscanner.analysis.final_attribute;
|
||||
import dscanner.analysis.vcall_in_ctor;
|
||||
import dscanner.analysis.useless_initializer;
|
||||
import dscanner.analysis.allman;
|
||||
import dscanner.analysis.always_curly;
|
||||
import dscanner.analysis.redundant_attributes;
|
||||
import dscanner.analysis.has_public_example;
|
||||
|
|
@ -668,10 +667,6 @@ BaseAnalyzer[] getAnalyzersForModuleAndConfig(string fileName,
|
|||
checks ~= new UndocumentedDeclarationCheck(args.setSkipTests(
|
||||
analysisConfig.undocumented_declaration_check == Check.skipTests && !ut));
|
||||
|
||||
if (moduleName.shouldRun!AllManCheck(analysisConfig))
|
||||
checks ~= new AllManCheck(args.setSkipTests(
|
||||
analysisConfig.allman_braces_check == Check.skipTests && !ut));
|
||||
|
||||
if (moduleName.shouldRun!IfConstraintsIndentCheck(analysisConfig))
|
||||
checks ~= new IfConstraintsIndentCheck(args.setSkipTests(
|
||||
analysisConfig.if_constraints_indent == Check.skipTests && !ut));
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import dscanner.analysis.unused_variable : UnusedVariableCheck;
|
|||
import dscanner.analysis.useless_assert : UselessAssertCheck;
|
||||
import dscanner.analysis.useless_initializer : UselessInitializerChecker;
|
||||
import dscanner.analysis.vcall_in_ctor : VcallCtorChecker;
|
||||
import dscanner.analysis.allman : AllManCheck;
|
||||
|
||||
version (unittest)
|
||||
enum ut = true;
|
||||
|
|
@ -318,6 +319,12 @@ MessageSet analyzeDmd(string fileName, ASTCodegen.Module m, const char[] moduleN
|
|||
config.vcall_in_ctor == Check.skipTests && !ut
|
||||
);
|
||||
|
||||
if (moduleName.shouldRunDmd!AllManCheck(config))
|
||||
visitors ~= new AllManCheck(
|
||||
fileName,
|
||||
config.allman_braces_check == Check.skipTests && !ut
|
||||
);
|
||||
|
||||
foreach (visitor; visitors)
|
||||
{
|
||||
m.accept(visitor);
|
||||
|
|
|
|||
Loading…
Reference in New Issue