assert_without_msg: Check for std.exception.enforce
This commit is contained in:
parent
5ba4a7bffa
commit
8304e8540c
|
@ -10,6 +10,7 @@ import dparse.lexer;
|
||||||
import dparse.ast;
|
import dparse.ast;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
import std.algorithm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that all asserts have an explanatory message.
|
* Check that all asserts have an explanatory message.
|
||||||
|
@ -31,8 +32,60 @@ class AssertWithoutMessageCheck : BaseAnalyzer
|
||||||
addErrorMessage(expr.line, expr.column, KEY, MESSAGE);
|
addErrorMessage(expr.line, expr.column, KEY, MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override void visit(const FunctionCallExpression expr)
|
||||||
|
{
|
||||||
|
if (!isStdExceptionImported)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (expr.unaryExpression !is null &&
|
||||||
|
expr.unaryExpression.primaryExpression !is null &&
|
||||||
|
expr.unaryExpression.primaryExpression.identifierOrTemplateInstance !is null)
|
||||||
|
{
|
||||||
|
auto ident = expr.unaryExpression.primaryExpression.identifierOrTemplateInstance.identifier;
|
||||||
|
if (ident.text == "enforce" && expr.arguments !is null && expr.arguments.argumentList !is null &&
|
||||||
|
expr.arguments.argumentList.items.length < 2)
|
||||||
|
addErrorMessage(ident.line, ident.column, KEY, MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(const SingleImport sImport)
|
||||||
|
{
|
||||||
|
static immutable stdException = ["std", "exception"];
|
||||||
|
if (sImport.identifierChain.identifiers.map!(a => a.text).equal(stdException))
|
||||||
|
isStdExceptionImported = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// revert the stack after new scopes
|
||||||
|
override void visit(const Declaration decl)
|
||||||
|
{
|
||||||
|
// be careful - ImportDeclarations don't introduce a new scope
|
||||||
|
if (decl.importDeclaration is null)
|
||||||
|
{
|
||||||
|
bool tmp = isStdExceptionImported;
|
||||||
|
scope(exit) isStdExceptionImported = tmp;
|
||||||
|
decl.accept(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
decl.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin ScopedVisit!IfStatement;
|
||||||
|
mixin ScopedVisit!BlockStatement;
|
||||||
|
|
||||||
alias visit = BaseAnalyzer.visit;
|
alias visit = BaseAnalyzer.visit;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStdExceptionImported;
|
||||||
|
|
||||||
|
template ScopedVisit(NodeType)
|
||||||
|
{
|
||||||
|
override void visit(const NodeType n)
|
||||||
|
{
|
||||||
|
bool tmp = isStdExceptionImported;
|
||||||
|
scope(exit) isStdExceptionImported = tmp;
|
||||||
|
n.accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
|
@ -63,6 +116,40 @@ unittest
|
||||||
AssertWithoutMessageCheck.MESSAGE,
|
AssertWithoutMessageCheck.MESSAGE,
|
||||||
), sac);
|
), sac);
|
||||||
|
|
||||||
|
// check for std.exception.enforce
|
||||||
|
assertAnalyzerWarnings(q{
|
||||||
|
unittest {
|
||||||
|
enforce(0); // std.exception not imported yet - could be a user-defined symbol
|
||||||
|
import std.exception;
|
||||||
|
enforce(0, "foo bar");
|
||||||
|
enforce(0); // [warn]: %s
|
||||||
|
}
|
||||||
|
}c.format(
|
||||||
|
AssertWithoutMessageCheck.MESSAGE,
|
||||||
|
), sac);
|
||||||
|
|
||||||
|
// check for std.exception.enforce
|
||||||
|
assertAnalyzerWarnings(q{
|
||||||
|
unittest {
|
||||||
|
import exception;
|
||||||
|
class C {
|
||||||
|
import std.exception;
|
||||||
|
}
|
||||||
|
enforce(0); // std.exception not imported yet - could be a user-defined symbol
|
||||||
|
struct S {
|
||||||
|
import std.exception;
|
||||||
|
}
|
||||||
|
enforce(0); // std.exception not imported yet - could be a user-defined symbol
|
||||||
|
if (false) {
|
||||||
|
import std.exception;
|
||||||
|
}
|
||||||
|
enforce(0); // std.exception not imported yet - could be a user-defined symbol
|
||||||
|
{
|
||||||
|
import std.exception;
|
||||||
|
}
|
||||||
|
enforce(0); // std.exception not imported yet - could be a user-defined symbol
|
||||||
|
}
|
||||||
|
}c, sac);
|
||||||
|
|
||||||
stderr.writeln("Unittest for AssertWithoutMessageCheck passed.");
|
stderr.writeln("Unittest for AssertWithoutMessageCheck passed.");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue