D-Scanner/src/dscanner/analysis/static_if_else.d

94 lines
2.0 KiB
D

// Copyright Chris Wright (dhasenan) 2016.
// 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 dscanner.analysis.static_if_else;
import dscanner.analysis.base;
import std.stdio;
// TODO: check and fix AutoFix
/**
* Checks for potentially mistaken static if / else if.
*
* It's potentially valid to write:
* ---
* static if (foo) {
* } else if (bar) {
* }
* ---
*
* However, it's more likely that this is a mistake.
*/
extern(C++) class StaticIfElse(AST) : BaseAnalyzerDmd
{
alias visit = BaseAnalyzerDmd.visit;
mixin AnalyzerInfo!"static_if_else_check";
extern(D) this(string fileName, bool skipTests = false)
{
super(fileName, skipTests);
}
override void visit(AST.ConditionalStatement s)
{
import dmd.astenums : STMT;
if (!s.condition.isStaticIfCondition())
{
super.visit(s);
return;
}
s.condition.accept(this);
if (s.ifbody)
s.ifbody.accept(this);
if (s.elsebody)
{
if (s.elsebody.stmt == STMT.If)
addErrorMessage(cast(ulong) s.elsebody.loc.linnum, cast(ulong) s.elsebody.loc.charnum,
KEY, MESSAGE);
s.elsebody.accept(this);
}
}
private:
enum KEY = "dscanner.suspicious.static_if_else";
enum MESSAGE = "Mismatched static if. Use 'else static if' here.";
}
unittest
{
import dscanner.analysis.helpers : assertAnalyzerWarnings = assertAnalyzerWarningsDMD;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig();
sac.static_if_else_check = Check.enabled;
assertAnalyzerWarnings(q{
void foo() {
static if (false)
auto a = 0;
else if (true) // [warn]: Mismatched static if. Use 'else static if' here.
auto b = 1;
}
}c, sac);
// Explicit braces, so no warning.
assertAnalyzerWarnings(q{
void foo() {
static if (false)
auto a = 0;
else {
if (true)
auto b = 1;
}
}
}c, sac);
stderr.writeln("Unittest for StaticIfElse passed.");
}