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 dscanner.analysis.static_if_else; 7 8 import dparse.ast; 9 import dparse.lexer; 10 import dscanner.analysis.base; 11 import dscanner.utils : safeAccess; 12 13 /** 14 * Checks for potentially mistaken static if / else if. 15 * 16 * It's potentially valid to write: 17 * --- 18 * static if (foo) { 19 * } else if (bar) { 20 * } 21 * --- 22 * 23 * However, it's more likely that this is a mistake. 24 */ 25 final class StaticIfElse : BaseAnalyzer 26 { 27 alias visit = BaseAnalyzer.visit; 28 29 mixin AnalyzerInfo!"static_if_else_check"; 30 31 this(string fileName, bool skipTests = false) 32 { 33 super(fileName, null, skipTests); 34 } 35 36 override void visit(const ConditionalStatement cc) 37 { 38 cc.accept(this); 39 if (cc.falseStatement is null) 40 { 41 return; 42 } 43 const(IfStatement) ifStmt = getIfStatement(cc); 44 if (!ifStmt) 45 { 46 return; 47 } 48 addErrorMessage(ifStmt.line, ifStmt.column, KEY, "Mismatched static if. Use 'else static if' here."); 49 } 50 51 const(IfStatement) getIfStatement(const ConditionalStatement cc) 52 { 53 return safeAccess(cc).falseStatement.statement.statementNoCaseNoDefault.ifStatement; 54 } 55 56 enum KEY = "dscanner.suspicious.static_if_else"; 57 } 58 59 unittest 60 { 61 import dscanner.analysis.helpers : assertAnalyzerWarnings; 62 import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig; 63 import std.stdio : stderr; 64 65 StaticAnalysisConfig sac = disabledConfig(); 66 sac.static_if_else_check = Check.enabled; 67 assertAnalyzerWarnings(q{ 68 void foo() { 69 static if (false) 70 auto a = 0; 71 else if (true) // [warn]: Mismatched static if. Use 'else static if' here. 72 auto b = 1; 73 } 74 }}, sac); 75 // Explicit braces, so no warning. 76 assertAnalyzerWarnings(q{ 77 void foo() { 78 static if (false) 79 auto a = 0; 80 else { 81 if (true) 82 auto b = 1; 83 } 84 } 85 }}, sac); 86 87 stderr.writeln("Unittest for StaticIfElse passed."); 88 }