Fix #262
This commit is contained in:
parent
cdc9d4d85c
commit
61770ee4c7
|
@ -104,4 +104,7 @@ struct StaticAnalysisConfig
|
|||
|
||||
@INI("Checks for assignment to auto-ref function parameters")
|
||||
bool auto_ref_assignment_check;
|
||||
|
||||
@INI("Checks for incorrect infinite range definitions")
|
||||
bool incorrect_infinite_range;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
// Copyright Brian Schott (Hackerpilot) 2015.
|
||||
// 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 analysis.incorrect_infinite_range;
|
||||
|
||||
import analysis.base;
|
||||
import analysis.helpers;
|
||||
import dparse.ast;
|
||||
import dparse.lexer;
|
||||
|
||||
/**
|
||||
* Checks for incorrect infinite range definitions
|
||||
*/
|
||||
class IncorrectInfiniteRangeCheck : BaseAnalyzer
|
||||
{
|
||||
alias visit = BaseAnalyzer.visit;
|
||||
|
||||
///
|
||||
this(string fileName)
|
||||
{
|
||||
super(fileName, null);
|
||||
}
|
||||
|
||||
override void visit(const StructBody structBody)
|
||||
{
|
||||
inStruct++;
|
||||
structBody.accept(this);
|
||||
inStruct--;
|
||||
}
|
||||
|
||||
override void visit(const FunctionDeclaration fd)
|
||||
{
|
||||
if (inStruct > 0 && fd.name.text == "empty")
|
||||
{
|
||||
line = fd.name.line;
|
||||
column = fd.name.column;
|
||||
fd.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
override void visit(const FunctionBody fb)
|
||||
{
|
||||
if (fb.bodyStatement !is null)
|
||||
visit(fb.bodyStatement.blockStatement);
|
||||
else
|
||||
visit(fb.blockStatement);
|
||||
}
|
||||
|
||||
override void visit(const BlockStatement bs)
|
||||
{
|
||||
if (bs.declarationsAndStatements is null)
|
||||
return;
|
||||
if (bs.declarationsAndStatements.declarationsAndStatements is null)
|
||||
return;
|
||||
if (bs.declarationsAndStatements.declarationsAndStatements.length != 1)
|
||||
return;
|
||||
visit(bs.declarationsAndStatements);
|
||||
}
|
||||
|
||||
override void visit(const ReturnStatement rs)
|
||||
{
|
||||
if (rs.expression.items.length != 1)
|
||||
return;
|
||||
UnaryExpression unary = cast(UnaryExpression) rs.expression.items[0];
|
||||
if (unary is null)
|
||||
return;
|
||||
if (unary.primaryExpression is null)
|
||||
return;
|
||||
if (unary.primaryExpression.primary != tok!"false")
|
||||
return;
|
||||
addErrorMessage(line, column, KEY, MESSAGE);
|
||||
}
|
||||
|
||||
override void visit(const Unittest u)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
uint inStruct;
|
||||
enum KEY = "dscanner.suspicios.incorrect_infinite_range";
|
||||
enum MESSAGE = "Use `enum bool empty = false;` to define an infinite range.";
|
||||
size_t line;
|
||||
size_t column;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
import std.stdio : stderr;
|
||||
import analysis.config : StaticAnalysisConfig;
|
||||
import std.format : format;
|
||||
|
||||
StaticAnalysisConfig sac;
|
||||
sac.builtin_property_names_check = true;
|
||||
assertAnalyzerWarnings(q{struct InfiniteRange
|
||||
{
|
||||
bool empty() // [warn]: %1$s
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool stuff()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool empty() { return false; }
|
||||
class C { bool empty() { return false; } } // [warn]: %1$s
|
||||
|
||||
}c
|
||||
.format(IncorrectInfiniteRangeCheck.MESSAGE), sac);
|
||||
stderr.writeln("Unittest for IncorrectInfiniteRangeCheck passed.");
|
||||
}
|
|
@ -53,6 +53,7 @@ import analysis.mismatched_args;
|
|||
import analysis.label_var_same_name_check;
|
||||
import analysis.line_length;
|
||||
import analysis.auto_ref_assignment;
|
||||
import analysis.incorrect_infinite_range;
|
||||
|
||||
import dsymbol.string_interning : internString;
|
||||
import dsymbol.scope_;
|
||||
|
@ -263,6 +264,7 @@ MessageSet analyze(string fileName, const Module m,
|
|||
checks ~= new LineLengthCheck(fileName, tokens);
|
||||
if (analysisConfig.auto_ref_assignment_check)
|
||||
checks ~= new AutoRefAssignmentCheck(fileName);
|
||||
checks ~= new IncorrectInfiniteRangeCheck(fileName);
|
||||
version (none)
|
||||
if (analysisConfig.redundant_if_check)
|
||||
checks ~= new IfStatementCheck(fileName, moduleScope);
|
||||
|
|
Loading…
Reference in New Issue