1 // Copyright Brian Schott (Hackerpilot) 2014. 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.ifelsesame; 7 8 import std.stdio; 9 import dparse.ast; 10 import dparse.lexer; 11 import dscanner.analysis.base; 12 import dscanner.analysis.helpers; 13 import dsymbol.scope_ : Scope; 14 15 /** 16 * Checks for duplicated code in conditional and logical expressions. 17 * $(UL 18 * $(LI If statements whose "then" block is the same as the "else" block) 19 * $(LI || and && expressions where the left and right are the same) 20 * $(LI == expressions where the left and right are the same) 21 * ) 22 */ 23 class IfElseSameCheck : BaseAnalyzer 24 { 25 alias visit = BaseAnalyzer.visit; 26 27 this(string fileName, const(Scope)* sc, bool skipTests = false) 28 { 29 super(fileName, sc, skipTests); 30 } 31 32 override void visit(const IfStatement ifStatement) 33 { 34 if (ifStatement.thenStatement == ifStatement.elseStatement) 35 addErrorMessage(ifStatement.line, ifStatement.column, 36 "dscanner.bugs.if_else_same", "'Else' branch is identical to 'Then' branch."); 37 ifStatement.accept(this); 38 } 39 40 override void visit(const AssignExpression assignExpression) 41 { 42 auto e = cast(const AssignExpression) assignExpression.expression; 43 if (e !is null && assignExpression.operator == tok!"=" 44 && e.ternaryExpression == assignExpression.ternaryExpression) 45 { 46 addErrorMessage(assignExpression.line, assignExpression.column, "dscanner.bugs.self_assignment", 47 "Left side of assignment operatior is identical to the right side."); 48 } 49 assignExpression.accept(this); 50 } 51 52 override void visit(const AndAndExpression andAndExpression) 53 { 54 if (andAndExpression.left !is null && andAndExpression.right !is null 55 && andAndExpression.left == andAndExpression.right) 56 { 57 addErrorMessage(andAndExpression.line, andAndExpression.column, 58 "dscanner.bugs.logic_operator_operands", 59 "Left side of logical and is identical to right side."); 60 } 61 andAndExpression.accept(this); 62 } 63 64 override void visit(const OrOrExpression orOrExpression) 65 { 66 if (orOrExpression.left !is null && orOrExpression.right !is null 67 && orOrExpression.left == orOrExpression.right) 68 { 69 addErrorMessage(orOrExpression.line, orOrExpression.column, 70 "dscanner.bugs.logic_operator_operands", 71 "Left side of logical or is identical to right side."); 72 } 73 orOrExpression.accept(this); 74 } 75 } 76 77 unittest 78 { 79 import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig; 80 81 StaticAnalysisConfig sac = disabledConfig(); 82 sac.if_else_same_check = Check.enabled; 83 assertAnalyzerWarnings(q{ 84 void testSizeT() 85 { 86 string person = "unknown"; 87 if (person == "unknown") // [warn]: 'Else' branch is identical to 'Then' branch. 88 person = "bobrick"; // same 89 else 90 person = "bobrick"; // same 91 92 if (person == "unknown") // ok 93 person = "ricky"; // not same 94 else 95 person = "bobby"; // not same 96 } 97 }c, sac); 98 stderr.writeln("Unittest for IfElseSameCheck passed."); 99 }