1 -- base class for all inspectors
2 -- every derived class must implement inspect()
6 function inspector
:__init(name
)
11 function inspector
:warning(path
, str
)
12 table.insert( self
.warnings
, { path
, str
} )
15 function inspector
:report()
16 local output
= function(_
,x
)
17 local name
= x
[1]:string()
18 print(name
.. ": " .. x
[2])
21 local cmp
= function(a
,b
)
22 return a
[1]:string() < b
[1]:string()
27 if table.getn(self
.warnings
) ~= 0 then
28 violations
= table.getn(self
.warnings
) .. " violations"
30 violations
= "no violations"
33 print("\n-- " .. self
.name
.. " [" .. violations
.. "]\n")
35 table.sort(self
.warnings
, cmp
)
36 table.foreach(self
.warnings
, output
)
39 inspector
.inspect
= nil
41 -- checks filename length
42 class
'filename_length' (inspector
)
44 function filename_length
:__init(n
)
45 super("filename length (" .. n
.. " characters)")
49 function filename_length
:inspect(path
)
50 local n
= string.len(path
:leaf())
51 if n
> self
.maxlen
then
52 self
:warning(path
, n
.. " characters in filename")
56 -- checks that the filename is all lowercase
57 class
'filename_case' (inspector
)
59 function filename_case
:__init()
60 super("filename case")
63 function filename_case
:inspect(path
)
64 if string.lower(path
:leaf()) ~= path
:leaf() then
65 self
:warning(path
, "uppercase letters")
69 -- checks that the file doesn't contain tabs
70 class
'tab_inspector' (inspector
)
72 function tab_inspector
:__init()
73 super("tab inspector")
76 function tab_inspector
:inspect(path
)
77 if has_endings(path
:leaf(), ".hpp", ".cpp") then
78 for line
in io
.lines(path
:string()) do
79 if string.find(line
, '\t') ~= nil then
80 self
:warning(path
, "tabs in file")
87 -- checks that the file doesn't contain too long lines
88 class
'line_length_inspector' (inspector
)
90 function line_length_inspector
:__init(n
)
91 super("line length inspector (" .. n
.. " characters)")
95 function line_length_inspector
:inspect(path
)
96 if has_endings(path
:leaf(), ".hpp", ".cpp") then
97 for line
in io
.lines(path
:string()) do
98 if string.len(line
) > self
.maxlen
then
99 self
:warning(path
, "lines too long " .. string.len(line
))
106 -- checks for unmatched #define/#undef pairs
107 class
'define_inspector' (inspector
)
109 function define_inspector
:__init()
110 super("define inspector")
113 function define_inspector
:inspect(path
)
114 if has_endings(path
:leaf(), ".hpp") then
118 for line
in io
.lines(path
:string()) do
119 local pos
, _
, def
= string.find(line
, "#%s*define%s+([%w_]+)")
120 if pos
~= nil then defs
[def
] = true end
121 local pos
, _
, def
= string.find(line
, "#%s*undef%s+([%w_]+)")
122 if pos
~= nil then defs
[def
] = nil end
125 table.foreach(defs
, function(def
)
126 self
:warning(path
, def
)
133 function file_ending(name
)
134 local pos
= string.find(name
, "%.")
135 if pos
== nil then return ""
137 return string.sub(name
, pos
)
141 function has_endings(name
, ...)
142 local ending
= file_ending(name
)
144 if ending
== i
then return true end
149 function recurse_dir(path
)
150 for i
in path
.contents
do
151 if i
:is_directory() then recurse_dir(i
)
153 table.foreach(inspectors
, function(_
,x
)
156 number_of_files
= number_of_files
+ 1
163 inspectors
= { filename_length(31), filename_case(),
164 tab_inspector(), line_length_inspector(79),
168 if args
.n
>= 3 then root
= filesystem
.path(args
[3])
169 else root
= filesystem
.initial_path() end
171 print("inspecting '" .. root
:string() .. "' ...")
175 print(" ** " .. number_of_files
.. " files was inspected")
177 table.foreach(inspectors
, function(_
,i
)