@@ -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