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.numbers; 7 8 import std.stdio; 9 import std.regex; 10 import dparse.ast; 11 import dparse.lexer; 12 import analysis.base; 13 import analysis.helpers; 14 import dsymbol.scope_ : Scope; 15 16 /** 17 * Checks for long and hard-to-read number literals 18 */ 19 class NumberStyleCheck : BaseAnalyzer 20 { 21 public: 22 alias visit = BaseAnalyzer.visit; 23 24 /** 25 * Constructs the style checker with the given file name. 26 */ 27 this(string fileName, const(Scope)* sc) 28 { 29 super(fileName, sc); 30 } 31 32 override void visit(const Token t) 33 { 34 import std.algorithm : startsWith; 35 36 if (isNumberLiteral(t.type) && !t.text.startsWith("0x") 37 && ((t.text.startsWith("0b") && !t.text.matchFirst(badBinaryRegex) 38 .empty) || !t.text.matchFirst(badDecimalRegex).empty)) 39 { 40 addErrorMessage(t.line, t.column, "dscanner.style.number_literals", 41 "Use underscores to improve number constant readability."); 42 } 43 } 44 45 private: 46 auto badBinaryRegex = ctRegex!(`^0b[01]{9,}`); 47 auto badDecimalRegex = ctRegex!(`^\d{5,}`); 48 } 49 50 unittest 51 { 52 import analysis.config : StaticAnalysisConfig; 53 54 StaticAnalysisConfig sac; 55 sac.number_style_check = true; 56 assertAnalyzerWarnings(q{ 57 void testNumbers() 58 { 59 int a; 60 a = 1; // ok 61 a = 10; // ok 62 a = 100; // ok 63 a = 1000; // FIXME: boom 64 a = 10000; // [warn]: Use underscores to improve number constant readability. 65 a = 100000; // [warn]: Use underscores to improve number constant readability. 66 a = 1000000; // [warn]: Use underscores to improve number constant readability. 67 } 68 }}, sac); 69 70 stderr.writeln("Unittest for NumberStyleCheck passed."); 71 }