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