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 analysis.ifelsesame; 7 8 import std.stdio; 9 import dparse.ast; 10 import dparse.lexer; 11 import analysis.base; 12 import 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) 28 { 29 super(fileName, sc); 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)(cast(const Expression) assignExpression.expression) 43 .items[$ - 1]; 44 if (e !is null && assignExpression.operator == tok!"=" 45 && e.ternaryExpression == assignExpression.ternaryExpression) 46 { 47 addErrorMessage(assignExpression.line, assignExpression.column, "dscanner.bugs.self_assignment", 48 "Left side of assignment operatior is identical to the right side."); 49 } 50 assignExpression.accept(this); 51 } 52 53 override void visit(const AndAndExpression andAndExpression) 54 { 55 if (andAndExpression.left !is null && andAndExpression.right !is null 56 && andAndExpression.left == andAndExpression.right) 57 { 58 addErrorMessage(andAndExpression.line, andAndExpression.column, 59 "dscanner.bugs.logic_operator_operands", 60 "Left side of logical and is identical to right side."); 61 } 62 andAndExpression.accept(this); 63 } 64 65 override void visit(const OrOrExpression orOrExpression) 66 { 67 if (orOrExpression.left !is null && orOrExpression.right !is null 68 && orOrExpression.left == orOrExpression.right) 69 { 70 addErrorMessage(orOrExpression.line, orOrExpression.column, 71 "dscanner.bugs.logic_operator_operands", 72 "Left side of logical or is identical to right side."); 73 } 74 orOrExpression.accept(this); 75 } 76 } 77 78 unittest 79 { 80 import analysis.config : StaticAnalysisConfig; 81 82 StaticAnalysisConfig sac; 83 sac.if_else_same_check = true; 84 assertAnalyzerWarnings(q{ 85 void testSizeT() 86 { 87 string person = "unknown"; 88 if (person == "unknown") // [warn]: 'Else' branch is identical to 'Then' branch. 89 person = "bobrick"; // same 90 else 91 person = "bobrick"; // same 92 93 if (person == "unknown") // ok 94 person = "ricky"; // not same 95 else 96 person = "bobby"; // not same 97 } 98 }}, sac); 99 stderr.writeln("Unittest for IfElseSameCheck passed."); 100 }