93 lines
2.1 KiB
D
93 lines
2.1 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 dparse.ast;
|
|
import dparse.lexer;
|
|
import dscanner.analysis.base;
|
|
import dscanner.utils : safeAccess;
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
final class StaticIfElse : BaseAnalyzer
|
|
{
|
|
alias visit = BaseAnalyzer.visit;
|
|
|
|
mixin AnalyzerInfo!"static_if_else_check";
|
|
|
|
this(string fileName, bool skipTests = false)
|
|
{
|
|
super(fileName, null, skipTests);
|
|
}
|
|
|
|
override void visit(const ConditionalStatement cc)
|
|
{
|
|
cc.accept(this);
|
|
if (cc.falseStatement is null)
|
|
{
|
|
return;
|
|
}
|
|
const(IfStatement) ifStmt = getIfStatement(cc);
|
|
if (!ifStmt)
|
|
{
|
|
return;
|
|
}
|
|
auto tokens = ifStmt.tokens[0 .. 1];
|
|
// extend one token to include `else` before this if
|
|
tokens = (tokens.ptr - 1)[0 .. 2];
|
|
addErrorMessage(tokens, KEY, "Mismatched static if. Use 'else static if' here.");
|
|
}
|
|
|
|
const(IfStatement) getIfStatement(const ConditionalStatement cc)
|
|
{
|
|
return safeAccess(cc).falseStatement.statement.statementNoCaseNoDefault.ifStatement;
|
|
}
|
|
|
|
enum KEY = "dscanner.suspicious.static_if_else";
|
|
}
|
|
|
|
unittest
|
|
{
|
|
import dscanner.analysis.helpers : assertAnalyzerWarnings;
|
|
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.");
|
|
}
|