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