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.line_length;
7 
8 import dparse.lexer;
9 import dparse.ast;
10 import analysis.base : BaseAnalyzer;
11 
12 /**
13  * Checks for lines longer than 120 characters
14  */
15 class LineLengthCheck : BaseAnalyzer
16 {
17 	///
18 	this(string fileName, const(Token)[] tokens)
19 	{
20 		super(fileName, null);
21 		this.tokens = tokens;
22 	}
23 
24 	override void visit(const Module)
25 	{
26 		ulong lastErrorLine = ulong.max;
27 		foreach (token; tokens)
28 		{
29 			if (tokenEndColumn(token) > MAX_LINE_LENGTH && token.line != lastErrorLine)
30 			{
31 				addErrorMessage(token.line, token.column, KEY, MESSAGE);
32 				lastErrorLine = token.line;
33 			}
34 		}
35 	}
36 
37 	alias visit = BaseAnalyzer.visit;
38 
39 private:
40 
41 	static ulong tokenEndColumn(ref const Token tok)
42 	{
43 		import std.uni : lineSep, paraSep;
44 
45 		ulong endColumn = tok.column;
46 		foreach (dchar c; tok.text)
47 		{
48 			if (c == lineSep || c == '\n' || c == '\v' || c == '\r' || c == paraSep)
49 				endColumn = 0;
50 			else
51 				endColumn++;
52 		}
53 		return endColumn;
54 	}
55 
56 	import std.conv : to;
57 
58 	enum string KEY = "dscanner.style.long_line";
59 	enum string MESSAGE = "Line is longer than " ~ to!string(MAX_LINE_LENGTH) ~ " characters";
60 	enum MAX_LINE_LENGTH = 120;
61 	const(Token)[] tokens;
62 }