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