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 if (isNumberLiteral(t.type) && !t.text.startsWith("0x") 36 && ((t.text.startsWith("0b") && !t.text.matchFirst(badBinaryRegex).empty) 37 || !t.text.matchFirst(badDecimalRegex).empty)) 38 { 39 addErrorMessage(t.line, t.column, "dscanner.style.number_literals", 40 "Use underscores to improve number constant readability."); 41 } 42 } 43 private: 44 auto badBinaryRegex = ctRegex!(`^0b[01]{9,}`); 45 auto badDecimalRegex = ctRegex!(`^\d{5,}`); 46 } 47 48 unittest 49 { 50 import analysis.config : StaticAnalysisConfig; 51 StaticAnalysisConfig sac; 52 sac.number_style_check = true; 53 assertAnalyzerWarnings(q{ 54 void testNumbers() 55 { 56 int a; 57 a = 1; // ok 58 a = 10; // ok 59 a = 100; // ok 60 a = 1000; // FIXME: boom 61 a = 10000; // [warn]: Use underscores to improve number constant readability. 62 a = 100000; // [warn]: Use underscores to improve number constant readability. 63 a = 1000000; // [warn]: Use underscores to improve number constant readability. 64 } 65 }}, sac); 66 67 stderr.writeln("Unittest for NumberStyleCheck passed."); 68 } 69