This commit is contained in:
Hackerpilot 2015-11-04 15:51:52 -08:00
parent cdc9d4d85c
commit 61770ee4c7
3 changed files with 125 additions and 0 deletions

View File

@ -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;
}

View File

@ -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.");
}

View File

@ -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);