cppcheck-py 2.20.0__py3-none-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. cppcheck/__init__.py +55 -0
  2. cppcheck/cppcheck-2.20.0.tar.gz +0 -0
  3. cppcheck/data/addons/__init__.py +0 -0
  4. cppcheck/data/addons/cppcheck.py +41 -0
  5. cppcheck/data/addons/cppcheckdata.py +1727 -0
  6. cppcheck/data/addons/findcasts.py +32 -0
  7. cppcheck/data/addons/misc.py +163 -0
  8. cppcheck/data/addons/misra.py +5153 -0
  9. cppcheck/data/addons/misra_9.py +559 -0
  10. cppcheck/data/addons/naming.py +92 -0
  11. cppcheck/data/addons/namingng.py +420 -0
  12. cppcheck/data/addons/runaddon.py +16 -0
  13. cppcheck/data/addons/threadsafety.py +350 -0
  14. cppcheck/data/addons/y2038.py +602 -0
  15. cppcheck/data/cfg/avr.cfg +402 -0
  16. cppcheck/data/cfg/bento4.cfg +142 -0
  17. cppcheck/data/cfg/boost.cfg +1284 -0
  18. cppcheck/data/cfg/bsd.cfg +567 -0
  19. cppcheck/data/cfg/cairo.cfg +90 -0
  20. cppcheck/data/cfg/cppcheck-lib.cfg +72 -0
  21. cppcheck/data/cfg/cppunit.cfg +48 -0
  22. cppcheck/data/cfg/dpdk.cfg +11 -0
  23. cppcheck/data/cfg/embedded_sql.cfg +4 -0
  24. cppcheck/data/cfg/emscripten.cfg +108 -0
  25. cppcheck/data/cfg/ginac.cfg +12848 -0
  26. cppcheck/data/cfg/gnu.cfg +1738 -0
  27. cppcheck/data/cfg/googletest.cfg +62 -0
  28. cppcheck/data/cfg/gtk.cfg +23086 -0
  29. cppcheck/data/cfg/icu.cfg +221 -0
  30. cppcheck/data/cfg/kde.cfg +92 -0
  31. cppcheck/data/cfg/libcerror.cfg +203 -0
  32. cppcheck/data/cfg/libcurl.cfg +487 -0
  33. cppcheck/data/cfg/libsigc++.cfg +36 -0
  34. cppcheck/data/cfg/lua.cfg +316 -0
  35. cppcheck/data/cfg/mfc.cfg +271 -0
  36. cppcheck/data/cfg/microsoft_atl.cfg +40 -0
  37. cppcheck/data/cfg/microsoft_sal.cfg +490 -0
  38. cppcheck/data/cfg/microsoft_unittest.cfg +20 -0
  39. cppcheck/data/cfg/motif.cfg +318 -0
  40. cppcheck/data/cfg/nspr.cfg +38 -0
  41. cppcheck/data/cfg/ntl.cfg +6907 -0
  42. cppcheck/data/cfg/opencv2.cfg +132 -0
  43. cppcheck/data/cfg/opengl.cfg +581 -0
  44. cppcheck/data/cfg/openmp.cfg +157 -0
  45. cppcheck/data/cfg/openssl.cfg +174 -0
  46. cppcheck/data/cfg/pcre.cfg +165 -0
  47. cppcheck/data/cfg/posix.cfg +6445 -0
  48. cppcheck/data/cfg/protobuf.cfg +10 -0
  49. cppcheck/data/cfg/python.cfg +674 -0
  50. cppcheck/data/cfg/qt.cfg +5502 -0
  51. cppcheck/data/cfg/ruby.cfg +142 -0
  52. cppcheck/data/cfg/sdl.cfg +354 -0
  53. cppcheck/data/cfg/selinux.cfg +3621 -0
  54. cppcheck/data/cfg/sfml.cfg +301 -0
  55. cppcheck/data/cfg/sqlite3.cfg +1571 -0
  56. cppcheck/data/cfg/std.cfg +9215 -0
  57. cppcheck/data/cfg/tinyxml2.cfg +37 -0
  58. cppcheck/data/cfg/vcl.cfg +4 -0
  59. cppcheck/data/cfg/windows.cfg +17237 -0
  60. cppcheck/data/cfg/wxsqlite3.cfg +1955 -0
  61. cppcheck/data/cfg/wxsvg.cfg +16905 -0
  62. cppcheck/data/cfg/wxwidgets.cfg +17313 -0
  63. cppcheck/data/cfg/zephyr.cfg +113 -0
  64. cppcheck/data/cfg/zlib.cfg +1450 -0
  65. cppcheck/data/cppcheck-htmlreport +1157 -0
  66. cppcheck/data/cppcheck.exe +0 -0
  67. cppcheck/data/platforms/aix_ppc64.xml +18 -0
  68. cppcheck/data/platforms/arm32-wchar_t2.xml +18 -0
  69. cppcheck/data/platforms/arm32-wchar_t4.xml +18 -0
  70. cppcheck/data/platforms/arm64-wchar_t2.xml +18 -0
  71. cppcheck/data/platforms/arm64-wchar_t4.xml +18 -0
  72. cppcheck/data/platforms/avr8.xml +18 -0
  73. cppcheck/data/platforms/cray_sv1.xml +18 -0
  74. cppcheck/data/platforms/elbrus-e1cp.xml +18 -0
  75. cppcheck/data/platforms/mips32.xml +18 -0
  76. cppcheck/data/platforms/msp430_eabi_large_datamodel.xml +18 -0
  77. cppcheck/data/platforms/pic16.xml +18 -0
  78. cppcheck/data/platforms/pic8-enhanced.xml +18 -0
  79. cppcheck/data/platforms/pic8.xml +18 -0
  80. cppcheck_py-2.20.0.dist-info/METADATA +76 -0
  81. cppcheck_py-2.20.0.dist-info/RECORD +84 -0
  82. cppcheck_py-2.20.0.dist-info/WHEEL +5 -0
  83. cppcheck_py-2.20.0.dist-info/entry_points.txt +4 -0
  84. cppcheck_py-2.20.0.dist-info/licenses/LICENSE.md +191 -0
@@ -0,0 +1,420 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # cppcheck addon for naming conventions
4
+ # An enhanced version. Configuration is taken from a json file
5
+ # It supports to check for type-based prefixes in function or variable names.
6
+ # Aside from include guard naming, include guard presence can also be tested.
7
+ #
8
+ # Example usage (variable name must start with lowercase, function name must start with uppercase):
9
+ # $ cppcheck --dump path-to-src/
10
+ # $ python namingng.py test.c.dump
11
+ #
12
+ # JSON format:
13
+ #
14
+ # {
15
+ # "RE_VARNAME": ["[a-z]*[a-zA-Z0-9_]*\\Z"],
16
+ # "RE_PRIVATE_MEMBER_VARIABLE": null,
17
+ # "RE_FUNCTIONNAME": ["[a-z0-9A-Z]*\\Z"],
18
+ # "_comment": "comments can be added to the config with underscore-prefixed keys",
19
+ # "include_guard": {
20
+ # "input": "path",
21
+ # "prefix": "GUARD_",
22
+ # "case": "upper",
23
+ # "max_linenr": 5,
24
+ # "RE_HEADERFILE": "[^/].*\\.h\\Z",
25
+ # "required": true
26
+ # },
27
+ # "var_prefixes": {"uint32_t": "ui32"},
28
+ # "function_prefixes": {"uint16_t": "ui16",
29
+ # "uint32_t": "ui32"}
30
+ # }
31
+ #
32
+ # RE_VARNAME, RE_PRIVATE_MEMBER_VARIABLE and RE_FUNCTIONNAME are regular expressions to cover the basic names
33
+ # In var_prefixes and function_prefixes there are the variable-type/prefix pairs
34
+
35
+ import cppcheckdata
36
+ import sys
37
+ import os
38
+ import re
39
+ import json
40
+
41
+ # Auxiliary class
42
+ class DataStruct:
43
+ def __init__(self, file, linenr, string, column=0):
44
+ self.file = file
45
+ self.linenr = linenr
46
+ self.str = string
47
+ self.column = column
48
+
49
+ def reportNamingError(location,message,errorId='namingConvention',severity='style',extra='',column=None):
50
+ cppcheckdata.reportError(location,severity,message,'namingng',errorId,extra,columnOverride=column)
51
+
52
+ def configError(error,fatal=True):
53
+ print('config error: %s'%error)
54
+ if fatal:
55
+ sys.exit(1)
56
+
57
+ def validateConfigREs(list_or_dict,json_key):
58
+ have_error = False
59
+ for item in list_or_dict:
60
+ try:
61
+ re.compile(item)
62
+ except re.error as err:
63
+ configError("item '%s' of '%s' is not a valid regular expression: %s"%(item,json_key,err),fatal=False)
64
+ have_error = True
65
+ continue
66
+ if not isinstance(list_or_dict,dict):
67
+ continue
68
+ # item is actually a dict key; check value
69
+ value = list_or_dict[item]
70
+ if (not isinstance(value,list) or len(value) != 2
71
+ or not isinstance(value[0],bool) or not isinstance(value[1],str)):
72
+ configError("item '%s' of '%s' must be an array [bool,string]"%(item,json_key),fatal=False)
73
+ have_error = True
74
+
75
+ return have_error
76
+
77
+ def loadConfig(configfile):
78
+ if not os.path.exists(configfile):
79
+ configError("cannot find config file '%s'"%configfile)
80
+
81
+ try:
82
+ with open(configfile) as fh:
83
+ data = json.load(fh)
84
+ except json.JSONDecodeError as e:
85
+ configError("error parsing config file as JSON at line %d: %s"%(e.lineno,e.msg))
86
+ except Exception as e:
87
+ configError("error opening config file '%s': %s"%(configfile,e))
88
+
89
+ if not isinstance(data, dict):
90
+ configError('config file must contain a JSON object at the top level')
91
+
92
+ # All errors are emitted before bailing out, to make the unit test more
93
+ # effective.
94
+ have_error = False
95
+
96
+ # Put config items in a class, so that settings can be accessed using
97
+ # config.feature
98
+ class Config:
99
+ pass
100
+ config = Config()
101
+
102
+ mapping = {
103
+ 'file': ('RE_FILE', (list,)),
104
+ 'namespace': ('RE_NAMESPACE', (list,dict)),
105
+ 'include_guard': ('include_guard', (dict,)),
106
+ 'variable': ('RE_VARNAME', (list,dict)),
107
+ 'variable_prefixes': ('var_prefixes', (dict,), {}),
108
+ 'private_member': ('RE_PRIVATE_MEMBER_VARIABLE', (list,dict)),
109
+ 'public_member': ('RE_PUBLIC_MEMBER_VARIABLE', (list,dict)),
110
+ 'global_variable': ('RE_GLOBAL_VARNAME', (list,dict)),
111
+ 'function_name': ('RE_FUNCTIONNAME', (list,dict)),
112
+ 'function_prefixes': ('function_prefixes', (dict,), {}),
113
+ 'class_name': ('RE_CLASS_NAME', (list,dict)),
114
+ 'skip_one_char_variables': ('skip_one_char_variables', (bool,)),
115
+ }
116
+
117
+ # parse defined keys and store as members of config object
118
+ for key,opts in mapping.items():
119
+ json_key = opts[0]
120
+ req_type = opts[1]
121
+ default = None if len(opts)<3 else opts[2]
122
+
123
+ value = data.pop(json_key,default)
124
+ if value is not None and type(value) not in req_type:
125
+ req_typename = ' or '.join([tp.__name__ for tp in req_type])
126
+ got_typename = type(value).__name__
127
+ configError('%s must be %s (not %s), or not set'%(json_key,req_typename,got_typename),fatal=False)
128
+ have_error = True
129
+ continue
130
+
131
+ # type list implies that this is either a list of REs or a dict with RE keys
132
+ if list in req_type and value is not None:
133
+ re_error = validateConfigREs(value,json_key)
134
+ if re_error:
135
+ have_error = True
136
+
137
+ setattr(config,key,value)
138
+
139
+ # check remaining keys, only accept underscore-prefixed comments
140
+ for key,value in data.items():
141
+ if key == '' or key[0] != '_':
142
+ configError("unknown config key '%s'"%key,fatal=False)
143
+ have_error = True
144
+
145
+ if have_error:
146
+ sys.exit(1)
147
+
148
+ # pylint: disable-next=no-member - TODO: fix this
149
+ if config.include_guard:
150
+ # pylint: disable-next=no-member - TODO: fix this
151
+ config.include_guard_header_re = config.include_guard.get('RE_HEADERFILE',"[^/].*\\.h\\Z")
152
+
153
+ return config
154
+
155
+
156
+ def evalExpr(conf, exp, mockToken, msgType):
157
+ report_as_error = False
158
+ msg = msgType + ' ' + mockToken.str + ' violates naming convention'
159
+
160
+ if isinstance(conf, dict):
161
+ report_as_error = conf[exp][0]
162
+ msg += ': ' + conf[exp][1]
163
+
164
+ res = re.match(exp,mockToken.str)
165
+ if bool(res) == report_as_error:
166
+ reportNamingError(mockToken,msg)
167
+
168
+ def check_include_guard_name(conf,directive):
169
+ parts = directive.str.split()
170
+ if len(parts) != 2:
171
+ msg = 'syntax error'
172
+ reportNamingError(directive,msg,'syntax')
173
+ return None,None
174
+ guard_name = parts[1]
175
+ guard_column = 1+directive.str.find(guard_name)
176
+
177
+ filename = directive.file
178
+ if conf.include_guard.get('input','path') == 'basename':
179
+ filename = os.path.basename(filename)
180
+ use_case = conf.include_guard.get('case','upper')
181
+ if use_case == 'upper':
182
+ filename = filename.upper()
183
+ elif use_case == 'lower':
184
+ filename = filename.lower()
185
+ elif use_case == 'keep':
186
+ pass # keep filename case as-is
187
+ else:
188
+ print("invalid config value for 'case': '%s'"%use_case,file=sys.stderr)
189
+ sys.exit(1)
190
+
191
+ barename = re.sub('[^A-Za-z0-9]','_',filename).strip('_')
192
+ expect_guard_name = conf.include_guard.get('prefix','') + barename + conf.include_guard.get('suffix','')
193
+ if expect_guard_name != guard_name:
194
+ msg = 'include guard naming violation; %s != %s'%(guard_name,expect_guard_name)
195
+ reportNamingError(directive,msg,'includeGuardName',column=guard_column)
196
+
197
+ return guard_name,guard_column
198
+
199
+ def check_include_guards(conf,cfg,unguarded_include_files):
200
+ # Scan for '#ifndef FILE_H' as the first directive, in the first N lines.
201
+ # Then test whether the next directive #defines the found name.
202
+ # Various tests are done:
203
+ # - check include guards for their naming and consistency
204
+ # - test whether include guards are in place
205
+ max_linenr = conf.include_guard.get('max_linenr', 5)
206
+
207
+ def report(directive,msg,errorId,severity='style',column=0):
208
+ reportNamingError(directive,msg,errorId,severity=severity,column=column)
209
+
210
+ def report_pending_ifndef(directive,column):
211
+ report(directive,'include guard #ifndef is not followed by #define','includeGuardIncomplete',column=column)
212
+
213
+ last_fn = None
214
+ pending_ifndef = None
215
+ guard_column = None
216
+ phase = 0
217
+ for directive in cfg.directives:
218
+ if last_fn != directive.file:
219
+ if pending_ifndef:
220
+ report_pending_ifndef(pending_ifndef,guard_column)
221
+ pending_ifndef = None
222
+ last_fn = directive.file
223
+ phase = 0
224
+ if phase == -1:
225
+ # ignore (the remainder of) this file
226
+ continue
227
+ if not re.match(conf.include_guard_header_re,directive.file):
228
+ phase = -1
229
+ continue
230
+
231
+ if directive.linenr > max_linenr:
232
+ if phase == 0 and conf.include_guard.get('required',1):
233
+ report(directive,'include guard not found before line %d'%max_linenr,'includeGuardMissing')
234
+ phase = -1
235
+ continue
236
+
237
+ if phase == 0:
238
+ # looking for '#ifndef FILE_H'
239
+ if not directive.str.startswith('#ifndef'):
240
+ if conf.include_guard.get('required',1):
241
+ report(directive,'first preprocessor directive should be include guard #ifndef','includeGuardMissing')
242
+ phase = -1
243
+ continue
244
+ guard_name,guard_column = check_include_guard_name(conf,directive)
245
+ if guard_name is None:
246
+ phase = -1
247
+ continue
248
+ pending_ifndef = directive
249
+ phase = 1
250
+ elif phase == 1:
251
+ pending_ifndef = None
252
+ # looking for '#define FILE_H'
253
+ if not directive.str.startswith('#define'):
254
+ report(directive,'second preprocessor directive should be include guard #define','includeGuardIncomplete')
255
+ phase = -1
256
+ continue
257
+ parts = directive.str.split()
258
+ if len(parts) == 1:
259
+ report(directive,'syntax error','syntax')
260
+ phase = -1
261
+ continue
262
+ if guard_name != parts[1]:
263
+ report(directive,'include guard does not guard; %s != %s'%(guard_name,parts[1]),'includeGuardAwayFromDuty',severity='warning',column=guard_column)
264
+
265
+ unguarded_include_files.remove(directive.file)
266
+
267
+ phase = -1
268
+ if pending_ifndef:
269
+ report_pending_ifndef(pending_ifndef,guard_column)
270
+
271
+ def process(dumpfiles, configfile, cli, debugprint):
272
+ conf = loadConfig(configfile)
273
+
274
+ for afile in dumpfiles:
275
+ if not afile[-5:] == '.dump':
276
+ continue
277
+ if not cli:
278
+ print('Checking ' + afile + '...')
279
+ data = cppcheckdata.CppcheckData(afile)
280
+ process_data(conf,data,cli,debugprint)
281
+
282
+ def check_file_naming(conf,data):
283
+ for source_file in data.files:
284
+ basename = os.path.basename(source_file)
285
+ good = False
286
+ for exp in conf.file:
287
+ good |= bool(re.match(exp, source_file))
288
+ good |= bool(re.match(exp, basename))
289
+ if not good:
290
+ mockToken = DataStruct(source_file, 0, basename)
291
+ reportNamingError(mockToken, 'File name ' + basename + ' violates naming convention')
292
+
293
+ def check_namespace_naming(conf,data):
294
+ for tk in data.rawTokens:
295
+ if tk.str != 'namespace':
296
+ continue
297
+ mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str, tk.next.column)
298
+ for exp in conf.namespace:
299
+ evalExpr(conf.namespace, exp, mockToken, 'Namespace')
300
+
301
+ def check_variable_naming(conf,cfg,debugprint):
302
+ for var in cfg.variables:
303
+ if not var.nameToken:
304
+ continue
305
+ if var.access in ('Global','Public','Private'):
306
+ continue
307
+ prev = var.nameToken.previous
308
+ varType = prev.str
309
+ while "*" in varType and len(varType.replace("*", "")) == 0:
310
+ prev = prev.previous
311
+ varType = prev.str + varType
312
+
313
+ if debugprint:
314
+ print("Variable Name: " + str(var.nameToken.str))
315
+ print("original Type Name: " + str(var.nameToken.valueType.originalTypeName))
316
+ print("Type Name: " + var.nameToken.valueType.type)
317
+ print("Sign: " + str(var.nameToken.valueType.sign))
318
+ print("variable type: " + varType)
319
+ print("\n")
320
+ print("\t-- {} {}".format(varType, str(var.nameToken.str)))
321
+
322
+ if conf.skip_one_char_variables and len(var.nameToken.str) == 1:
323
+ continue
324
+ if varType in conf.variable_prefixes:
325
+ prefix = conf.variable_prefixes[varType]
326
+ if not var.nameToken.str.startswith(prefix):
327
+ reportNamingError(var.typeStartToken,
328
+ 'Variable ' +
329
+ var.nameToken.str +
330
+ ' violates naming convention',
331
+ column=var.nameToken.column)
332
+
333
+ mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str, var.nameToken.column)
334
+ for exp in conf.variable:
335
+ evalExpr(conf.variable, exp, mockToken, 'Variable')
336
+
337
+ # Naming check for Global, Private and Public member variables
338
+ def check_gpp_naming(conf_list,cfg,access,message):
339
+ for var in cfg.variables:
340
+ if var.access != access:
341
+ continue
342
+ mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str, var.nameToken.column)
343
+ for exp in conf_list:
344
+ evalExpr(conf_list, exp, mockToken, message)
345
+
346
+ def check_function_naming(conf,cfg,debugprint):
347
+ for token in cfg.tokenlist:
348
+ if not token.function:
349
+ continue
350
+ if token.function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'):
351
+ continue
352
+ retval = token.previous.str
353
+ prev = token.previous
354
+ while "*" in retval and len(retval.replace("*", "")) == 0:
355
+ prev = prev.previous
356
+ retval = prev.str + retval
357
+ if debugprint:
358
+ print("\t:: {} {}".format(retval, token.function.name))
359
+
360
+ if retval and retval in conf.function_prefixes:
361
+ if not token.function.name.startswith(conf.function_prefixes[retval]):
362
+ reportNamingError(token, 'Function ' + token.function.name + ' violates naming convention', column=token.column)
363
+ mockToken = DataStruct(token.file, token.linenr, token.function.name, token.column)
364
+ msgType = 'Function'
365
+ for exp in conf.function_name:
366
+ evalExpr(conf.function_name, exp, mockToken, msgType)
367
+
368
+ def check_class_naming(conf,cfg):
369
+ for fnc in cfg.functions:
370
+ if fnc.type not in ('Constructor','Destructor'):
371
+ continue
372
+ mockToken = DataStruct(fnc.tokenDef.file, fnc.tokenDef.linenr, fnc.name, fnc.tokenDef.column)
373
+ msgType = 'Class ' + fnc.type
374
+ for exp in conf.class_name:
375
+ evalExpr(conf.class_name, exp, mockToken, msgType)
376
+
377
+ def process_data(conf,data,cli,debugprint):
378
+ if conf.file:
379
+ check_file_naming(conf,data)
380
+
381
+ if conf.namespace:
382
+ check_namespace_naming(conf,data)
383
+
384
+ unguarded_include_files = []
385
+ if conf.include_guard and conf.include_guard.get('required',1):
386
+ unguarded_include_files = [fn for fn in data.files if re.match(conf.include_guard_header_re,fn)]
387
+
388
+ for cfg in data.configurations:
389
+ if not cli:
390
+ print('Checking config %s...' % cfg.name)
391
+ if conf.variable:
392
+ check_variable_naming(conf,cfg,debugprint)
393
+ if conf.private_member:
394
+ check_gpp_naming(conf.private_member,cfg,'Private','Private member variable')
395
+ if conf.public_member:
396
+ check_gpp_naming(conf.public_member,cfg,'Public','Public member variable')
397
+ if conf.global_variable:
398
+ check_gpp_naming(conf.global_variable,cfg,'Global','Global variable')
399
+ if conf.function_name:
400
+ check_function_naming(conf,cfg,debugprint)
401
+ if conf.class_name:
402
+ check_class_naming(conf,cfg)
403
+ if conf.include_guard:
404
+ check_include_guards(conf,cfg,unguarded_include_files)
405
+
406
+ for fn in unguarded_include_files:
407
+ mockToken = DataStruct(fn,0,os.path.basename(fn))
408
+ reportNamingError(mockToken,'Missing include guard','includeGuardMissing')
409
+
410
+ if __name__ == "__main__":
411
+ parser = cppcheckdata.ArgumentParser()
412
+ parser.add_argument("--debugprint", action="store_true", default=False,
413
+ help="Add debug prints")
414
+ parser.add_argument("--configfile", type=str, default="namingng.config.json",
415
+ help="Naming check config file")
416
+
417
+ args = parser.parse_args()
418
+ process(args.dumpfile, args.configfile, args.cli, args.debugprint)
419
+
420
+ sys.exit(0)
@@ -0,0 +1,16 @@
1
+ import cppcheckdata
2
+ import cppcheck
3
+ import runpy
4
+ import sys
5
+ import os
6
+
7
+ if __name__ == '__main__':
8
+ addon = sys.argv[1]
9
+ __addon_name__ = os.path.splitext(os.path.basename(addon))[0]
10
+ sys.argv.pop(0)
11
+
12
+ runpy.run_path(addon, run_name='__main__')
13
+
14
+ # Run registered checkers
15
+ cppcheck.runcheckers()
16
+ sys.exit(cppcheckdata.EXIT_CODE)