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