1 // Copyright Chris Wright (dhasenan) 2016. 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 module analysis.static_if_else; 7 8 import dparse.ast; 9 import dparse.lexer; 10 import analysis.base; 11 12 /** 13 * Checks for potentially mistaken static if / else if. 14 * 15 * It's potentially valid to write: 16 * --- 17 * static if (foo) { 18 * } else if (bar) { 19 * } 20 * --- 21 * 22 * However, it's more likely that this is a mistake. 23 */ 24 class StaticIfElse : BaseAnalyzer 25 { 26 alias visit = BaseAnalyzer.visit; 27 28 this(string fileName, bool skipTests = false) 29 { 30 super(fileName, null, skipTests); 31 } 32 33 override void visit(const ConditionalStatement cc) 34 { 35 cc.accept(this); 36 if (cc.falseStatement is null) 37 { 38 return; 39 } 40 const(IfStatement) ifStmt = getIfStatement(cc); 41 if (!ifStmt) 42 { 43 return; 44 } 45 addErrorMessage(ifStmt.line, ifStmt.column, KEY, "Mismatched static if. Use 'else static if' here."); 46 } 47 48 const(IfStatement) getIfStatement(const ConditionalStatement cc) 49 { 50 if (cc.falseStatement.statement) 51 { 52 if (cc.falseStatement.statement.statementNoCaseNoDefault) 53 { 54 if (cc.falseStatement.statement.statementNoCaseNoDefault.ifStatement) 55 { 56 return cc.falseStatement.statement.statementNoCaseNoDefault.ifStatement; 57 } 58 } 59 } 60 return null; 61 } 62 63 enum KEY = "dscanner.suspicious.static_if_else"; 64 } 65 66 unittest 67 { 68 import analysis.helpers : assertAnalyzerWarnings; 69 import analysis.config : StaticAnalysisConfig, Check; 70 import std.stdio : stderr; 71 72 StaticAnalysisConfig sac; 73 sac.static_if_else_check = Check.enabled; 74 assertAnalyzerWarnings(q{ 75 void foo() { 76 static if (false) 77 auto a = 0; 78 else if (true) // [warn]: Mismatched static if. Use 'else static if' here. 79 auto b = 1; 80 } 81 }}, sac); 82 // Explicit braces, so no warning. 83 assertAnalyzerWarnings(q{ 84 void foo() { 85 static if (false) 86 auto a = 0; 87 else { 88 if (true) 89 auto b = 1; 90 } 91 } 92 }}, sac); 93 94 stderr.writeln("Unittest for StaticIfElse passed."); 95 }