2019-11-15 21:38:20 +01:00
|
|
|
#!/usr/bin/env python3
|
2015-07-28 14:50:30 +02:00
|
|
|
#
|
2015-07-28 14:20:38 +02:00
|
|
|
# cppcheck addon for naming conventions
|
2015-07-28 14:50:30 +02:00
|
|
|
#
|
|
|
|
# Example usage (variable name must start with lowercase, function name must start with uppercase):
|
|
|
|
# $ cppcheck --dump path-to-src/
|
|
|
|
# $ python addons/naming.py --var='[a-z].*' --function='[A-Z].*' path-to-src/*.dump
|
|
|
|
#
|
2015-07-28 14:20:38 +02:00
|
|
|
|
2019-12-30 17:30:17 +01:00
|
|
|
import cppcheckdata
|
2015-07-28 14:20:38 +02:00
|
|
|
import sys
|
|
|
|
import re
|
|
|
|
|
2019-03-26 18:54:09 +01:00
|
|
|
|
|
|
|
def validate_regex(expr):
|
|
|
|
try:
|
|
|
|
re.compile(expr)
|
|
|
|
except re.error:
|
|
|
|
print('Error: "{}" is not a valid regular expression.'.format(expr))
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
|
2015-07-28 14:20:38 +02:00
|
|
|
RE_VARNAME = None
|
2019-11-20 15:37:09 +01:00
|
|
|
RE_CONSTNAME = None
|
2018-06-17 14:46:59 +02:00
|
|
|
RE_PRIVATE_MEMBER_VARIABLE = None
|
2015-07-28 14:20:38 +02:00
|
|
|
RE_FUNCTIONNAME = None
|
|
|
|
for arg in sys.argv[1:]:
|
2015-08-21 10:55:19 +02:00
|
|
|
if arg[:6] == '--var=':
|
|
|
|
RE_VARNAME = arg[6:]
|
2019-03-26 18:54:09 +01:00
|
|
|
validate_regex(RE_VARNAME)
|
2019-11-20 15:37:09 +01:00
|
|
|
elif arg.startswith('--const='):
|
|
|
|
RE_CONSTNAME = arg[arg.find('=')+1:]
|
|
|
|
validate_regex(RE_CONSTNAME)
|
2018-06-17 14:46:59 +02:00
|
|
|
elif arg.startswith('--private-member-variable='):
|
|
|
|
RE_PRIVATE_MEMBER_VARIABLE = arg[arg.find('=')+1:]
|
2019-03-26 18:54:09 +01:00
|
|
|
validate_regex(RE_PRIVATE_MEMBER_VARIABLE)
|
2015-08-21 10:55:19 +02:00
|
|
|
elif arg[:11] == '--function=':
|
|
|
|
RE_FUNCTIONNAME = arg[11:]
|
2019-03-26 18:54:09 +01:00
|
|
|
validate_regex(RE_FUNCTIONNAME)
|
2015-08-21 10:55:19 +02:00
|
|
|
|
2019-11-18 18:41:57 +01:00
|
|
|
|
2019-04-08 19:42:16 +02:00
|
|
|
def reportError(token, severity, msg, errorId):
|
2019-04-14 08:54:53 +02:00
|
|
|
cppcheckdata.reportError(token, severity, msg, 'naming', errorId)
|
2015-07-28 14:20:38 +02:00
|
|
|
|
2019-11-18 18:41:57 +01:00
|
|
|
|
2015-07-28 14:20:38 +02:00
|
|
|
for arg in sys.argv[1:]:
|
2019-04-10 21:11:50 +02:00
|
|
|
if not arg.endswith('.dump'):
|
2015-08-21 10:55:19 +02:00
|
|
|
continue
|
|
|
|
print('Checking ' + arg + '...')
|
2019-12-27 08:50:56 +01:00
|
|
|
data = cppcheckdata.CppcheckData(arg)
|
|
|
|
|
|
|
|
for cfg in data.iterconfigurations():
|
|
|
|
print('Checking %s, config %s...' % (arg, cfg.name))
|
2015-12-14 09:37:26 +01:00
|
|
|
if RE_VARNAME:
|
|
|
|
for var in cfg.variables:
|
2019-11-20 15:37:09 +01:00
|
|
|
if var.access == 'Private':
|
|
|
|
continue
|
|
|
|
if var.nameToken and not var.isConst:
|
2019-03-26 18:54:09 +01:00
|
|
|
res = re.match(RE_VARNAME, var.nameToken.str)
|
|
|
|
if not res:
|
|
|
|
reportError(var.typeStartToken, 'style', 'Variable ' +
|
2019-04-08 19:42:16 +02:00
|
|
|
var.nameToken.str + ' violates naming convention', 'varname')
|
2019-11-20 15:37:09 +01:00
|
|
|
if RE_CONSTNAME:
|
|
|
|
for var in cfg.variables:
|
|
|
|
if var.access == 'Private':
|
|
|
|
continue
|
|
|
|
if var.nameToken and var.isConst:
|
|
|
|
res = re.match(RE_CONSTNAME, var.nameToken.str)
|
|
|
|
if not res:
|
|
|
|
reportError(var.typeStartToken, 'style', 'Constant ' +
|
|
|
|
var.nameToken.str + ' violates naming convention', 'constname')
|
2018-06-17 14:46:59 +02:00
|
|
|
if RE_PRIVATE_MEMBER_VARIABLE:
|
|
|
|
for var in cfg.variables:
|
|
|
|
if (var.access is None) or var.access != 'Private':
|
|
|
|
continue
|
|
|
|
res = re.match(RE_PRIVATE_MEMBER_VARIABLE, var.nameToken.str)
|
|
|
|
if not res:
|
|
|
|
reportError(var.typeStartToken, 'style', 'Private member variable ' +
|
2019-04-08 19:42:16 +02:00
|
|
|
var.nameToken.str + ' violates naming convention', 'privateMemberVariable')
|
2015-12-14 09:37:26 +01:00
|
|
|
if RE_FUNCTIONNAME:
|
|
|
|
for scope in cfg.scopes:
|
|
|
|
if scope.type == 'Function':
|
2019-11-18 18:41:57 +01:00
|
|
|
function = scope.function
|
|
|
|
if function is not None and function.type in ('Constructor', 'Destructor'):
|
|
|
|
continue
|
2015-12-14 09:37:26 +01:00
|
|
|
res = re.match(RE_FUNCTIONNAME, scope.className)
|
|
|
|
if not res:
|
|
|
|
reportError(
|
2019-04-08 19:42:16 +02:00
|
|
|
scope.bodyStart, 'style', 'Function ' + scope.className + ' violates naming convention', 'functionName')
|
2020-08-29 07:44:13 +02:00
|
|
|
|
|
|
|
sys.exit(cppcheckdata.EXIT_CODE)
|