forked from dlang/dlang.org
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheck_ddoc.d
executable file
·81 lines (67 loc) · 2.1 KB
/
check_ddoc.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/env rdmd
/**
Search HTML output for errors:
- for undefined Ddoc macros
- raw macro leakage
- trailing parenthesis
*/
import std.algorithm, std.file, std.functional, std.range, std.stdio;
shared int errors = 0;
void error(string name, string file, size_t lineNr, const(char)[] line)
{
import core.atomic;
errors.atomicOp!"+="(1);
synchronized
{
stderr.writefln("%s:%d: [%s] %s", file, lineNr, name, line);
}
}
enum ErrorMessages
{
undefinedMacro = "UNDEFINED MACRO",
rawMacroLeakage = "RAW MACRO LEAKAGE",
trailingParenthesis = "TRAILING PARENTHESIS",
}
void checkLine(alias errorFun)(string file, size_t lineNr, const(char)[] line)
{
if (line.canFind("UNDEFINED MACRO"))
errorFun(ErrorMessages.undefinedMacro, file, lineNr, line);
if (line.findSplitAfter("$(")
.pipe!(a => !a.expand.only.any!empty && a[1].front != '\''))
errorFun(ErrorMessages.rawMacroLeakage, file, lineNr, line);
if (line.equal(")"))
errorFun(ErrorMessages.trailingParenthesis, file, lineNr, line);
}
version(unittest) {} else
int main(string[] args)
{
import std.parallelism : parallel;
auto files = args[1 .. $];
foreach (file; files.parallel(1))
foreach (nr, line; File(file, "r").byLine.enumerate)
checkLine!error(file, nr, line);
if (errors > 0)
stderr.writefln("%s error%s found. Exiting.", errors, errors > 1 ? "s" : "");
return errors != 0;
}
unittest
{
string lastSeenError;
void errorStub(string name, string file, size_t lineNr, const(char)[] line)
{
lastSeenError = name;
}
auto check(string line)
{
lastSeenError = null;
checkLine!errorStub(null, 0, line);
return lastSeenError;
}
assert(check(` <!--UNDEFINED MACRO: "D_CONTRIBUTORS"--> `) == ErrorMessages.undefinedMacro);
assert(check(" $('") is null);
assert(check(" $(") is null);
assert(check(" $(FOO)") == ErrorMessages.rawMacroLeakage);
assert(check(" )") is null);
assert(check(") ") is null);
assert(check(")") == ErrorMessages.trailingParenthesis);
}