@@ -0,0 +1,52 | |||
|
1 | # - try to find vera++ tool | |
|
2 | # | |
|
3 | # Cache Variables: | |
|
4 | # VERA++_ROOT_DIR | |
|
5 | # VERA++_EXECUTABLE | |
|
6 | # VERA++_USE_FILE | |
|
7 | # | |
|
8 | # Non-cache variables you might use in your CMakeLists.txt: | |
|
9 | # VERA++_FOUND | |
|
10 | # | |
|
11 | # Requires these CMake modules: | |
|
12 | # FindPackageHandleStandardArgs (known included with CMake >=2.6.2) | |
|
13 | ||
|
14 | file(TO_CMAKE_PATH "${VERA++_ROOT_DIR}" VERA++_ROOT_DIR) | |
|
15 | set(VERA++_ROOT_DIR | |
|
16 | "${VERA++_ROOT_DIR}" | |
|
17 | CACHE | |
|
18 | PATH | |
|
19 | "Path to search for vera++") | |
|
20 | ||
|
21 | if(VERA++_EXECUTABLE AND NOT EXISTS "${VERA++_EXECUTABLE}") | |
|
22 | set(VERA++_EXECUTABLE "notfound" CACHE PATH FORCE "") | |
|
23 | endif() | |
|
24 | ||
|
25 | # If we have a custom path, look there first. | |
|
26 | if(VERA++_ROOT_DIR) | |
|
27 | find_program(VERA++_EXECUTABLE | |
|
28 | NAMES | |
|
29 | vera++ | |
|
30 | PATHS | |
|
31 | "${VERA++_ROOT_DIR}" | |
|
32 | PATH_SUFFIXES | |
|
33 | bin | |
|
34 | NO_DEFAULT_PATH) | |
|
35 | endif() | |
|
36 | ||
|
37 | find_program(VERA++_EXECUTABLE NAMES vera++) | |
|
38 | ||
|
39 | # Find the use file for vera | |
|
40 | GET_FILENAME_COMPONENT(VERA++_MODULE_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) | |
|
41 | SET(VERA++_USE_FILE "${VERA++_MODULE_DIR}/use_vera++.cmake") | |
|
42 | ||
|
43 | SET(VERA++_ALL ${VERA++_EXECUTABLE} ${VERA++_USE_FILE}) | |
|
44 | ||
|
45 | include(FindPackageHandleStandardArgs) | |
|
46 | find_package_handle_standard_args(vera++ | |
|
47 | DEFAULT_MSG | |
|
48 | VERA++_ALL | |
|
49 | VERA++_EXECUTABLE | |
|
50 | VERA++_USE_FILE) | |
|
51 | ||
|
52 | mark_as_advanced(VERA++_EXECUTABLE) |
@@ -0,0 +1,342 | |||
|
1 | # | |
|
2 | # use_vera++.cmake | |
|
3 | # | |
|
4 | # The following functions are defined in this document: | |
|
5 | # - ADD_VERA_TARGETS | |
|
6 | # - ADD_VERA_CHECKSTYLE_TARGET | |
|
7 | # | |
|
8 | ||
|
9 | # ADD_VERA_TARGETS(<globExpression> ... | |
|
10 | # [ADD_TO_ALL] | |
|
11 | # [NAME <name>] | |
|
12 | # [NAME_ALL <nameall>] | |
|
13 | # [ROOT <directory>] | |
|
14 | # [PROFILE <profile>] | |
|
15 | # [RECURSE] | |
|
16 | # [EXCLUSION <exclusionFile> ...] | |
|
17 | # [PARAMETER <name>=<value> ...] | |
|
18 | # [PARAMETERFILE <parameterFile> ...]) | |
|
19 | # | |
|
20 | # Two custom targets will be created: | |
|
21 | # * style_reports is run as part of the build, and is not rerun unless one of | |
|
22 | # the file checked is modified (only created if ADD_TO_ALL is provided); | |
|
23 | # * style must be explicitely called (make style) and is rerun even if the files | |
|
24 | # to check have not been modified. To achieve this behavior, the commands used | |
|
25 | # in this target pretend to produce a file without actually producing it. | |
|
26 | # Because the output file is not there after the run, the command will be rerun | |
|
27 | # again at the next target build. | |
|
28 | # The report style is selected based on the build environment, so the style | |
|
29 | # problems are properly reported in the IDEs | |
|
30 | # | |
|
31 | # If ADD_TO_ALL is provided then a target will be added to the default build | |
|
32 | # targets so that each time a source file is compiled, it is analyzed with | |
|
33 | # vera++. | |
|
34 | # | |
|
35 | # NAME and NAME_ALL customize the name of the targets (style and style_reports | |
|
36 | # by default respectively). | |
|
37 | # | |
|
38 | # ROOT set the vera++ root directory, containing the rules and profiles (default | |
|
39 | # to the current binary directory). | |
|
40 | # | |
|
41 | # PROFILE selects the vera++ profile to use (default to "default"). | |
|
42 | # | |
|
43 | # RECURSE selects if the glob expressions should be applied recursively or not. | |
|
44 | # | |
|
45 | # EXCLUSION list of vera++ exclusion files. Can be used several times. | |
|
46 | # | |
|
47 | # PARAMETER list of vera++ parameters (name=value). Can be used several times. | |
|
48 | # | |
|
49 | # PARAMETERFILE list of vera++ parameter files. Can be used several times. | |
|
50 | function(add_vera_targets) | |
|
51 | # default values | |
|
52 | set(target "style") | |
|
53 | set(target_all "style_reports") | |
|
54 | set(profile "default") | |
|
55 | set(root "${CMAKE_CURRENT_BINARY_DIR}") | |
|
56 | set(exclusions) | |
|
57 | set(parameters) | |
|
58 | set(parameterFiles) | |
|
59 | set(recurse OFF) | |
|
60 | set(addToAll OFF) | |
|
61 | set(globs) | |
|
62 | # parse the options | |
|
63 | math(EXPR lastIdx "${ARGC} - 1") | |
|
64 | set(i 0) | |
|
65 | while(i LESS ${ARGC}) | |
|
66 | set(arg "${ARGV${i}}") | |
|
67 | if("${arg}" STREQUAL "ADD_TO_ALL") | |
|
68 | set(addToAll ON) | |
|
69 | elseif("${arg}" STREQUAL "NAME") | |
|
70 | vera_incr(i) | |
|
71 | set(target "${ARGV${i}}") | |
|
72 | elseif("${arg}" STREQUAL "NAME_ALL") | |
|
73 | vera_incr(i) | |
|
74 | set(target_all "${ARGV${i}}") | |
|
75 | elseif("${arg}" STREQUAL "ROOT") | |
|
76 | vera_incr(i) | |
|
77 | set(root "${ARGV${i}}") | |
|
78 | elseif("${arg}" STREQUAL "PROFILE") | |
|
79 | vera_incr(i) | |
|
80 | set(profile "${ARGV${i}}") | |
|
81 | elseif("${arg}" STREQUAL "EXCLUSION") | |
|
82 | vera_incr(i) | |
|
83 | list(APPEND exclusions --exclusions "${ARGV${i}}") | |
|
84 | elseif("${arg}" STREQUAL "RECURSE") | |
|
85 | set(recurse ON) | |
|
86 | elseif("${arg}" STREQUAL "PARAMETER") | |
|
87 | vera_incr(i) | |
|
88 | list(APPEND parameters --parameter "${ARGV${i}}") | |
|
89 | elseif("${arg}" STREQUAL "PARAMETERFILE") | |
|
90 | vera_incr(i) | |
|
91 | list(APPEND parameterFiles --parameters "${ARGV${i}}") | |
|
92 | else() | |
|
93 | list(APPEND globs ${arg}) | |
|
94 | endif() | |
|
95 | vera_incr(i) | |
|
96 | endwhile() | |
|
97 | ||
|
98 | if(recurse) | |
|
99 | file(GLOB_RECURSE srcs ${globs}) | |
|
100 | else() | |
|
101 | file(GLOB srcs ${globs}) | |
|
102 | endif() | |
|
103 | list(SORT srcs) | |
|
104 | ||
|
105 | if(NOT VERA++_EXECUTABLE AND TARGET vera) | |
|
106 | set(vera_program "$<TARGET_FILE:vera>") | |
|
107 | else() | |
|
108 | set(vera_program "${VERA++_EXECUTABLE}") | |
|
109 | endif() | |
|
110 | ||
|
111 | # Two custom targets will be created: | |
|
112 | # * style_reports is run as part of the build, and is not rerun unless one of | |
|
113 | # the file checked is modified; | |
|
114 | # * style must be explicitely called (make style) and is rerun even if the files | |
|
115 | # to check have not been modified. To achieve this behavior, the commands used | |
|
116 | # in this target pretend to produce a file without actually producing it. | |
|
117 | # Because the output file is not there after the run, the command will be rerun | |
|
118 | # again at the next target build. | |
|
119 | # The report style is selected based on the build environment, so the style | |
|
120 | # problems are properly reported in the IDEs | |
|
121 | if(MSVC) | |
|
122 | set(style vc) | |
|
123 | else() | |
|
124 | set(style std) | |
|
125 | endif() | |
|
126 | set(xmlreports) | |
|
127 | set(noreports) | |
|
128 | set(reportNb 0) | |
|
129 | set(reportsrcs) | |
|
130 | list(GET srcs 0 first) | |
|
131 | get_filename_component(currentDir ${first} PATH) | |
|
132 | # add a fake src file in a fake dir to trigger the creation of the last | |
|
133 | # custom command | |
|
134 | list(APPEND srcs "#12345678900987654321#/0987654321#1234567890") | |
|
135 | # Create the directory where the reports will be saved | |
|
136 | SET(reportDirectory "${CMAKE_CURRENT_BINARY_DIR}/vera") | |
|
137 | FILE(MAKE_DIRECTORY ${reportDirectory}) | |
|
138 | foreach(s ${srcs}) | |
|
139 | get_filename_component(d ${s} PATH) | |
|
140 | if(NOT "${d}" STREQUAL "${currentDir}") | |
|
141 | # this is a new dir - lets generate everything needed for the previous dir | |
|
142 | string(LENGTH "${CMAKE_SOURCE_DIR}" len) | |
|
143 | string(SUBSTRING "${currentDir}" 0 ${len} pre) | |
|
144 | if("${pre}" STREQUAL "${CMAKE_SOURCE_DIR}") | |
|
145 | string(SUBSTRING "${currentDir}" ${len} -1 currentDir) | |
|
146 | string(REGEX REPLACE "^/" "" currentDir "${currentDir}") | |
|
147 | endif() | |
|
148 | if("${currentDir}" STREQUAL "") | |
|
149 | set(currentDir ".") | |
|
150 | endif() | |
|
151 | set(xmlreport ${reportDirectory}/vera_report_${reportNb}.xml) | |
|
152 | if(addToAll) | |
|
153 | add_custom_command( | |
|
154 | OUTPUT ${xmlreport} | |
|
155 | COMMAND ${vera_program} | |
|
156 | --root ${root} | |
|
157 | --profile ${profile} | |
|
158 | --${style}-report=- | |
|
159 | --show-rule | |
|
160 | --warning | |
|
161 | --xml-report=${xmlreport} | |
|
162 | ${exclusions} | |
|
163 | ${parameters} | |
|
164 | ${parameterFiles} | |
|
165 | ${reportsrcs} | |
|
166 | DEPENDS ${reportsrcs} | |
|
167 | COMMENT "Checking style with vera++ in ${currentDir}" | |
|
168 | ) | |
|
169 | endif() | |
|
170 | ||
|
171 | set(noreport ${reportDirectory}/vera_noreport_${reportNb}.xml) | |
|
172 | add_custom_command( | |
|
173 | OUTPUT ${noreport} | |
|
174 | COMMAND ${vera_program} | |
|
175 | --root ${root} | |
|
176 | --profile ${profile} | |
|
177 | --${style}-report=- | |
|
178 | --show-rule | |
|
179 | --warning | |
|
180 | # --xml-report=${noreport} | |
|
181 | ${exclusions} | |
|
182 | ${parameters} | |
|
183 | ${parameterFiles} | |
|
184 | ${reportsrcs} | |
|
185 | DEPENDS ${reportsrcs} | |
|
186 | COMMENT "Checking style with vera++ in ${currentDir}" | |
|
187 | ) | |
|
188 | ||
|
189 | list(APPEND xmlreports ${xmlreport}) | |
|
190 | list(APPEND noreports ${noreport}) | |
|
191 | vera_incr(reportNb) | |
|
192 | # clear the list for the next dir | |
|
193 | set(reportsrcs) | |
|
194 | set(currentDir ${d}) | |
|
195 | endif() | |
|
196 | list(APPEND reportsrcs ${s}) | |
|
197 | endforeach() | |
|
198 | # Create the custom targets that will trigger the custom command created | |
|
199 | # previously | |
|
200 | if(addToAll) | |
|
201 | add_custom_target(${target_all} ALL DEPENDS ${xmlreports}) | |
|
202 | endif() | |
|
203 | add_custom_target(${target} DEPENDS ${noreports}) | |
|
204 | endfunction() | |
|
205 | ||
|
206 | ||
|
207 | # ADD_VERA_CHECKSTYLE_TARGET(<globExpression> ... | |
|
208 | # [NAME <name>] | |
|
209 | # [ROOT <directory>] | |
|
210 | # [PROFILE <profile>] | |
|
211 | # [RECURSE] | |
|
212 | # [EXCLUSION <exclusionFile> ...] | |
|
213 | # [PARAMETER <name>=<value> ...] | |
|
214 | # [PARAMETERFILE <parameterFile> ...]) | |
|
215 | # | |
|
216 | # The checkstyle custom target will be created. This target runs vera++ and | |
|
217 | # create checkstyle reports in the ${CMAKE_CURRENT_BINARY_DIR}/checkstyle | |
|
218 | # directory. | |
|
219 | # | |
|
220 | # NAME customize the name of the target (checkstyle by default). | |
|
221 | # | |
|
222 | # ROOT set the vera++ root directory, containing the rules and profiles (default | |
|
223 | # to the current binary directory). | |
|
224 | # | |
|
225 | # PROFILE selects the vera++ profile to use (default to "default"). | |
|
226 | # | |
|
227 | # RECURSE selects if the glob expressions should be applied recursively or not. | |
|
228 | # | |
|
229 | # EXCLUSION list of vera++ exclusion files. Can be used several times. | |
|
230 | # | |
|
231 | # PARAMETER list of vera++ parameters (name=value). Can be used several times. | |
|
232 | # | |
|
233 | # PARAMETERFILE list of vera++ parameter files. Can be used several times. | |
|
234 | function(add_vera_checkstyle_target) | |
|
235 | # default values | |
|
236 | set(target "checkstyle") | |
|
237 | set(profile "default") | |
|
238 | set(root "${CMAKE_CURRENT_BINARY_DIR}") | |
|
239 | set(exclusions) | |
|
240 | set(parameters) | |
|
241 | set(parameterFiles) | |
|
242 | set(recurse OFF) | |
|
243 | set(globs) | |
|
244 | # parse the options | |
|
245 | math(EXPR lastIdx "${ARGC} - 1") | |
|
246 | set(i 0) | |
|
247 | while(i LESS ${ARGC}) | |
|
248 | set(arg "${ARGV${i}}") | |
|
249 | if("${arg}" STREQUAL "NAME") | |
|
250 | vera_incr(i) | |
|
251 | set(target "${ARGV${i}}") | |
|
252 | elseif("${arg}" STREQUAL "ROOT") | |
|
253 | vera_incr(i) | |
|
254 | set(root "${ARGV${i}}") | |
|
255 | elseif("${arg}" STREQUAL "PROFILE") | |
|
256 | vera_incr(i) | |
|
257 | set(profile "${ARGV${i}}") | |
|
258 | elseif("${arg}" STREQUAL "EXCLUSION") | |
|
259 | vera_incr(i) | |
|
260 | list(APPEND exclusions --exclusions "${ARGV${i}}") | |
|
261 | elseif("${arg}" STREQUAL "RECURSE") | |
|
262 | set(recurse ON) | |
|
263 | elseif("${arg}" STREQUAL "PARAMETER") | |
|
264 | vera_incr(i) | |
|
265 | list(APPEND parameters --parameter "${ARGV${i}}") | |
|
266 | elseif("${arg}" STREQUAL "PARAMETERFILE") | |
|
267 | vera_incr(i) | |
|
268 | list(APPEND parameterFiles --parameters "${ARGV${i}}") | |
|
269 | else() | |
|
270 | list(APPEND globs ${arg}) | |
|
271 | endif() | |
|
272 | vera_incr(i) | |
|
273 | endwhile() | |
|
274 | ||
|
275 | if(recurse) | |
|
276 | file(GLOB_RECURSE srcs ${globs}) | |
|
277 | else() | |
|
278 | file(GLOB srcs ${globs}) | |
|
279 | endif() | |
|
280 | list(SORT srcs) | |
|
281 | ||
|
282 | if(NOT VERA++_EXECUTABLE AND TARGET vera) | |
|
283 | set(vera_program "$<TARGET_FILE:vera>") | |
|
284 | else() | |
|
285 | set(vera_program "${VERA++_EXECUTABLE}") | |
|
286 | endif() | |
|
287 | ||
|
288 | set(checkstylereports) | |
|
289 | set(reportNb 0) | |
|
290 | set(reportsrcs) | |
|
291 | list(GET srcs 0 first) | |
|
292 | get_filename_component(currentDir ${first} PATH) | |
|
293 | # add a fake src file in a fake dir to trigger the creation of the last | |
|
294 | # custom command | |
|
295 | list(APPEND srcs "#12345678900987654321#/0987654321#1234567890") | |
|
296 | # Create the directory where the reports will be saved | |
|
297 | SET(checkstyleDirectory "${CMAKE_CURRENT_BINARY_DIR}/checkstyle") | |
|
298 | FILE(MAKE_DIRECTORY ${checkstyleDirectory}) | |
|
299 | foreach(s ${srcs}) | |
|
300 | get_filename_component(d ${s} PATH) | |
|
301 | if(NOT "${d}" STREQUAL "${currentDir}") | |
|
302 | # this is a new dir - lets generate everything needed for the previous dir | |
|
303 | string(LENGTH "${CMAKE_SOURCE_DIR}" len) | |
|
304 | string(SUBSTRING "${currentDir}" 0 ${len} pre) | |
|
305 | if("${pre}" STREQUAL "${CMAKE_SOURCE_DIR}") | |
|
306 | string(SUBSTRING "${currentDir}" ${len} -1 currentDir) | |
|
307 | string(REGEX REPLACE "^/" "" currentDir "${currentDir}") | |
|
308 | endif() | |
|
309 | if("${currentDir}" STREQUAL "") | |
|
310 | set(currentDir ".") | |
|
311 | endif() | |
|
312 | set(checkstylereport ${checkstyleDirectory}/vera_checkstylereport_${reportNb}.xml) | |
|
313 | add_custom_command( | |
|
314 | OUTPUT ${checkstylereport} | |
|
315 | COMMAND ${vera_program} | |
|
316 | --root ${root} | |
|
317 | --profile ${profile} | |
|
318 | --show-rule | |
|
319 | --checkstyle-report ${checkstylereport} | |
|
320 | ${exclusions} | |
|
321 | ${parameters} | |
|
322 | ${parameterFiles} | |
|
323 | ${reportsrcs} | |
|
324 | DEPENDS ${reportsrcs} | |
|
325 | COMMENT "Checking style with vera++ in ${currentDir}" | |
|
326 | ) | |
|
327 | list(APPEND checkstylereports ${checkstylereport}) | |
|
328 | vera_incr(reportNb) | |
|
329 | # clear the list for the next dir | |
|
330 | set(reportsrcs) | |
|
331 | set(currentDir ${d}) | |
|
332 | endif() | |
|
333 | list(APPEND reportsrcs ${s}) | |
|
334 | endforeach() | |
|
335 | # Create the custom targets that will trigger the custom command created | |
|
336 | # previously | |
|
337 | add_custom_target(${target} DEPENDS ${checkstylereports}) | |
|
338 | endfunction() | |
|
339 | ||
|
340 | macro(vera_incr var_name) | |
|
341 | math(EXPR ${var_name} "${${var_name}} + 1") | |
|
342 | endmacro() |
@@ -0,0 +1,26 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # This file defines the set of scripts (rules) that should be executed | |
|
3 | # by default (if no specific profile is named when vera++ is launched). | |
|
4 | ||
|
5 | set rules { | |
|
6 | IPSIS_F11 | |
|
7 | IPSIS_F13 | |
|
8 | ||
|
9 | IPSIS_S01 | |
|
10 | IPSIS_S02 | |
|
11 | IPSIS_S03 | |
|
12 | IPSIS_S04_FILENAME | |
|
13 | IPSIS_S04_NAMESPACE | |
|
14 | IPSIS_S04_CLASS | |
|
15 | IPSIS_S04_ENUM | |
|
16 | IPSIS_S04_TYPEDEF | |
|
17 | IPSIS_S04_METHOD | |
|
18 | IPSIS_S04_VARIABLE | |
|
19 | IPSIS_S05 | |
|
20 | IPSIS_S06 | |
|
21 | IPSIS_S09 | |
|
22 | ||
|
23 | IPSIS_C01 | |
|
24 | IPSIS_C09 | |
|
25 | IPSIS_C11 | |
|
26 | } |
@@ -0,0 +1,26 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # This file defines the set of scripts (rules) that should be executed for a | |
|
3 | # default IPSIS project. | |
|
4 | ||
|
5 | set rules { | |
|
6 | IPSIS_F11 | |
|
7 | IPSIS_F13 | |
|
8 | ||
|
9 | IPSIS_S01 | |
|
10 | IPSIS_S02 | |
|
11 | IPSIS_S03 | |
|
12 | IPSIS_S04_FILENAME | |
|
13 | IPSIS_S04_NAMESPACE | |
|
14 | IPSIS_S04_CLASS | |
|
15 | IPSIS_S04_ENUM | |
|
16 | IPSIS_S04_TYPEDEF | |
|
17 | IPSIS_S04_METHOD | |
|
18 | IPSIS_S04_VARIABLE | |
|
19 | IPSIS_S05 | |
|
20 | IPSIS_S06 | |
|
21 | IPSIS_S09 | |
|
22 | ||
|
23 | IPSIS_C01 | |
|
24 | IPSIS_C09 | |
|
25 | IPSIS_C11 | |
|
26 | } |
@@ -0,0 +1,13 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | foreach f [getSourceFileNames] { | |
|
3 | puts "Tokens in file ${f}:" | |
|
4 | foreach t [getTokens $f 1 0 -1 -1 {}] { | |
|
5 | set value [lindex $t 0] | |
|
6 | set line [lindex $t 1] | |
|
7 | set column [lindex $t 2] | |
|
8 | set name [lindex $t 3] | |
|
9 | ||
|
10 | puts "${line}/${column}\t${name}\t${value}" | |
|
11 | } | |
|
12 | puts "" | |
|
13 | } |
@@ -0,0 +1,65 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # The destructor of a class should be virtual | |
|
3 | ||
|
4 | proc createMachine {initState} { | |
|
5 | set machine [dict create state $initState bracesCounter 0] | |
|
6 | return $machine | |
|
7 | } | |
|
8 | ||
|
9 | foreach fileName [getSourceFileNames] { | |
|
10 | set machines [list] | |
|
11 | ||
|
12 | set prev1 "" | |
|
13 | set prev2 "" | |
|
14 | foreach token [getTokens $fileName 1 0 -1 -1 {class struct leftbrace rightbrace virtual compl identifier semicolon}] { | |
|
15 | set type [lindex $token 3] | |
|
16 | set line [lindex $token 1] | |
|
17 | ||
|
18 | if {$type == "class" || $type == "struct"} { | |
|
19 | lappend machines [createMachine "beforeLeftBrace"] | |
|
20 | } | |
|
21 | ||
|
22 | set machinesToKeep [list] | |
|
23 | foreach m $machines { | |
|
24 | set keepMachine 1 | |
|
25 | dict with m { | |
|
26 | if {$state == "beforeLeftBrace"} { | |
|
27 | if {$type == "leftbrace"} { | |
|
28 | set state "root" | |
|
29 | } elseif {$type == "semicolon"} { | |
|
30 | set keepMachine 0 | |
|
31 | } | |
|
32 | } elseif {$state == "root"} { | |
|
33 | if {$prev2 != "virtual" && $prev1 == "compl" && $type == "identifier"} { | |
|
34 | set dtorName [lindex $token 0] | |
|
35 | report $fileName $line "The destructor ~${dtorName}() of the class should be virtual" | |
|
36 | } | |
|
37 | ||
|
38 | if {$type == "leftbrace"} { | |
|
39 | incr bracesCounter | |
|
40 | set state "consumeBraces" | |
|
41 | } elseif {$type == "rightbrace"} { | |
|
42 | set keepMachine 0 | |
|
43 | } | |
|
44 | } elseif {$state == "consumeBraces"} { | |
|
45 | if {$type == "leftbrace"} { | |
|
46 | incr bracesCounter | |
|
47 | } elseif {$type == "rightbrace"} { | |
|
48 | incr bracesCounter -1 | |
|
49 | if {$bracesCounter == 0} { | |
|
50 | set state "root" | |
|
51 | } | |
|
52 | } | |
|
53 | } | |
|
54 | } | |
|
55 | ||
|
56 | if {$keepMachine} { | |
|
57 | lappend machinesToKeep $m | |
|
58 | } | |
|
59 | } | |
|
60 | set machines $machinesToKeep | |
|
61 | ||
|
62 | set prev2 $prev1 | |
|
63 | set prev1 $type | |
|
64 | } | |
|
65 | } |
@@ -0,0 +1,23 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # using namespace are not allowed in header files | |
|
3 | ||
|
4 | foreach fileName [getSourceFileNames] { | |
|
5 | set extension [file extension $fileName] | |
|
6 | if {[lsearch {.h .hh .hpp .hxx .ipp} $extension] != -1} { | |
|
7 | ||
|
8 | set state "start" | |
|
9 | foreach token [getTokens $fileName 1 0 -1 -1 {using namespace identifier}] { | |
|
10 | set type [lindex $token 3] | |
|
11 | ||
|
12 | if {$state == "using" && $type == "namespace"} { | |
|
13 | report $fileName $usingLine "using namespace not allowed in header file" | |
|
14 | } | |
|
15 | ||
|
16 | if {$type == "using"} { | |
|
17 | set usingLine [lindex $token 1] | |
|
18 | } | |
|
19 | ||
|
20 | set state $type | |
|
21 | } | |
|
22 | } | |
|
23 | } |
@@ -0,0 +1,103 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Exceptions should be thrown by value and catched by reference. | |
|
3 | # Moreover a rethrow must be done with throw; | |
|
4 | ||
|
5 | proc createThrowMachine {line initState} { | |
|
6 | set machine [dict create name "throw" keywordLine $line state $initState bracesCounter 0 firstKeyword ""] | |
|
7 | return $machine | |
|
8 | } | |
|
9 | ||
|
10 | proc createCatchMachine {line initState} { | |
|
11 | set machine [dict create name "catch" keywordLine $line state $initState bracesCounter 0 catchedException ""] | |
|
12 | return $machine | |
|
13 | } | |
|
14 | ||
|
15 | foreach fileName [getSourceFileNames] { | |
|
16 | set machines [list] | |
|
17 | ||
|
18 | set lastIdentifier "" | |
|
19 | set prev1 "" | |
|
20 | set prev2 "" | |
|
21 | set prev3 "" | |
|
22 | foreach token [getTokens $fileName 1 0 -1 -1 {throw catch new leftbrace rightbrace greater and identifier rightparen semicolon}] { | |
|
23 | set type [lindex $token 3] | |
|
24 | set line [lindex $token 1] | |
|
25 | ||
|
26 | if {$type == "identifier"} { | |
|
27 | set lastIdentifier [lindex $token 0] | |
|
28 | } | |
|
29 | ||
|
30 | if {$type == "throw"} { | |
|
31 | lappend machines [createThrowMachine $line "beforeThrow"] | |
|
32 | } elseif {$type == "catch"} { | |
|
33 | lappend machines [createCatchMachine $line "waitingForLeftBrace"] | |
|
34 | } | |
|
35 | ||
|
36 | set machinesToKeep [list] | |
|
37 | foreach m $machines { | |
|
38 | set keepMachine 1 | |
|
39 | dict with m { | |
|
40 | if {$name == "throw"} { | |
|
41 | if {$state == "beforeThrow" && $type == "throw"} { | |
|
42 | set state "catchFirstKeyword" | |
|
43 | } elseif {$state == "catchFirstKeyword"} { | |
|
44 | if {$type == "semicolon"} { | |
|
45 | # This is a rethrow | |
|
46 | set keepMachine 0 | |
|
47 | } else { | |
|
48 | set firstKeyword $type | |
|
49 | set state "waitForEndOfThrow" | |
|
50 | } | |
|
51 | } elseif {$state == "waitForEndOfThrow"} { | |
|
52 | if {$type == "leftbrace"} { | |
|
53 | # This is an exception specification | |
|
54 | set keepMachine 0 | |
|
55 | } elseif {$type == "semicolon"} { | |
|
56 | # This is a throw, check that the first keyword isn't | |
|
57 | # new or & | |
|
58 | if {$firstKeyword == "new" || $firstKeyword == "and"} { | |
|
59 | report $fileName $keywordLine "Exceptions should be thrown by value. Not allocated with new or dereferenced with &." | |
|
60 | } | |
|
61 | set keepMachine 0 | |
|
62 | } | |
|
63 | } | |
|
64 | } elseif {$name == "catch"} { | |
|
65 | if {$state == "waitingForLeftBrace" && $type == "leftbrace"} { | |
|
66 | set state "insideCatch" | |
|
67 | ||
|
68 | if {$prev2 == "identifier" && $prev1 == "rightparen"} { | |
|
69 | set catchedException $lastIdentifier | |
|
70 | ||
|
71 | if {$prev3 != "and"} { | |
|
72 | report $fileName $keywordLine "Exceptions should be catched by reference (exception catched: $catchedException)" | |
|
73 | } | |
|
74 | } | |
|
75 | } elseif {$state == "insideCatch"} { | |
|
76 | if {$type == "leftbrace"} { | |
|
77 | incr bracesCounter | |
|
78 | } elseif {$type == "rightbrace"} { | |
|
79 | if {$bracesCounter > 0} { | |
|
80 | incr bracesCounter -1 | |
|
81 | } else { | |
|
82 | set keepMachine 0 | |
|
83 | } | |
|
84 | } elseif {$prev2 == "throw" && $prev1 == "identifier" && $type == "semicolon"} { | |
|
85 | if {$lastIdentifier == $catchedException} { | |
|
86 | report $fileName $line "Exceptions should be rethrown with 'throw;' instead of 'throw ${catchedException};'" | |
|
87 | } | |
|
88 | } | |
|
89 | } | |
|
90 | } | |
|
91 | } | |
|
92 | ||
|
93 | if {$keepMachine} { | |
|
94 | lappend machinesToKeep $m | |
|
95 | } | |
|
96 | } | |
|
97 | set machines $machinesToKeep | |
|
98 | ||
|
99 | set prev3 $prev2 | |
|
100 | set prev2 $prev1 | |
|
101 | set prev1 $type | |
|
102 | } | |
|
103 | } |
@@ -0,0 +1,39 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # control structures should have complete curly-braced block of code | |
|
3 | ||
|
4 | foreach fileName [getSourceFileNames] { | |
|
5 | ||
|
6 | set state "start" | |
|
7 | set prev "" | |
|
8 | foreach token [getTokens $fileName 1 0 -1 -1 {for if while do leftparen rightparen leftbrace rightbrace semicolon}] { | |
|
9 | set type [lindex $token 3] | |
|
10 | ||
|
11 | if {$state == "control"} { | |
|
12 | if {$type == "leftparen"} { | |
|
13 | incr parenCount | |
|
14 | } elseif {$type == "rightparen"} { | |
|
15 | incr parenCount -1 | |
|
16 | if {$parenCount == 0} { | |
|
17 | set state "expectedblock" | |
|
18 | } | |
|
19 | } | |
|
20 | } elseif {$state == "expectedblock"} { | |
|
21 | if {$type != "leftbrace"} { | |
|
22 | set line [lindex $token 1] | |
|
23 | report $fileName $line "full block {} expected in the control structure" | |
|
24 | } | |
|
25 | set state "block" | |
|
26 | } | |
|
27 | ||
|
28 | if {$type == "for" || $type == "if"} { | |
|
29 | set parenCount 0 | |
|
30 | set state "control" | |
|
31 | } elseif {$type == "do"} { | |
|
32 | set state "expectedblock" | |
|
33 | } elseif {$type == "while" && $prev != "rightbrace"} { | |
|
34 | set parenCount 0 | |
|
35 | set state "control" | |
|
36 | } | |
|
37 | set prev $type | |
|
38 | } | |
|
39 | } |
@@ -0,0 +1,73 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # namespace names should be recalled at the end of the namespace | |
|
3 | # namespace mynamespace { | |
|
4 | # } // mynamespace | |
|
5 | ||
|
6 | proc createNamespaceDict {} { | |
|
7 | return [dict create state "waitingForIdentifier" identifier "" bracesCounter 0] | |
|
8 | } | |
|
9 | ||
|
10 | foreach fileName [getSourceFileNames] { | |
|
11 | ||
|
12 | set namespaces [list] | |
|
13 | ||
|
14 | foreach token [getTokens $fileName 1 0 -1 -1 {namespace identifier leftbrace rightbrace semicolon cppcomment}] { | |
|
15 | set type [lindex $token 3] | |
|
16 | ||
|
17 | set namespacesToKeep [list] | |
|
18 | foreach n $namespaces { | |
|
19 | set keepNamespace 1 | |
|
20 | dict with n { | |
|
21 | if {$state == "waitingForIdentifier" && $type == "identifier"} { | |
|
22 | set state "waitingForLeftBrace" | |
|
23 | set identifier [lindex $token 0] | |
|
24 | } elseif {$state == "waitingForLeftBrace"} { | |
|
25 | if {$type == "semicolon"} { | |
|
26 | # Wasn't a namespace, remove the dict | |
|
27 | set keepNamespace 0 | |
|
28 | } elseif {$type == "leftbrace"} { | |
|
29 | set bracesCounter 0 | |
|
30 | set state "waitingForRightBrace" | |
|
31 | } | |
|
32 | } elseif {$state == "waitingForRightBrace"} { | |
|
33 | if {$type == "leftbrace"} { | |
|
34 | incr bracesCounter | |
|
35 | } elseif {$type == "rightbrace"} { | |
|
36 | if {$bracesCounter > 0} { | |
|
37 | incr bracesCounter -1 | |
|
38 | } else { | |
|
39 | set state "waitingForComment" | |
|
40 | } | |
|
41 | } | |
|
42 | } elseif {$state == "waitingForComment"} { | |
|
43 | if {$type == "cppcomment"} { | |
|
44 | set commentValue [lindex $token 0] | |
|
45 | # Check that the comment report the namespace name | |
|
46 | if {![regexp "\\m$identifier\\M" $commentValue]} { | |
|
47 | set line [lindex $token 1] | |
|
48 | set commentValue [string trim $commentValue] | |
|
49 | report $fileName $line "The namespace $identifier should have been recalled in the comment here (// $identifier). Comment found: $commentValue" | |
|
50 | } | |
|
51 | } else { | |
|
52 | # There should have been a comment here | |
|
53 | set line [lindex $token 1] | |
|
54 | report $fileName $line "The namespace $identifier should have been recalled in a comment here (// $identifier)" | |
|
55 | } | |
|
56 | # Namespace processed, remove it from the list | |
|
57 | set keepNamespace 0 | |
|
58 | } | |
|
59 | } | |
|
60 | ||
|
61 | if {$keepNamespace} { | |
|
62 | lappend namespacesToKeep $n | |
|
63 | } | |
|
64 | } | |
|
65 | set namespaces $namespacesToKeep | |
|
66 | ||
|
67 | # If the token is a namespace keyword, add a namespace dict for the next | |
|
68 | # foreach | |
|
69 | if {$type == "namespace"} { | |
|
70 | lappend namespaces [createNamespaceDict] | |
|
71 | } | |
|
72 | } | |
|
73 | } |
@@ -0,0 +1,60 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # At most one class per header file | |
|
3 | ||
|
4 | foreach fileName [getSourceFileNames] { | |
|
5 | if {[regexp {(?:\\|/)?([^\\/]+?)\.h$} $fileName matchedExpr expectedClassName]} { | |
|
6 | set state "waitingForClass" | |
|
7 | set alreadyOneClass 0 | |
|
8 | set firstClassName "" | |
|
9 | set bracesCounter 0 | |
|
10 | ||
|
11 | set lastIdentifier "" | |
|
12 | foreach token [getTokens $fileName 1 0 -1 -1 {class identifier leftbrace rightbrace colon semicolon}] { | |
|
13 | set type [lindex $token 3] | |
|
14 | ||
|
15 | if {$type == "identifier"} { | |
|
16 | set lastIdentifier [lindex $token 0] | |
|
17 | } | |
|
18 | ||
|
19 | if {$state == "waitingForClass" && $type == "class"} { | |
|
20 | set state "waitingForBeginingOfClass" | |
|
21 | } elseif {$state == "waitingForBeginingOfClass"} { | |
|
22 | if {$type == "semicolon"} { | |
|
23 | set state "waitingForClass" | |
|
24 | } elseif {$type == "leftbrace" || $type == "colon"} { | |
|
25 | # Check if this is the first class | |
|
26 | if {$alreadyOneClass} { | |
|
27 | set line [lindex $token 1] | |
|
28 | report $fileName $line "At most one public class can be defined in a header file. (class $lastIdentifier found but class $firstClassName already defined)" | |
|
29 | } else { | |
|
30 | set alreadyOneClass 1 | |
|
31 | set firstClassName $lastIdentifier | |
|
32 | ||
|
33 | # Check that the class has the same name than the file | |
|
34 | if {$lastIdentifier != $expectedClassName} { | |
|
35 | set line [lindex $token 1] | |
|
36 | report $fileName $line "The public class should have the same name than the header file. (class $lastIdentifier found but class $expectedClassName expected)" | |
|
37 | } | |
|
38 | } | |
|
39 | if {$type == "leftbrace"} { | |
|
40 | set state "waitingForEndOfClass" | |
|
41 | } else { | |
|
42 | set state "waitingForLeftBrace" | |
|
43 | } | |
|
44 | } | |
|
45 | } elseif {$state == "waitingForLeftBrace" && $type == "leftbrace"} { | |
|
46 | set state "waitingForEndOfClass" | |
|
47 | } elseif {$state == "waitingForEndOfClass"} { | |
|
48 | if {$type == "leftbrace"} { | |
|
49 | incr bracesCounter | |
|
50 | } elseif {$type == "rightbrace"} { | |
|
51 | if {$bracesCounter > 0} { | |
|
52 | incr bracesCounter -1 | |
|
53 | } else { | |
|
54 | set state "waitingForClass" | |
|
55 | } | |
|
56 | } | |
|
57 | } | |
|
58 | } | |
|
59 | } | |
|
60 | } |
@@ -0,0 +1,45 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # The include guards should have the form PROJECT_FILENAME_H | |
|
3 | ||
|
4 | set projectName [string toupper [getParameter "project-name" "PROJECTNAMENOTFOUND"]] | |
|
5 | ||
|
6 | foreach fileName [getSourceFileNames] { | |
|
7 | if {[regexp {(?:\\|/)?([^\\/]+?)\.h$} $fileName matchedExpr fileNameWithoutExt]} { | |
|
8 | set upperFileName [string toupper $fileNameWithoutExt] | |
|
9 | set expectedGuard "${projectName}_${upperFileName}_H" | |
|
10 | ||
|
11 | set state "waitingForIfndef" | |
|
12 | ||
|
13 | set firstInstruction 1 | |
|
14 | set ifndefLine -1 | |
|
15 | set prev "" | |
|
16 | foreach token [getTokens $fileName 1 0 -1 -1 {pp_ifndef pp_ifdef pp_if pp_include pp_define pp_undef pp_error pp_pragma pp_endif identifier}] { | |
|
17 | set type [lindex $token 3] | |
|
18 | set line [lindex $token 1] | |
|
19 | ||
|
20 | if {$firstInstruction} { | |
|
21 | set firstInstruction 0 | |
|
22 | if {$type != "pp_ifndef"} { | |
|
23 | report $fileName $line "The first preprocessor instruction of a header file should be the include guard of the form PROJECTNAME_FILENAME_H. (expected: $expectedGuard)" | |
|
24 | break | |
|
25 | } else { | |
|
26 | set ifndefLine $line | |
|
27 | } | |
|
28 | } | |
|
29 | ||
|
30 | if {$prev == "pp_ifndef"} { | |
|
31 | if {$type == "identifier"} { | |
|
32 | set identifier [lindex $token 0] | |
|
33 | if {$identifier != $expectedGuard} { | |
|
34 | report $fileName $ifndefLine "The include guard should have the form PROJECTNAME_FILENAME_H. (Found $identifier, expected $expectedGuard)" | |
|
35 | } | |
|
36 | } else { | |
|
37 | report $fileName $ifndefLine "The first preprocessor instruction of a header file should be the include guard of the form PROJECTNAME_FILENAME_H. (expected: $expectedGuard)" | |
|
38 | } | |
|
39 | break | |
|
40 | } | |
|
41 | ||
|
42 | set prev $type | |
|
43 | } | |
|
44 | } | |
|
45 | } |
@@ -0,0 +1,25 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # The macros in header files should begin with the name of the project to avoid | |
|
3 | # collisions | |
|
4 | ||
|
5 | set projectName [string toupper [getParameter "project-name" "PROJECTNAMENOTFOUND"]] | |
|
6 | ||
|
7 | foreach fileName [getSourceFileNames] { | |
|
8 | if {[regexp {\.h$} $fileName]} { | |
|
9 | ||
|
10 | set prev "" | |
|
11 | foreach token [getTokens $fileName 1 0 -1 -1 {pp_define identifier}] { | |
|
12 | set type [lindex $token 3] | |
|
13 | ||
|
14 | if {$prev == "pp_define" && $type == "identifier"} { | |
|
15 | set identifier [lindex $token 0] | |
|
16 | if {![regexp "^${projectName}.*$" $identifier]} { | |
|
17 | set line [lindex $token 1] | |
|
18 | report $fileName $line "The macros in header files should begin with the name of the project to avoid collisions. (project name: $projectName, macro found: $identifier)" | |
|
19 | } | |
|
20 | } | |
|
21 | ||
|
22 | set prev $type | |
|
23 | } | |
|
24 | } | |
|
25 | } |
@@ -0,0 +1,124 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Naming conventions for classes and structs | |
|
3 | ||
|
4 | set classRegex [getParameter "class-regex" {^[A-Z][A-Za-z1-9]*$}] | |
|
5 | set structRegex [getParameter "struct-regex" {^[A-Z][A-Za-z1-9]*$}] | |
|
6 | ||
|
7 | proc createMachine {machineName initState} { | |
|
8 | set machine [dict create name $machineName state $initState identifier "" bracesCounter 0 bracketCounter 0 angleBracketCounter 0] | |
|
9 | ||
|
10 | return $machine | |
|
11 | } | |
|
12 | ||
|
13 | proc isClassMacro {value} { | |
|
14 | set classMacroRegexp [getParameter "classmacro-regex" {}] | |
|
15 | set classMacros { | |
|
16 | "Q_OBJECT" | |
|
17 | } | |
|
18 | set isClassMacroByRegexp 0 | |
|
19 | if {[string length $classMacroRegexp] != 0} { | |
|
20 | set isClassMacroByRegexp [regexp $classMacroRegexp $value] | |
|
21 | } | |
|
22 | return [expr ([lsearch $classMacros $value] != -1) || $isClassMacroByRegexp] | |
|
23 | } | |
|
24 | ||
|
25 | proc isCppType {type value} { | |
|
26 | set cppTypes { | |
|
27 | "bool" | |
|
28 | "char" | |
|
29 | "int" | |
|
30 | "float" | |
|
31 | "double" | |
|
32 | "void" | |
|
33 | "wchart" | |
|
34 | "identifier" | |
|
35 | } | |
|
36 | ||
|
37 | set valueIsClassMacro 0 | |
|
38 | if {$type == "identifier"} { | |
|
39 | set valueIsClassMacro [isClassMacro $value] | |
|
40 | } | |
|
41 | ||
|
42 | return [expr ([lsearch $cppTypes $type] != -1) && !$valueIsClassMacro] | |
|
43 | } | |
|
44 | ||
|
45 | set tokenFilter { | |
|
46 | class | |
|
47 | struct | |
|
48 | leftbrace | |
|
49 | rightbrace | |
|
50 | semicolon | |
|
51 | colon | |
|
52 | identifier | |
|
53 | comma | |
|
54 | assign | |
|
55 | rightparen | |
|
56 | leftbracket | |
|
57 | } | |
|
58 | ||
|
59 | foreach fileName [getSourceFileNames] { | |
|
60 | ||
|
61 | set machines [list] | |
|
62 | ||
|
63 | set lastIdentifier "" | |
|
64 | set lastIdentifier2 "" | |
|
65 | set prev1 "" | |
|
66 | set prev2 "" | |
|
67 | foreach token [getTokens $fileName 1 0 -1 -1 $tokenFilter] { | |
|
68 | set type [lindex $token 3] | |
|
69 | set line [lindex $token 1] | |
|
70 | ||
|
71 | # Retrieve identifier value | |
|
72 | if {$type == "identifier"} { | |
|
73 | set lastIdentifier2 $lastIdentifier | |
|
74 | set lastIdentifier [lindex $token 0] | |
|
75 | } | |
|
76 | ||
|
77 | # If the type is a class or a struct, start a class/struct state machine | |
|
78 | if {$type == "class"} { | |
|
79 | lappend machines [createMachine "class" "waitingForIdentifier"] | |
|
80 | } | |
|
81 | if {$type == "struct"} { | |
|
82 | lappend machines [createMachine "struct" "waitingForIdentifier"] | |
|
83 | } | |
|
84 | ||
|
85 | set machinesToKeep [list] | |
|
86 | foreach m $machines { | |
|
87 | set keepMachine 1 | |
|
88 | dict with m { | |
|
89 | # class/struct | |
|
90 | if {$name == "class" || $name == "struct"} { | |
|
91 | # We retrieve the name of the class when we find a colon or | |
|
92 | # a leftbrace. We wait for these tokens to avoid the export | |
|
93 | # macros | |
|
94 | if {$state == "waitingForIdentifier" && ($type == "colon" || $type == "leftbrace")} { | |
|
95 | set state "waitingForLeftBrace" | |
|
96 | set identifier $lastIdentifier | |
|
97 | } | |
|
98 | ||
|
99 | if {$state == "waitingForLeftBrace" && $type == "leftbrace"} { | |
|
100 | if {$name == "class" && ![regexp $classRegex $identifier]} { | |
|
101 | report $fileName $line "The class names should match the following regex: $classRegex (found: $identifier)" | |
|
102 | } | |
|
103 | if {$name == "struct" && ![regexp $structRegex $identifier]} { | |
|
104 | report $fileName $line "The struct names should match the following regex: $structRegex (found: $identifier)" | |
|
105 | } | |
|
106 | } | |
|
107 | ||
|
108 | if {[lsearch {semicolon leftbrace comma assign rightparen leftbracket} $type] != -1} { | |
|
109 | # End of the state machine | |
|
110 | set keepMachine 0 | |
|
111 | } | |
|
112 | } | |
|
113 | } | |
|
114 | ||
|
115 | if {$keepMachine} { | |
|
116 | lappend machinesToKeep $m | |
|
117 | } | |
|
118 | } | |
|
119 | set machines $machinesToKeep | |
|
120 | ||
|
121 | set prev2 $prev1 | |
|
122 | set prev1 $type | |
|
123 | } | |
|
124 | } |
@@ -0,0 +1,41 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Naming conventions for enums | |
|
3 | ||
|
4 | set enumRegex [getParameter "enum-regex" {^[A-Z][A-Za-z1-9]*$}] | |
|
5 | ||
|
6 | set tokenFilter { | |
|
7 | class | |
|
8 | struct | |
|
9 | enum | |
|
10 | typedef | |
|
11 | identifier | |
|
12 | leftbrace | |
|
13 | rightbrace | |
|
14 | semicolon | |
|
15 | } | |
|
16 | ||
|
17 | foreach fileName [getSourceFileNames] { | |
|
18 | ||
|
19 | set lastIdentifier "" | |
|
20 | set prev1 "" | |
|
21 | set prev2 "" | |
|
22 | foreach token [getTokens $fileName 1 0 -1 -1 $tokenFilter] { | |
|
23 | set type [lindex $token 3] | |
|
24 | set line [lindex $token 1] | |
|
25 | ||
|
26 | # Retrieve identifier value | |
|
27 | if {$type == "identifier"} { | |
|
28 | set lastIdentifier [lindex $token 0] | |
|
29 | } | |
|
30 | ||
|
31 | # Check enum | |
|
32 | if {$prev2 == "enum" && $prev1 == "identifier" && $type == "leftbrace"} { | |
|
33 | if {![regexp $enumRegex $lastIdentifier]} { | |
|
34 | report $fileName $line "The enum names should match the following regex: $enumRegex (found: $lastIdentifier)" | |
|
35 | } | |
|
36 | } | |
|
37 | ||
|
38 | set prev2 $prev1 | |
|
39 | set prev1 $type | |
|
40 | } | |
|
41 | } |
@@ -0,0 +1,13 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Naming conventions for file names | |
|
3 | ||
|
4 | set fileNameRegex [getParameter "filename-regex" {^[A-Z]\w*$}] | |
|
5 | ||
|
6 | foreach fileName [getSourceFileNames] { | |
|
7 | # Check file name | |
|
8 | if {[regexp {(?:\\|/)?([^\\/]+?)\.(?:h|cpp)$} $fileName matchedExpr fileNameWithoutExt]} { | |
|
9 | if {![regexp $fileNameRegex $fileNameWithoutExt]} { | |
|
10 | report $fileName 1 "The file names should match the following regex: $fileNameRegex (found: $fileNameWithoutExt)" | |
|
11 | } | |
|
12 | } | |
|
13 | } |
@@ -0,0 +1,152 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Naming conventions for methods | |
|
3 | ||
|
4 | set methodRegex [getParameter "method-regex" {^[a-z][A-Za-z1-9]*$}] | |
|
5 | ||
|
6 | proc createMachine {machineName initState} { | |
|
7 | set machine [dict create name $machineName state $initState identifier "" bracesCounter 0 bracketCounter 0 angleBracketCounter 0] | |
|
8 | return $machine | |
|
9 | } | |
|
10 | ||
|
11 | proc isClassMacro {value} { | |
|
12 | set classMacroRegexp [getParameter "classmacro-regex" {}] | |
|
13 | set classMacros { | |
|
14 | "Q_OBJECT" | |
|
15 | } | |
|
16 | set isClassMacroByRegexp 0 | |
|
17 | if {[string length $classMacroRegexp] != 0} { | |
|
18 | set isClassMacroByRegexp [regexp $classMacroRegexp $value] | |
|
19 | } | |
|
20 | return [expr ([lsearch $classMacros $value] != -1) || $isClassMacroByRegexp] | |
|
21 | } | |
|
22 | ||
|
23 | proc isCppType {type value} { | |
|
24 | set cppTypes { | |
|
25 | "bool" | |
|
26 | "char" | |
|
27 | "int" | |
|
28 | "float" | |
|
29 | "double" | |
|
30 | "void" | |
|
31 | "wchart" | |
|
32 | "identifier" | |
|
33 | } | |
|
34 | ||
|
35 | set valueIsClassMacro 0 | |
|
36 | if {$type == "identifier"} { | |
|
37 | set valueIsClassMacro [isClassMacro $value] | |
|
38 | } | |
|
39 | ||
|
40 | return [expr ([lsearch $cppTypes $type] != -1) && !$valueIsClassMacro] | |
|
41 | } | |
|
42 | ||
|
43 | set tokenFilter { | |
|
44 | namespace | |
|
45 | class | |
|
46 | struct | |
|
47 | leftbrace | |
|
48 | rightbrace | |
|
49 | leftparen | |
|
50 | rightparen | |
|
51 | less | |
|
52 | greater | |
|
53 | semicolon | |
|
54 | identifier | |
|
55 | colon_colon | |
|
56 | assign | |
|
57 | pp_define | |
|
58 | bool | |
|
59 | char | |
|
60 | int | |
|
61 | float | |
|
62 | double | |
|
63 | void | |
|
64 | wchart | |
|
65 | } | |
|
66 | ||
|
67 | foreach fileName [getSourceFileNames] { | |
|
68 | ||
|
69 | set machines [list] | |
|
70 | ||
|
71 | # Check the functions at the root of the file | |
|
72 | lappend machines [createMachine "method" "root"] | |
|
73 | ||
|
74 | set lastIdentifier "" | |
|
75 | set lastIdentifier2 "" | |
|
76 | set prev1 "" | |
|
77 | set prev2 "" | |
|
78 | foreach token [getTokens $fileName 1 0 -1 -1 $tokenFilter] { | |
|
79 | set type [lindex $token 3] | |
|
80 | set line [lindex $token 1] | |
|
81 | ||
|
82 | # Retrieve identifier value | |
|
83 | if {$type == "identifier"} { | |
|
84 | set lastIdentifier2 $lastIdentifier | |
|
85 | set lastIdentifier [lindex $token 0] | |
|
86 | } | |
|
87 | ||
|
88 | # Start a method state machine when coming accross a namespace or a | |
|
89 | # class/struct | |
|
90 | if {$type == "namespace" || $type == "class" || $type == "struct"} { | |
|
91 | lappend machines [createMachine "method" "beforeLeftBrace"] | |
|
92 | } | |
|
93 | ||
|
94 | set machinesToKeep [list] | |
|
95 | foreach m $machines { | |
|
96 | set keepMachine 1 | |
|
97 | dict with m { | |
|
98 | # Method | |
|
99 | if {$name == "method"} { | |
|
100 | if {$state == "beforeLeftBrace"} { | |
|
101 | if {$type == "leftbrace"} { | |
|
102 | set state "root" | |
|
103 | } elseif {$type == "semicolon"} { | |
|
104 | set keepMachine 0 | |
|
105 | } | |
|
106 | } elseif {$state == "root"} { | |
|
107 | if {[isCppType $prev2 $lastIdentifier2] && $prev1 == "identifier" && $type == "leftparen"} { | |
|
108 | if {![regexp $methodRegex $lastIdentifier]} { | |
|
109 | report $fileName $line "The method names should match the following regex: $methodRegex (found: $lastIdentifier)" | |
|
110 | } | |
|
111 | } elseif {$type == "leftbrace"} { | |
|
112 | set state "consumeBraces" | |
|
113 | incr bracesCounter | |
|
114 | } elseif {$type == "less"} { | |
|
115 | set state "consumeAngleBracket" | |
|
116 | incr angleBracketCounter | |
|
117 | } elseif {$type == "rightbrace"} { | |
|
118 | # End of the state machine | |
|
119 | set keepMachine 0 | |
|
120 | } | |
|
121 | } elseif {$state == "consumeBraces"} { | |
|
122 | if {$type == "leftbrace"} { | |
|
123 | incr bracesCounter | |
|
124 | } elseif {$type == "rightbrace"} { | |
|
125 | incr bracesCounter -1 | |
|
126 | if {$bracesCounter == 0} { | |
|
127 | set state "root" | |
|
128 | } | |
|
129 | } | |
|
130 | } elseif {$state == "consumeAngleBracket"} { | |
|
131 | if {$type == "less"} { | |
|
132 | incr angleBracketCounter | |
|
133 | } elseif {$type == "greater"} { | |
|
134 | incr angleBracketCounter -1 | |
|
135 | if {$angleBracketCounter == 0} { | |
|
136 | set state "root" | |
|
137 | } | |
|
138 | } | |
|
139 | } | |
|
140 | } | |
|
141 | } | |
|
142 | ||
|
143 | if {$keepMachine} { | |
|
144 | lappend machinesToKeep $m | |
|
145 | } | |
|
146 | } | |
|
147 | set machines $machinesToKeep | |
|
148 | ||
|
149 | set prev2 $prev1 | |
|
150 | set prev1 $type | |
|
151 | } | |
|
152 | } |
@@ -0,0 +1,49 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Naming conventions for namespaces | |
|
3 | ||
|
4 | set namespaceRegex [getParameter "namespace-regex" {^[a-z][a-z1-9]*$}] | |
|
5 | ||
|
6 | proc createMachine {machineName initState} { | |
|
7 | set machine [dict create name $machineName state $initState identifier "" bracesCounter 0 bracketCounter 0 angleBracketCounter 0] | |
|
8 | return $machine | |
|
9 | } | |
|
10 | ||
|
11 | set tokenFilter { | |
|
12 | using | |
|
13 | namespace | |
|
14 | identifier | |
|
15 | class | |
|
16 | struct | |
|
17 | enum | |
|
18 | typedef | |
|
19 | leftbrace | |
|
20 | rightbrace | |
|
21 | } | |
|
22 | ||
|
23 | foreach fileName [getSourceFileNames] { | |
|
24 | ||
|
25 | set machines [list] | |
|
26 | ||
|
27 | set lastIdentifier "" | |
|
28 | set prev1 "" | |
|
29 | set prev2 "" | |
|
30 | foreach token [getTokens $fileName 1 0 -1 -1 $tokenFilter] { | |
|
31 | set type [lindex $token 3] | |
|
32 | set line [lindex $token 1] | |
|
33 | ||
|
34 | # Retrieve identifier value | |
|
35 | if {$type == "identifier"} { | |
|
36 | set lastIdentifier [lindex $token 0] | |
|
37 | } | |
|
38 | ||
|
39 | # Check namespace | |
|
40 | if {$prev2 == "namespace" && $prev1 == "identifier" && $type == "leftbrace"} { | |
|
41 | if {![regexp $namespaceRegex $lastIdentifier]} { | |
|
42 | report $fileName $line "The namespace names should match the following regex: $namespaceRegex (found: $lastIdentifier)" | |
|
43 | } | |
|
44 | } | |
|
45 | ||
|
46 | set prev2 $prev1 | |
|
47 | set prev1 $type | |
|
48 | } | |
|
49 | } |
@@ -0,0 +1,87 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Naming conventions for typedefs | |
|
3 | ||
|
4 | set typedefRegex [getParameter "type-regex" {^[A-Z][A-Za-z1-9]*$}] | |
|
5 | ||
|
6 | proc createMachine {machineName initState} { | |
|
7 | set machine [dict create name $machineName state $initState identifier "" bracesCounter 0] | |
|
8 | return $machine | |
|
9 | } | |
|
10 | ||
|
11 | set tokenFilter { | |
|
12 | typedef | |
|
13 | leftbrace | |
|
14 | rightbrace | |
|
15 | semicolon | |
|
16 | identifier | |
|
17 | } | |
|
18 | ||
|
19 | foreach fileName [getSourceFileNames] { | |
|
20 | ||
|
21 | set machines [list] | |
|
22 | ||
|
23 | set lastIdentifier "" | |
|
24 | set lastIdentifier2 "" | |
|
25 | set prev1 "" | |
|
26 | set prev2 "" | |
|
27 | foreach token [getTokens $fileName 1 0 -1 -1 $tokenFilter] { | |
|
28 | set type [lindex $token 3] | |
|
29 | set line [lindex $token 1] | |
|
30 | ||
|
31 | # Retrieve identifier value | |
|
32 | if {$type == "identifier"} { | |
|
33 | set lastIdentifier2 $lastIdentifier | |
|
34 | set lastIdentifier [lindex $token 0] | |
|
35 | } | |
|
36 | ||
|
37 | # If the type is a typedef, start a typedef state machine | |
|
38 | if {$type == "typedef"} { | |
|
39 | lappend machines [createMachine "typedef" "waitingForIdentifier"] | |
|
40 | } | |
|
41 | ||
|
42 | set machinesToKeep [list] | |
|
43 | foreach m $machines { | |
|
44 | set keepMachine 1 | |
|
45 | dict with m { | |
|
46 | # typedef | |
|
47 | if {$name == "typedef"} { | |
|
48 | if {$state == "waitingForIdentifier"} { | |
|
49 | if {$type == "leftbrace"} { | |
|
50 | set state "consumeBraces" | |
|
51 | incr bracesCounter | |
|
52 | } elseif {$type == "semicolon"} { | |
|
53 | if {$prev1 == "identifier"} { | |
|
54 | # Check identifier | |
|
55 | if {![regexp $typedefRegex $lastIdentifier]} { | |
|
56 | report $fileName $line "The typedef names should match the following regex: $typedefRegex (found: $lastIdentifier)" | |
|
57 | } | |
|
58 | } else { | |
|
59 | # Typedef without identifier | |
|
60 | report $fileName $line "A typedef should have a name" | |
|
61 | } | |
|
62 | # End of the state machine | |
|
63 | set keepMachine 0 | |
|
64 | } | |
|
65 | } elseif {$state == "consumeBraces"} { | |
|
66 | if {$type == "leftbrace"} { | |
|
67 | incr bracesCounter | |
|
68 | } elseif {$type == "rightbrace"} { | |
|
69 | incr bracesCounter -1 | |
|
70 | if {$bracesCounter == 0} { | |
|
71 | set state "waitingForIdentifier" | |
|
72 | } | |
|
73 | } | |
|
74 | } | |
|
75 | } | |
|
76 | } | |
|
77 | ||
|
78 | if {$keepMachine} { | |
|
79 | lappend machinesToKeep $m | |
|
80 | } | |
|
81 | } | |
|
82 | set machines $machinesToKeep | |
|
83 | ||
|
84 | set prev2 $prev1 | |
|
85 | set prev1 $type | |
|
86 | } | |
|
87 | } |
@@ -0,0 +1,351 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Naming conventions for variables | |
|
3 | ||
|
4 | set localVariableRegex [getParameter "local-var-regex" {^[a-z][A-Za-z1-9]*$}] | |
|
5 | set classMemberVariableRegex [getParameter "class-member-var-regex" {^m_[A-Z][A-Za-z1-9]*$}] | |
|
6 | set structMemberVariableRegex [getParameter "struct-member-var-regex" {^[a-z][A-Za-z1-9]*$}] | |
|
7 | set staticMemberVariableRegex [getParameter "static-member-var-regex" {^s_[A-Z][A-Za-z1-9]*$}] | |
|
8 | set constVarRegex [getParameter "const-var-regex" {^[A-Z][A-Z1-9_]*$}] | |
|
9 | ||
|
10 | proc createMachine {machineName initState} { | |
|
11 | set machine [dict create name $machineName state $initState previousState "" identifier "" bracesCounter 0 bracketCounter 0 angleBracketCounter 0] | |
|
12 | ||
|
13 | # Specific keys for the "memberVariable" type | |
|
14 | if {$machineName == "memberVariable"} { | |
|
15 | dict set machine parenCounter 0 | |
|
16 | dict set machine isStatic 0 | |
|
17 | dict set machine isConst 0 | |
|
18 | dict set machine isVar 1 | |
|
19 | dict set machine isTypedef 0 | |
|
20 | dict set machine isInClass 0 | |
|
21 | dict set machine classOrStruct "" | |
|
22 | } | |
|
23 | ||
|
24 | return $machine | |
|
25 | } | |
|
26 | ||
|
27 | proc isClassMacro {value} { | |
|
28 | set classMacroRegexp [getParameter "classmacro-regex" {}] | |
|
29 | set classMacros { | |
|
30 | "Q_OBJECT" | |
|
31 | } | |
|
32 | set isClassMacroByRegexp 0 | |
|
33 | if {[string length $classMacroRegexp] != 0} { | |
|
34 | set isClassMacroByRegexp [regexp $classMacroRegexp $value] | |
|
35 | } | |
|
36 | return [expr ([lsearch $classMacros $value] != -1) || $isClassMacroByRegexp] | |
|
37 | } | |
|
38 | ||
|
39 | proc isCppType {type value} { | |
|
40 | set cppTypes { | |
|
41 | "bool" | |
|
42 | "char" | |
|
43 | "int" | |
|
44 | "float" | |
|
45 | "double" | |
|
46 | "void" | |
|
47 | "wchart" | |
|
48 | "identifier" | |
|
49 | } | |
|
50 | ||
|
51 | set valueIsClassMacro 0 | |
|
52 | if {$type == "identifier"} { | |
|
53 | set valueIsClassMacro [isClassMacro $value] | |
|
54 | } | |
|
55 | ||
|
56 | return [expr ([lsearch $cppTypes $type] != -1) && !$valueIsClassMacro] | |
|
57 | } | |
|
58 | ||
|
59 | set tokenFilter { | |
|
60 | using | |
|
61 | namespace | |
|
62 | class | |
|
63 | struct | |
|
64 | enum | |
|
65 | typedef | |
|
66 | pp_define | |
|
67 | leftbrace | |
|
68 | rightbrace | |
|
69 | leftparen | |
|
70 | rightparen | |
|
71 | leftbracket | |
|
72 | rightbracket | |
|
73 | semicolon | |
|
74 | colon_colon | |
|
75 | colon | |
|
76 | comma | |
|
77 | dot | |
|
78 | arrow | |
|
79 | assign | |
|
80 | static | |
|
81 | const | |
|
82 | identifier | |
|
83 | bool | |
|
84 | char | |
|
85 | int | |
|
86 | float | |
|
87 | double | |
|
88 | void | |
|
89 | wchart | |
|
90 | return | |
|
91 | operator | |
|
92 | less | |
|
93 | greater | |
|
94 | } | |
|
95 | ||
|
96 | foreach fileName [getSourceFileNames] { | |
|
97 | set machines [list] | |
|
98 | ||
|
99 | # Check the functions at the root of the file | |
|
100 | lappend machines [createMachine "method" "root"] | |
|
101 | ||
|
102 | # Check static const variables at the root of the file | |
|
103 | lappend machines [createMachine "memberVariable" "root"] | |
|
104 | ||
|
105 | set lastIdentifier "" | |
|
106 | set lastIdentifier2 "" | |
|
107 | set prev1 "" | |
|
108 | set prev2 "" | |
|
109 | set insideFunctionParameters 0 | |
|
110 | set insideFunction 0 | |
|
111 | foreach token [getTokens $fileName 1 0 -1 -1 $tokenFilter] { | |
|
112 | set type [lindex $token 3] | |
|
113 | set line [lindex $token 1] | |
|
114 | ||
|
115 | # Retrieve identifier value | |
|
116 | if {$type == "identifier"} { | |
|
117 | set lastIdentifier2 $lastIdentifier | |
|
118 | set lastIdentifier [lindex $token 0] | |
|
119 | } | |
|
120 | ||
|
121 | if {$type == "namespace"} { | |
|
122 | # Look for the functions in the namespace to check the local variables | |
|
123 | lappend machines [createMachine "method" "beforeLeftBrace"] | |
|
124 | # Check the static const variables inside this namespace | |
|
125 | lappend machines [createMachine "memberVariable" "beforeLeftBrace"] | |
|
126 | } elseif {$type == "class" || ($type == "struct" && !$insideFunctionParameters)} { | |
|
127 | # Look for the functions in the class/struct to check the local variables | |
|
128 | lappend machines [createMachine "method" "beforeLeftBrace"] | |
|
129 | # Check the static const variables inside this namespace | |
|
130 | set m [createMachine "memberVariable" "beforeLeftBrace"] | |
|
131 | dict set m isInClass 1 | |
|
132 | dict set m classOrStruct $type | |
|
133 | lappend machines $m | |
|
134 | } | |
|
135 | ||
|
136 | set machinesToKeep [list] | |
|
137 | foreach m $machines { | |
|
138 | set keepMachine 1 | |
|
139 | dict with m { | |
|
140 | # Method | |
|
141 | if {$name == "method"} { | |
|
142 | if {$state == "beforeLeftBrace"} { | |
|
143 | if {$type == "leftbrace"} { | |
|
144 | set state "root" | |
|
145 | } elseif {$type == "semicolon"} { | |
|
146 | set keepMachine 0 | |
|
147 | } | |
|
148 | } elseif {$state == "root"} { | |
|
149 | if {[isCppType $prev2 $lastIdentifier2] && $prev1 == "identifier" && $type == "leftparen"} { | |
|
150 | # Check the local variables inside this function | |
|
151 | set insideFunctionParameters 1 | |
|
152 | set insideFunction 1 | |
|
153 | lappend machinesToKeep [createMachine "localVariable" "beforeLeftBrace"] | |
|
154 | ||
|
155 | } elseif {$type == "leftbrace"} { | |
|
156 | set state "consumeBraces" | |
|
157 | incr bracesCounter | |
|
158 | } elseif {$type == "rightbrace"} { | |
|
159 | # End of the state machine | |
|
160 | set keepMachine 0 | |
|
161 | } | |
|
162 | } elseif {$state == "consumeBraces"} { | |
|
163 | if {$type == "leftbrace"} { | |
|
164 | incr bracesCounter | |
|
165 | } elseif {$type == "rightbrace"} { | |
|
166 | incr bracesCounter -1 | |
|
167 | if {$bracesCounter == 0} { | |
|
168 | set state "root" | |
|
169 | } | |
|
170 | } | |
|
171 | } | |
|
172 | } | |
|
173 | ||
|
174 | # Local variables | |
|
175 | if {$name == "localVariable"} { | |
|
176 | if {$state == "beforeLeftBrace"} { | |
|
177 | if {$type == "less"} { | |
|
178 | set previousState $state | |
|
179 | set state "consumeAngleBracket" | |
|
180 | incr angleBracketCounter | |
|
181 | } elseif {[isCppType $prev2 $lastIdentifier2] && $prev1 == "identifier" && ($type == "comma" || $type == "assign" || $type == "rightparen" || $type == "leftbracket")} { | |
|
182 | # Check function parameters | |
|
183 | if {![regexp $localVariableRegex $lastIdentifier]} { | |
|
184 | report $fileName $line "The method parameter names should match the following regex: $localVariableRegex (found: $lastIdentifier)" | |
|
185 | } | |
|
186 | } elseif {$type == "leftbrace"} { | |
|
187 | set insideFunctionParameters 0 | |
|
188 | set state "root" | |
|
189 | } elseif {$type == "semicolon"} { | |
|
190 | # End of the state machine | |
|
191 | set insideFunctionParameters 0 | |
|
192 | set insideFunction 0 | |
|
193 | set keepMachine 0 | |
|
194 | } | |
|
195 | } elseif {$state == "root"} { | |
|
196 | if {$type == "leftbrace"} { | |
|
197 | incr bracesCounter | |
|
198 | } elseif {$type == "rightbrace"} { | |
|
199 | if {$bracesCounter > 0} { | |
|
200 | incr bracesCounter -1 | |
|
201 | } else { | |
|
202 | # End of the state machine | |
|
203 | set insideFunctionParameters 0 | |
|
204 | set insideFunction 0 | |
|
205 | set keepMachine 0 | |
|
206 | } | |
|
207 | } | |
|
208 | ||
|
209 | if {[isCppType $prev2 $lastIdentifier2] && $prev1 == "identifier" && ($type == "assign" || $type == "semicolon" || $type == "leftparen" || $type == "leftbracket")} { | |
|
210 | # Check local variable | |
|
211 | if {![regexp $localVariableRegex $lastIdentifier]} { | |
|
212 | report $fileName $line "The local variable names should match the following regex: $localVariableRegex (found: $lastIdentifier)" | |
|
213 | } | |
|
214 | } | |
|
215 | } elseif {$state == "consumeBracket"} { | |
|
216 | if {$type == "leftbracket"} { | |
|
217 | incr bracketCounter | |
|
218 | } elseif {$type == "rightbracket"} { | |
|
219 | incr bracketCounter -1 | |
|
220 | if {$bracketCounter == 0} { | |
|
221 | set state $previousState | |
|
222 | } | |
|
223 | } | |
|
224 | } elseif {$state == "consumeAngleBracket"} { | |
|
225 | if {$type == "less"} { | |
|
226 | incr angleBracketCounter | |
|
227 | } elseif {$type == "greater"} { | |
|
228 | incr angleBracketCounter -1 | |
|
229 | if {$angleBracketCounter == 0} { | |
|
230 | set state $previousState | |
|
231 | } | |
|
232 | } | |
|
233 | } | |
|
234 | ||
|
235 | if {$state != "consumeBracket" && $type == "leftbracket"} { | |
|
236 | set previousState $state | |
|
237 | set state "consumeBracket" | |
|
238 | incr bracketCounter | |
|
239 | } | |
|
240 | } | |
|
241 | ||
|
242 | # Member and const variables | |
|
243 | if {$name == "memberVariable"} { | |
|
244 | if {$state == "beforeLeftBrace"} { | |
|
245 | if {$type == "leftbrace"} { | |
|
246 | set state "root" | |
|
247 | } elseif {$type == "semicolon"} { | |
|
248 | set keepMachine 0 | |
|
249 | } | |
|
250 | } elseif {$state == "root"} { | |
|
251 | # is/isn't var | |
|
252 | if {$type == "using" || $type == "class" || $type == "struct"} { | |
|
253 | set isVar 0 | |
|
254 | } elseif {$type == "typedef"} { | |
|
255 | set isTypedef 1 | |
|
256 | } | |
|
257 | ||
|
258 | # static/const | |
|
259 | if {$type == "static"} { | |
|
260 | set isStatic 1 | |
|
261 | } elseif {$type == "const"} { | |
|
262 | set isConst 1 | |
|
263 | } | |
|
264 | ||
|
265 | if {$isVar && !$isTypedef && $prev1 == "pp_define" && $type == "identifier"} { | |
|
266 | # Check defines | |
|
267 | if {![regexp $constVarRegex $lastIdentifier]} { | |
|
268 | report $fileName $line "The constant names should match the following regex: $constVarRegex (found: $lastIdentifier)" | |
|
269 | } | |
|
270 | } elseif {$isVar && !$isTypedef && $prev1 == "identifier" && ($type == "assign" || $type == "semicolon" || $type == "leftbracket")} { | |
|
271 | # Check member variables | |
|
272 | # Appart from the const, we don't check the member variables outside | |
|
273 | # of their classes to avoid false positive | |
|
274 | if {((!$isInClass && $isConst) || ($isInClass && $isStatic && $isConst)) && ![regexp $constVarRegex $lastIdentifier]} { | |
|
275 | report $fileName $line "The constant names should match the following regex: $constVarRegex (found: $lastIdentifier)" | |
|
276 | } elseif {$isInClass && $isStatic && !$isConst && ![regexp $staticMemberVariableRegex $lastIdentifier]} { | |
|
277 | report $fileName $line "The static member variable names should match the following regex: $staticMemberVariableRegex (found: $lastIdentifier)" | |
|
278 | } elseif {$isInClass && !$isStatic} { | |
|
279 | if {$classOrStruct == "class" && ![regexp $classMemberVariableRegex $lastIdentifier]} { | |
|
280 | report $fileName $line "The class member variable names should match the following regex: $classMemberVariableRegex (found: $lastIdentifier)" | |
|
281 | } elseif {$classOrStruct == "struct" && ![regexp $structMemberVariableRegex $lastIdentifier] && ![regexp $classMemberVariableRegex $lastIdentifier]} { | |
|
282 | report $fileName $line "The struct member variable names should match the following regex: $structMemberVariableRegex or the class member regex: $classMemberVariableRegex (found: $lastIdentifier)" | |
|
283 | } | |
|
284 | } | |
|
285 | } elseif {$type == "leftbrace"} { | |
|
286 | set state "consumeBraces" | |
|
287 | incr bracesCounter | |
|
288 | } elseif {$type == "leftparen"} { | |
|
289 | set state "consumeParen" | |
|
290 | incr parenCounter | |
|
291 | } elseif {$type == "rightbrace"} { | |
|
292 | # End of the state machine | |
|
293 | set keepMachine 0 | |
|
294 | } | |
|
295 | ||
|
296 | if {$type == "leftbracket"} { | |
|
297 | incr bracketCounter | |
|
298 | set state "consumeBracket" | |
|
299 | } | |
|
300 | ||
|
301 | # Reinit static, const and isVar | |
|
302 | if {$type == "assign" || $type == "semicolon" || $type == "leftbrace"} { | |
|
303 | set isStatic 0 | |
|
304 | set isConst 0 | |
|
305 | set isVar 1 | |
|
306 | } | |
|
307 | ||
|
308 | if {$type == "semicolon"} { | |
|
309 | set isTypedef 0 | |
|
310 | } | |
|
311 | } elseif {$state == "consumeBraces"} { | |
|
312 | if {$type == "leftbrace"} { | |
|
313 | incr bracesCounter | |
|
314 | } elseif {$type == "rightbrace"} { | |
|
315 | incr bracesCounter -1 | |
|
316 | if {$bracesCounter == 0} { | |
|
317 | set state "root" | |
|
318 | } | |
|
319 | } | |
|
320 | } elseif {$state == "consumeParen"} { | |
|
321 | if {$type == "leftparen"} { | |
|
322 | incr parenCounter | |
|
323 | } elseif {$type == "rightparen"} { | |
|
324 | incr parenCounter -1 | |
|
325 | if {$parenCounter == 0} { | |
|
326 | set state "root" | |
|
327 | } | |
|
328 | } | |
|
329 | } elseif {$state == "consumeBracket"} { | |
|
330 | if {$type == "leftbracket"} { | |
|
331 | incr bracketCounter | |
|
332 | } elseif {$type == "rightbracket"} { | |
|
333 | incr bracketCounter -1 | |
|
334 | if {$bracketCounter == 0} { | |
|
335 | set state "root" | |
|
336 | } | |
|
337 | } | |
|
338 | } | |
|
339 | } | |
|
340 | } | |
|
341 | ||
|
342 | if {$keepMachine} { | |
|
343 | lappend machinesToKeep $m | |
|
344 | } | |
|
345 | } | |
|
346 | set machines $machinesToKeep | |
|
347 | ||
|
348 | set prev2 $prev1 | |
|
349 | set prev1 $type | |
|
350 | } | |
|
351 | } |
@@ -0,0 +1,329 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Declaration order inside classes | |
|
3 | ||
|
4 | proc createMachine {visibility initState} { | |
|
5 | set machine [dict create visibility $visibility state $initState waitingFor "typedef" previousState "" bracesCounter 0 isStatic 0] | |
|
6 | return $machine | |
|
7 | } | |
|
8 | ||
|
9 | proc createVisibilityMachine {} { | |
|
10 | set machine [dict create state "beforeLeftBrace" visibilityState "waitingForPublic" bracesCounter 0 visibility ""] | |
|
11 | return $machine | |
|
12 | } | |
|
13 | ||
|
14 | set tokenFilter { | |
|
15 | public | |
|
16 | protected | |
|
17 | private | |
|
18 | colon | |
|
19 | typedef | |
|
20 | class | |
|
21 | struct | |
|
22 | enum | |
|
23 | static | |
|
24 | const | |
|
25 | identifier | |
|
26 | operator | |
|
27 | assign | |
|
28 | semicolon | |
|
29 | leftbrace | |
|
30 | rightbrace | |
|
31 | leftparen | |
|
32 | rightparen | |
|
33 | } | |
|
34 | ||
|
35 | set globalOrder "The global order is public members then public slots, protected members then protected slots and private members then private slots." | |
|
36 | ||
|
37 | foreach fileName [getSourceFileNames] { | |
|
38 | set machines [list] | |
|
39 | set visibilityMachines [list] | |
|
40 | ||
|
41 | set visibilityState "waitingForPublic" | |
|
42 | ||
|
43 | set prev1 "" | |
|
44 | set prev2 "" | |
|
45 | set lastIdentifier "" | |
|
46 | foreach token [getTokens $fileName 1 0 -1 -1 $tokenFilter] { | |
|
47 | set type [lindex $token 3] | |
|
48 | set line [lindex $token 1] | |
|
49 | ||
|
50 | if {$type == "identifier"} { | |
|
51 | set lastIdentifier [lindex $token 0] | |
|
52 | } | |
|
53 | ||
|
54 | if {$type == "class" || $type == "struct"} { | |
|
55 | lappend visibilityMachines [createVisibilityMachine] | |
|
56 | } | |
|
57 | ||
|
58 | if {$type == "colon" && ($prev1 == "public" || $prev1 == "protected" || $prev1 == "private")} { | |
|
59 | lappend machines [createMachine $prev1 "beforeVisibility"] | |
|
60 | } | |
|
61 | ||
|
62 | # Machines for the visibility order | |
|
63 | set visibilityMachinesToKeep [list] | |
|
64 | foreach m $visibilityMachines { | |
|
65 | set keepMachine 1 | |
|
66 | dict with m { | |
|
67 | if {$state == "beforeLeftBrace"} { | |
|
68 | if {$type == "semicolon"} { | |
|
69 | set keepMachine 0 | |
|
70 | } elseif {$type == "leftbrace"} { | |
|
71 | set state "root" | |
|
72 | } | |
|
73 | } elseif {$state == "root"} { | |
|
74 | if {$type == "public" || $type == "protected" || $type == "private"} { | |
|
75 | set visibility $type | |
|
76 | set state "waitingForColon" | |
|
77 | } elseif {$type == "leftbrace"} { | |
|
78 | incr bracesCounter | |
|
79 | set state "consumeBraces" | |
|
80 | } elseif {$type == "rightbrace"} { | |
|
81 | set keepMachine 0 | |
|
82 | } | |
|
83 | } elseif {$state == "waitingForColon"} { | |
|
84 | if {$type == "colon"} { | |
|
85 | if {$visibility == "public" && $prev1 != "identifier"} { | |
|
86 | if {$visibilityState == "waitingForPublicSlots" | |
|
87 | || $visibilityState == "waitingForProtected" | |
|
88 | || $visibilityState == "waitingForProtectedSlots" | |
|
89 | || $visibilityState == "waitingForPrivate" | |
|
90 | || $visibilityState == "waitingForPrivateSlots" | |
|
91 | || $visibilityState == "done"} { | |
|
92 | report $fileName $line "There should be at most one public visibility and it should be at the start of the class. $globalOrder" | |
|
93 | } else { | |
|
94 | set visibilityState "waitingForPublicSlots" | |
|
95 | } | |
|
96 | } elseif {$visibility == "public" && $prev1 == "identifier" && $lastIdentifier == "slots"} { | |
|
97 | if {$visibilityState == "waitingForProtected" | |
|
98 | || $visibilityState == "waitingForProtectedSlots" | |
|
99 | || $visibilityState == "waitingForPrivate" | |
|
100 | || $visibilityState == "waitingForPrivateSlots" | |
|
101 | || $visibilityState == "done"} { | |
|
102 | report $fileName $line "There should be at most one public slots visibility and it should be between public and protected. $globalOrder" | |
|
103 | } else { | |
|
104 | set visibilityState "waitingForProtected" | |
|
105 | } | |
|
106 | } elseif {$visibility == "protected" && $prev1 != "identifier"} { | |
|
107 | if {$visibilityState == "waitingForProtectedSlots" | |
|
108 | || $visibilityState == "waitingForPrivate" | |
|
109 | || $visibilityState == "waitingForPrivateSlots" | |
|
110 | || $visibilityState == "done"} { | |
|
111 | report $fileName $line "There should be at most one protected visibility and it should be between public slots and protected slots. $globalOrder" | |
|
112 | } else { | |
|
113 | set visibilityState "waitingForProtectedSlots" | |
|
114 | } | |
|
115 | } elseif {$visibility == "protected" && $prev1 == "identifier" && $lastIdentifier == "slots"} { | |
|
116 | if {$visibilityState == "waitingForPrivate" | |
|
117 | || $visibilityState == "waitingForPrivateSlots" | |
|
118 | || $visibilityState == "done"} { | |
|
119 | report $fileName $line "There should be at most one protected slots visibility and it should be between protected and private. $globalOrder" | |
|
120 | } else { | |
|
121 | set visibilityState "waitingForPrivate" | |
|
122 | } | |
|
123 | } elseif {$visibility == "private" && $prev1 != "identifier"} { | |
|
124 | if {$visibilityState == "waitingForPrivateSlots" | |
|
125 | || $visibilityState == "done"} { | |
|
126 | report $fileName $line "There should be at most one private visibility and it should be between protected slots and private slots. $globalOrder" | |
|
127 | } else { | |
|
128 | set visibilityState "waitingForPrivateSlots" | |
|
129 | } | |
|
130 | } elseif {$visibility == "private" && $prev1 == "identifier" && $lastIdentifier == "slots"} { | |
|
131 | if {$visibilityState == "done"} { | |
|
132 | report $fileName $line "There should be at most one private visibility and it should be the last of the class. $globalOrder" | |
|
133 | } else { | |
|
134 | set visibilityState "done" | |
|
135 | } | |
|
136 | } | |
|
137 | ||
|
138 | set state "root" | |
|
139 | } | |
|
140 | } elseif {$state == "consumeBraces"} { | |
|
141 | if {$type == "leftbrace"} { | |
|
142 | incr bracesCounter | |
|
143 | } elseif {$type == "rightbrace"} { | |
|
144 | incr bracesCounter -1 | |
|
145 | if {$bracesCounter == 0} { | |
|
146 | set state "root" | |
|
147 | } | |
|
148 | } | |
|
149 | } | |
|
150 | } | |
|
151 | ||
|
152 | if {$keepMachine} { | |
|
153 | lappend visibilityMachinesToKeep $m | |
|
154 | } | |
|
155 | } | |
|
156 | set visibilityMachines $visibilityMachinesToKeep | |
|
157 | ||
|
158 | # Machines for the declaration order inside a visibility | |
|
159 | set machinesToKeep [list] | |
|
160 | foreach m $machines { | |
|
161 | set keepMachine 1 | |
|
162 | dict with m { | |
|
163 | if {$state == "beforeVisibility" && $type == $visibility} { | |
|
164 | set state "root" | |
|
165 | } elseif {$state == "root"} { | |
|
166 | if {$type == "public" || $type == "protected" || $type == "private" || $type == "rightbrace"} { | |
|
167 | # End of the state machine when we reach the next | |
|
168 | # visibility block | |
|
169 | set keepMachine 0 | |
|
170 | } else { | |
|
171 | if {$type == "static"} { | |
|
172 | set isStatic 1 | |
|
173 | } | |
|
174 | ||
|
175 | if {$waitingFor == "typedef"} { | |
|
176 | if {$type == "typedef"} { | |
|
177 | set state "consumeUntilNextSemiColon" | |
|
178 | } else { | |
|
179 | set waitingFor "enum" | |
|
180 | } | |
|
181 | } | |
|
182 | ||
|
183 | if {$waitingFor == "enum"} { | |
|
184 | if {$type == "typedef"} { | |
|
185 | set state "consumeUntilNextSemiColon" | |
|
186 | report $fileName $line "The typedefs should be before the enums" | |
|
187 | } elseif {$type == "enum"} { | |
|
188 | set state "consumeUntilNextSemiColon" | |
|
189 | } else { | |
|
190 | set waitingFor "class/struct" | |
|
191 | } | |
|
192 | } | |
|
193 | ||
|
194 | if {$waitingFor == "class/struct"} { | |
|
195 | if {$type == "typedef" || $type == "enum"} { | |
|
196 | set state "consumeUntilNextSemiColon" | |
|
197 | report $fileName $line "The typedefs and enums should be before the classes/structs" | |
|
198 | } elseif {$type == "class" || $type == "struct"} { | |
|
199 | set state "consumeUntilNextSemiColon" | |
|
200 | } else { | |
|
201 | set waitingFor "staticFunc" | |
|
202 | } | |
|
203 | } | |
|
204 | ||
|
205 | if {$waitingFor == "staticFunc"} { | |
|
206 | if {$type == "typedef" || $type == "enum" || $type == "class" || $type == "struct"} { | |
|
207 | set state "consumeUntilNextSemiColon" | |
|
208 | report $fileName $line "The typedefs, enums, classes and structs should be before the static functions" | |
|
209 | } elseif {$prev1 == "identifier"} { | |
|
210 | if {$type == "leftparen"} { | |
|
211 | if {$isStatic} { | |
|
212 | set state "consumeFunction" | |
|
213 | } else { | |
|
214 | set waitingFor "method" | |
|
215 | } | |
|
216 | } elseif {$type == "assign" || $type == "semicolon"} { | |
|
217 | set waitingFor "staticVar" | |
|
218 | } | |
|
219 | } | |
|
220 | } | |
|
221 | ||
|
222 | if {$waitingFor == "staticVar"} { | |
|
223 | if {$type == "typedef" || $type == "enum" || $type == "class" || $type == "struct"} { | |
|
224 | set state "consumeUntilNextSemiColon" | |
|
225 | report $fileName $line "The typedefs, enums, classes and structs should be before the static variables" | |
|
226 | } elseif {$prev1 == "identifier"} { | |
|
227 | if {$type == "leftparen"} { | |
|
228 | if {$isStatic} { | |
|
229 | set state "consumeFunction" | |
|
230 | report $fileName $line "The static functions should be before the static variables" | |
|
231 | } else { | |
|
232 | set waitingFor "method" | |
|
233 | } | |
|
234 | } elseif {$type == "assign" || $type == "semicolon"} { | |
|
235 | if {!$isStatic} { | |
|
236 | set waitingFor "method" | |
|
237 | } | |
|
238 | if {$type != "semicolon"} { | |
|
239 | set state "consumeUntilNextSemiColon" | |
|
240 | } else { | |
|
241 | set isStatic 0 | |
|
242 | } | |
|
243 | } | |
|
244 | } | |
|
245 | } | |
|
246 | ||
|
247 | if {$waitingFor == "method"} { | |
|
248 | if {$type == "typedef" || $type == "enum" || $type == "class" || $type == "struct"} { | |
|
249 | set state "consumeUntilNextSemiColon" | |
|
250 | report $fileName $line "The typedefs, enums, classes and structs should be before the methods" | |
|
251 | } elseif {$prev2 == "identifier" && $prev1 == "operator" && $type == "assign"} { | |
|
252 | # override of operator=() | |
|
253 | set state "consumeFunction" | |
|
254 | } elseif {$prev1 == "identifier"} { | |
|
255 | if {$type == "leftparen"} { | |
|
256 | if {$isStatic} { | |
|
257 | report $fileName $line "The static functions should be before the methods" | |
|
258 | } | |
|
259 | set state "consumeFunction" | |
|
260 | } elseif {$type == "assign" || $type == "semicolon"} { | |
|
261 | if {$isStatic} { | |
|
262 | report $fileName $line "The static variables should be before the methods" | |
|
263 | } else { | |
|
264 | set waitingFor "var" | |
|
265 | } | |
|
266 | } | |
|
267 | } | |
|
268 | } | |
|
269 | ||
|
270 | if {$waitingFor == "var"} { | |
|
271 | if {$type == "typedef" || $type == "enum" || $type == "class" || $type == "struct"} { | |
|
272 | set state "consumeUntilNextSemiColon" | |
|
273 | report $fileName $line "The typedefs, enums, classes and structs should be before the variables" | |
|
274 | } elseif {$prev1 == "identifier"} { | |
|
275 | if {$type == "leftparen"} { | |
|
276 | if {$isStatic} { | |
|
277 | report $fileName $line "The static functions should be before the variables" | |
|
278 | } else { | |
|
279 | report $fileName $line "The methods should be before the variables" | |
|
280 | } | |
|
281 | set state "consumeFunction" | |
|
282 | } elseif {$type == "assign" || $type == "semicolon"} { | |
|
283 | if {$isStatic} { | |
|
284 | report $fileName $line "The static variables should be before the variables" | |
|
285 | } | |
|
286 | } | |
|
287 | } | |
|
288 | } | |
|
289 | } | |
|
290 | } elseif {$state == "consumeUntilNextSemiColon"} { | |
|
291 | set isStatic 0 | |
|
292 | if {$type == "semicolon"} { | |
|
293 | set state "root" | |
|
294 | } elseif {$type == "leftbrace"} { | |
|
295 | incr bracesCounter | |
|
296 | set previousState $state | |
|
297 | set state "consumeBraces" | |
|
298 | } | |
|
299 | } elseif {$state == "consumeFunction"} { | |
|
300 | set isStatic 0 | |
|
301 | if {$type == "semicolon"} { | |
|
302 | set state "root" | |
|
303 | } elseif {$type == "leftbrace"} { | |
|
304 | incr bracesCounter | |
|
305 | set previousState "root" | |
|
306 | set state "consumeBraces" | |
|
307 | } | |
|
308 | } elseif {$state == "consumeBraces"} { | |
|
309 | if {$type == "leftbrace"} { | |
|
310 | incr bracesCounter | |
|
311 | } elseif {$type == "rightbrace"} { | |
|
312 | incr bracesCounter -1 | |
|
313 | if {$bracesCounter == 0} { | |
|
314 | set state $previousState | |
|
315 | } | |
|
316 | } | |
|
317 | } | |
|
318 | } | |
|
319 | ||
|
320 | if {$keepMachine} { | |
|
321 | lappend machinesToKeep $m | |
|
322 | } | |
|
323 | } | |
|
324 | set machines $machinesToKeep | |
|
325 | ||
|
326 | set prev2 $prev1 | |
|
327 | set prev1 $type | |
|
328 | } | |
|
329 | } No newline at end of file |
@@ -0,0 +1,166 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Forbid public member variables | |
|
3 | ||
|
4 | set forbidPublicMemberVarInStruct [getParameter "also-forbid-public-member-var-in-struct" 0] | |
|
5 | ||
|
6 | proc createMachine {type initState} { | |
|
7 | set machine [dict create classOrStruct $type state $initState previousState "" bracesCounter 0 parenCounter 0 bracketCounter 0 isStatic 0 isTypedef 0 isRootClass 0] | |
|
8 | return $machine | |
|
9 | } | |
|
10 | ||
|
11 | set tokenFilter { | |
|
12 | public | |
|
13 | protected | |
|
14 | private | |
|
15 | typedef | |
|
16 | enum | |
|
17 | class | |
|
18 | struct | |
|
19 | static | |
|
20 | identifier | |
|
21 | assign | |
|
22 | semicolon | |
|
23 | leftbrace | |
|
24 | rightbrace | |
|
25 | leftparen | |
|
26 | rightparen | |
|
27 | leftbracket | |
|
28 | rightbracket | |
|
29 | operator | |
|
30 | } | |
|
31 | ||
|
32 | foreach fileName [getSourceFileNames] { | |
|
33 | if {[regexp {\.h$} $fileName]} { | |
|
34 | set machines [list] | |
|
35 | ||
|
36 | set rootClass 1 | |
|
37 | set lastIdentifier "" | |
|
38 | set prev1 "" | |
|
39 | foreach token [getTokens $fileName 1 0 -1 -1 $tokenFilter] { | |
|
40 | set type [lindex $token 3] | |
|
41 | set line [lindex $token 1] | |
|
42 | ||
|
43 | if {$type == "identifier"} { | |
|
44 | set lastIdentifier [lindex $token 0] | |
|
45 | } | |
|
46 | ||
|
47 | if {$rootClass && ($type == "class" || $type == "struct")} { | |
|
48 | set m [createMachine $type "beforeLeftBrace"] | |
|
49 | dict set m isRootClass 1 | |
|
50 | lappend machines $m | |
|
51 | set rootClass 0 | |
|
52 | } | |
|
53 | ||
|
54 | set machinesToKeep [list] | |
|
55 | foreach m $machines { | |
|
56 | set keepMachine 1 | |
|
57 | dict with m { | |
|
58 | if {$state == "beforeLeftBrace"} { | |
|
59 | if {$type == "leftbrace"} { | |
|
60 | if {$classOrStruct == "class"} { | |
|
61 | set state "root" | |
|
62 | } elseif {$classOrStruct == "struct"} { | |
|
63 | set state "public" | |
|
64 | } | |
|
65 | } elseif {$type == "semicolon"} { | |
|
66 | set keepMachine 0 | |
|
67 | set rootClass $isRootClass | |
|
68 | } | |
|
69 | } elseif {$state == "root"} { | |
|
70 | if {$type == "public"} { | |
|
71 | set state "public" | |
|
72 | } elseif {$type == "leftbrace"} { | |
|
73 | incr bracesCounter | |
|
74 | set previousState $state | |
|
75 | set state "consumeBraces" | |
|
76 | } elseif {$type == "rightbrace"} { | |
|
77 | set keepMachine 0 | |
|
78 | set rootClass $isRootClass | |
|
79 | } | |
|
80 | } elseif {$state == "public"} { | |
|
81 | if {$type == "class" || $type == "struct"} { | |
|
82 | lappend machinesToKeep [createMachine $type "beforeLeftBrace"] | |
|
83 | } | |
|
84 | ||
|
85 | if {$type == "static"} { | |
|
86 | set isStatic 1 | |
|
87 | } | |
|
88 | if {$type == "typedef"} { | |
|
89 | set isTypedef 1 | |
|
90 | } | |
|
91 | ||
|
92 | if {$prev1 == "identifier" && ($type == "assign" || $type == "semicolon" || $type == "leftbracket")} { | |
|
93 | if {!$isStatic && !$isTypedef} { | |
|
94 | if {($classOrStruct == "class") || ($classOrStruct == "struct" && $forbidPublicMemberVarInStruct)} { | |
|
95 | report $fileName $line "Public member variables are forbidden in $classOrStruct (found: $lastIdentifier)" | |
|
96 | } | |
|
97 | } | |
|
98 | } elseif {$type == "protected" || $type == "private"} { | |
|
99 | set isStatic 0 | |
|
100 | set isTypedef 0 | |
|
101 | set state "root" | |
|
102 | } elseif {$type == "leftbrace"} { | |
|
103 | incr bracesCounter | |
|
104 | set previousState $state | |
|
105 | set state "consumeBraces" | |
|
106 | } elseif {$type == "leftparen"} { | |
|
107 | incr parenCounter | |
|
108 | set previousState $state | |
|
109 | set state "consumeParen" | |
|
110 | } elseif {$type == "rightbrace"} { | |
|
111 | set keepMachine 0 | |
|
112 | set rootClass $isRootClass | |
|
113 | } | |
|
114 | ||
|
115 | if {$type == "leftbracket"} { | |
|
116 | incr bracketCounter | |
|
117 | set previousState $state | |
|
118 | set state "consumeBracket" | |
|
119 | } | |
|
120 | ||
|
121 | if {$type == "semicolon" || $type == "leftbrace"} { | |
|
122 | set isStatic 0 | |
|
123 | } | |
|
124 | if {$type == "semicolon"} { | |
|
125 | set isTypedef 0 | |
|
126 | } | |
|
127 | } elseif {$state == "consumeBraces"} { | |
|
128 | if {$type == "leftbrace"} { | |
|
129 | incr bracesCounter | |
|
130 | } elseif {$type == "rightbrace"} { | |
|
131 | incr bracesCounter -1 | |
|
132 | if {$bracesCounter == 0} { | |
|
133 | set state $previousState | |
|
134 | } | |
|
135 | } | |
|
136 | } elseif {$state == "consumeParen"} { | |
|
137 | if {$type == "leftparen"} { | |
|
138 | incr parenCounter | |
|
139 | } elseif {$type == "rightparen"} { | |
|
140 | incr parenCounter -1 | |
|
141 | if {$parenCounter == 0} { | |
|
142 | set state $previousState | |
|
143 | } | |
|
144 | } | |
|
145 | } elseif {$state == "consumeBracket"} { | |
|
146 | if {$type == "leftbracket"} { | |
|
147 | incr bracketCounter | |
|
148 | } elseif {$type == "rightbracket"} { | |
|
149 | incr bracketCounter -1 | |
|
150 | if {$bracketCounter == 0} { | |
|
151 | set state $previousState | |
|
152 | } | |
|
153 | } | |
|
154 | } | |
|
155 | } | |
|
156 | ||
|
157 | if {$keepMachine} { | |
|
158 | lappend machinesToKeep $m | |
|
159 | } | |
|
160 | } | |
|
161 | set machines $machinesToKeep | |
|
162 | ||
|
163 | set prev1 $type | |
|
164 | } | |
|
165 | } | |
|
166 | } |
@@ -0,0 +1,60 | |||
|
1 | #!/usr/bin/tclsh | |
|
2 | # Prefer C++ includes of the C std headers (cstdio instead of stdio.h for instance) | |
|
3 | ||
|
4 | set cStdHeaders { | |
|
5 | assert.h | |
|
6 | complex.h | |
|
7 | ctype.h | |
|
8 | errno.h | |
|
9 | fenv.h | |
|
10 | float.h | |
|
11 | inttypes.h | |
|
12 | iso646.h | |
|
13 | limits.h | |
|
14 | locale.h | |
|
15 | math.h | |
|
16 | setjmp.h | |
|
17 | signal.h | |
|
18 | stdalign.h | |
|
19 | stdarg.h | |
|
20 | stdbool.h | |
|
21 | stddef.h | |
|
22 | stdint.h | |
|
23 | stdio.h | |
|
24 | stdlib.h | |
|
25 | string.h | |
|
26 | tgmath.h | |
|
27 | time.h | |
|
28 | uchar.h | |
|
29 | wchar.h | |
|
30 | wctype.h | |
|
31 | } | |
|
32 | ||
|
33 | set cStdHeadersWithDifferentCppEquivalent [dict create \ | |
|
34 | stdatomic.h atomic \ | |
|
35 | threads.h thread \ | |
|
36 | ] | |
|
37 | ||
|
38 | set cStdHeadersWithNoCppEquivalent { | |
|
39 | stdnoreturn.h | |
|
40 | } | |
|
41 | ||
|
42 | foreach fileName [getSourceFileNames] { | |
|
43 | foreach token [getTokens $fileName 1 0 -1 -1 {pp_hheader}] { | |
|
44 | set line [lindex $token 1] | |
|
45 | set value [lindex $token 0] | |
|
46 | ||
|
47 | if {[regexp {^[^<]*?<(.*)>[^>]*?$} $value matched headerName]} { | |
|
48 | if {[lsearch $cStdHeaders $headerName] != -1} { | |
|
49 | set headerWithoutExt [string range $headerName 0 [expr [string length $headerName] - 3]] | |
|
50 | set cppHeader "c$headerWithoutExt" | |
|
51 | report $fileName $line "$headerName is a C include, use the equivalent C++ include <$cppHeader>" | |
|
52 | } elseif {[dict exists $cStdHeadersWithDifferentCppEquivalent $headerName]} { | |
|
53 | set cppHeader [dict get $cStdHeadersWithDifferentCppEquivalent $headerName] | |
|
54 | report $fileName $line "$headerName is a C include, use the equivalent C++ include <$cppHeader>" | |
|
55 | } elseif {[lsearch $cStdHeadersWithNoCppEquivalent $headerName] != -1} { | |
|
56 | report $fileName $line "$headerName is a C include without C++ equivalent. Use the C++ constructions instead of relying on C headers." | |
|
57 | } | |
|
58 | } | |
|
59 | } | |
|
60 | } |
General Comments 0
You need to be logged in to leave comments.
Login now