1 // Copyright Brian Schott (Hackerpilot) 2015. 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.incorrect_infinite_range; 7 8 import analysis.base; 9 import analysis.helpers; 10 import dparse.ast; 11 import dparse.lexer; 12 13 /** 14 * Checks for incorrect infinite range definitions 15 */ 16 class IncorrectInfiniteRangeCheck : BaseAnalyzer 17 { 18 alias visit = BaseAnalyzer.visit; 19 20 /// 21 this(string fileName) 22 { 23 super(fileName, null); 24 } 25 26 override void visit(const StructBody structBody) 27 { 28 inStruct++; 29 structBody.accept(this); 30 inStruct--; 31 } 32 33 override void visit(const FunctionDeclaration fd) 34 { 35 if (inStruct > 0 && fd.name.text == "empty") 36 { 37 line = fd.name.line; 38 column = fd.name.column; 39 fd.accept(this); 40 } 41 } 42 43 override void visit(const FunctionBody fb) 44 { 45 if (fb.bodyStatement !is null) 46 visit(fb.bodyStatement.blockStatement); 47 else 48 visit(fb.blockStatement); 49 } 50 51 override void visit(const BlockStatement bs) 52 { 53 if (bs.declarationsAndStatements is null) 54 return; 55 if (bs.declarationsAndStatements.declarationsAndStatements is null) 56 return; 57 if (bs.declarationsAndStatements.declarationsAndStatements.length != 1) 58 return; 59 visit(bs.declarationsAndStatements); 60 } 61 62 override void visit(const ReturnStatement rs) 63 { 64 if (rs.expression.items.length != 1) 65 return; 66 UnaryExpression unary = cast(UnaryExpression) rs.expression.items[0]; 67 if (unary is null) 68 return; 69 if (unary.primaryExpression is null) 70 return; 71 if (unary.primaryExpression.primary != tok!"false") 72 return; 73 addErrorMessage(line, column, KEY, MESSAGE); 74 } 75 76 override void visit(const Unittest u) 77 { 78 } 79 80 private: 81 uint inStruct; 82 enum string KEY = "dscanner.suspicios.incorrect_infinite_range"; 83 enum string MESSAGE = "Use `enum bool empty = false;` to define an infinite range."; 84 size_t line; 85 size_t column; 86 } 87 88 unittest 89 { 90 import std.stdio : stderr; 91 import analysis.config : StaticAnalysisConfig; 92 import std.format : format; 93 94 StaticAnalysisConfig sac; 95 sac.incorrect_infinite_range_check = true; 96 assertAnalyzerWarnings(q{struct InfiniteRange 97 { 98 bool empty() // [warn]: %1$s 99 { 100 return false; 101 } 102 103 bool stuff() 104 { 105 return false; 106 } 107 108 unittest 109 { 110 return false; 111 } 112 } 113 114 bool empty() { return false; } 115 class C { bool empty() { return false; } } // [warn]: %1$s 116 117 }} 118 .format(IncorrectInfiniteRangeCheck.MESSAGE), sac); 119 stderr.writeln("Unittest for IncorrectInfiniteRangeCheck passed."); 120 }