From 4501592c3a6708c5003743045ef391d3642214b5 Mon Sep 17 00:00:00 2001 From: Maarten van der Schrieck Date: Fri, 22 Dec 2023 23:16:32 +0100 Subject: [PATCH] addons/namingng.py: Fix use with --cli. Commandline use of namingng led to an error complaining about the use of --cli. This flag is supported by the generic cppcheckdata.ArgumentParser(), which is not used by namingng.py. Replacing argparse.ArgumentParser() by the pre-configured cppcheckdata variant, solves this. Furthermore this patch changes namingng.py to use the generic reporting provided by cppcheckdata.reportError(). A local function reportNamingError() is implemented to call through to cppcheckdata.reportError(), while collecting all errors. If --cli is given, the exit status is now 0, even if errors are reported, as a non-zero exit status is interpreted as an internal error. The --verify option now verifies correct working both in --cli and non --cli mode. --- addons/namingng.py | 99 +++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/addons/namingng.py b/addons/namingng.py index 73f1b08ec087..f2547042c544 100755 --- a/addons/namingng.py +++ b/addons/namingng.py @@ -28,6 +28,7 @@ import argparse import json +errors = [] # Auxiliary class class DataStruct: @@ -35,18 +36,11 @@ def __init__(self, file, linenr, string): self.file = file self.linenr = linenr self.str = string + self.column = 0 - -def reportError(filename, linenr, severity, msg): - message = "[{filename}:{linenr}] ( {severity} ) naming.py: {msg}\n".format( - filename=filename, - linenr=linenr, - severity=severity, - msg=msg - ) - sys.stderr.write(message) - return message - +def reportNamingError(location,message,errorId='namingConvention',severity='style',extra=''): + line = cppcheckdata.reportError(location,severity,message,'namingng',errorId,extra) + errors.append(line) def loadConfig(configfile): with open(configfile) as fh: @@ -54,38 +48,35 @@ def loadConfig(configfile): return data -def checkTrueRegex(data, expr, msg, errors): +def checkTrueRegex(data, expr, msg): res = re.match(expr, data.str) if res: - errors.append(reportError(data.file, data.linenr, 'style', msg)) + reportNamingError(data,msg) -def checkFalseRegex(data, expr, msg, errors): +def checkFalseRegex(data, expr, msg): res = re.match(expr, data.str) if not res: - errors.append(reportError(data.file, data.linenr, 'style', msg)) + reportNamingError(data,msg) -def evalExpr(conf, exp, mockToken, msgType, errors): +def evalExpr(conf, exp, mockToken, msgType): if isinstance(conf, dict): if conf[exp][0]: msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1] - checkTrueRegex(mockToken, exp, msg, errors) + checkTrueRegex(mockToken, exp, msg) elif ~conf[exp][0]: msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1] - checkFalseRegex(mockToken, exp, msg, errors) + checkFalseRegex(mockToken, exp, msg) else: msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][0] - checkFalseRegex(mockToken, exp, msg, errors) + checkFalseRegex(mockToken, exp, msg) else: msg = msgType + ' ' + mockToken.str + ' violates naming convention' - checkFalseRegex(mockToken, exp, msg, errors) + checkFalseRegex(mockToken, exp, msg) def process(dumpfiles, configfile, debugprint=False): - - errors = [] - conf = loadConfig(configfile) for afile in dumpfiles: @@ -99,7 +90,7 @@ def process(dumpfiles, configfile, debugprint=False): mockToken = DataStruct(afile[:-5], "0", afile[afile.rfind('/') + 1:-5]) msgType = 'File name' for exp in conf["RE_FILE"]: - evalExpr(conf["RE_FILE"], exp, mockToken, msgType, errors) + evalExpr(conf["RE_FILE"], exp, mockToken, msgType) # Check Namespace naming if "RE_NAMESPACE" in conf and conf["RE_NAMESPACE"]: @@ -108,7 +99,7 @@ def process(dumpfiles, configfile, debugprint=False): mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str) msgType = 'Namespace' for exp in conf["RE_NAMESPACE"]: - evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType, errors) + evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType) for cfg in data.configurations: print('Checking %s, config %s...' % (afile, cfg.name)) @@ -134,18 +125,15 @@ def process(dumpfiles, configfile, debugprint=False): continue if varType in conf["var_prefixes"]: if not var.nameToken.str.startswith(conf["var_prefixes"][varType]): - errors.append(reportError( - var.typeStartToken.file, - var.typeStartToken.linenr, - 'style', + reportNamingError(var.typeStartToken, 'Variable ' + var.nameToken.str + - ' violates naming convention')) + ' violates naming convention') mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str) msgType = 'Variable' for exp in conf["RE_VARNAME"]: - evalExpr(conf["RE_VARNAME"], exp, mockToken, msgType, errors) + evalExpr(conf["RE_VARNAME"], exp, mockToken, msgType) # Check Private Variable naming if "RE_PRIVATE_MEMBER_VARIABLE" in conf and conf["RE_PRIVATE_MEMBER_VARIABLE"]: @@ -156,7 +144,7 @@ def process(dumpfiles, configfile, debugprint=False): mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str) msgType = 'Private member variable' for exp in conf["RE_PRIVATE_MEMBER_VARIABLE"]: - evalExpr(conf["RE_PRIVATE_MEMBER_VARIABLE"], exp, mockToken, msgType, errors) + evalExpr(conf["RE_PRIVATE_MEMBER_VARIABLE"], exp, mockToken, msgType) # Check Public Member Variable naming if "RE_PUBLIC_MEMBER_VARIABLE" in conf and conf["RE_PUBLIC_MEMBER_VARIABLE"]: @@ -166,7 +154,7 @@ def process(dumpfiles, configfile, debugprint=False): mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str) msgType = 'Public member variable' for exp in conf["RE_PUBLIC_MEMBER_VARIABLE"]: - evalExpr(conf["RE_PUBLIC_MEMBER_VARIABLE"], exp, mockToken, msgType, errors) + evalExpr(conf["RE_PUBLIC_MEMBER_VARIABLE"], exp, mockToken, msgType) # Check Global Variable naming if "RE_GLOBAL_VARNAME" in conf and conf["RE_GLOBAL_VARNAME"]: @@ -176,7 +164,7 @@ def process(dumpfiles, configfile, debugprint=False): mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str) msgType = 'Public member variable' for exp in conf["RE_GLOBAL_VARNAME"]: - evalExpr(conf["RE_GLOBAL_VARNAME"], exp, mockToken, msgType, errors) + evalExpr(conf["RE_GLOBAL_VARNAME"], exp, mockToken, msgType) # Check Functions naming if "RE_FUNCTIONNAME" in conf and conf["RE_FUNCTIONNAME"]: @@ -194,12 +182,11 @@ def process(dumpfiles, configfile, debugprint=False): if retval and retval in conf["function_prefixes"]: if not token.function.name.startswith(conf["function_prefixes"][retval]): - errors.append(reportError( - token.file, token.linenr, 'style', 'Function ' + token.function.name + ' violates naming convention')) + reportNamingError(token, 'Function ' + token.function.name + ' violates naming convention') mockToken = DataStruct(token.file, token.linenr, token.function.name) msgType = 'Function' for exp in conf["RE_FUNCTIONNAME"]: - evalExpr(conf["RE_FUNCTIONNAME"], exp, mockToken, msgType, errors) + evalExpr(conf["RE_FUNCTIONNAME"], exp, mockToken, msgType) # Check Class naming if "RE_CLASS_NAME" in conf and conf["RE_CLASS_NAME"]: @@ -209,14 +196,10 @@ def process(dumpfiles, configfile, debugprint=False): mockToken = DataStruct(fnc.tokenDef.file, fnc.tokenDef.linenr, fnc.name) msgType = 'Class ' + fnc.type for exp in conf["RE_CLASS_NAME"]: - evalExpr(conf["RE_CLASS_NAME"], exp, mockToken, msgType, errors) - return errors - + evalExpr(conf["RE_CLASS_NAME"], exp, mockToken, msgType) if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Naming verification') - parser.add_argument('dumpfiles', type=str, nargs='+', - help='A set of dumpfiles to process') + parser = cppcheckdata.ArgumentParser() parser.add_argument("--debugprint", action="store_true", default=False, help="Add debug prints") parser.add_argument("--configfile", type=str, default="naming.json", @@ -225,20 +208,30 @@ def process(dumpfiles, configfile, debugprint=False): help="verify this script. Must be executed in test folder !") args = parser.parse_args() - errors = process(args.dumpfiles, args.configfile, args.debugprint) + process(args.dumpfile, args.configfile, args.debugprint) if args.verify: - print(errors) if len(errors) < 6: print("Not enough errors found") sys.exit(1) - target = [ - '[namingng_test.c:8] ( style ) naming.py: Variable badui32 violates naming convention\n', - '[namingng_test.c:11] ( style ) naming.py: Variable a violates naming convention\n', - '[namingng_test.c:29] ( style ) naming.py: Variable badui32 violates naming convention\n', - '[namingng_test.c:20] ( style ) naming.py: Function ui16bad_underscore violates naming convention\n', - '[namingng_test.c:25] ( style ) naming.py: Function u32Bad violates naming convention\n', - '[namingng_test.c:37] ( style ) naming.py: Function Badui16 violates naming convention\n'] + if args.cli: + target = [ + '{"file": "namingng_test.c", "linenr": 8, "column": 5, "severity": "style", "message": "Variable badui32 violates naming convention", "addon": "namingng", "errorId": "namingConvention", "extra": ""}\n', + '{"file": "namingng_test.c", "linenr": 11, "column": 5, "severity": "style", "message": "Variable a violates naming convention", "addon": "namingng", "errorId": "namingConvention", "extra": ""}\n', + '{"file": "namingng_test.c", "linenr": 29, "column": 5, "severity": "style", "message": "Variable badui32 violates naming convention", "addon": "namingng", "errorId": "namingConvention", "extra": ""}\n', + '{"file": "namingng_test.c", "linenr": 20, "column": 0, "severity": "style", "message": "Function ui16bad_underscore violates naming convention", "addon": "namingng", "errorId": "namingConvention", "extra": ""}\n', + '{"file": "namingng_test.c", "linenr": 25, "column": 10, "severity": "style", "message": "Function u32Bad violates naming convention", "addon": "namingng", "errorId": "namingConvention", "extra": ""}\n', + '{"file": "namingng_test.c", "linenr": 37, "column": 10, "severity": "style", "message": "Function Badui16 violates naming convention", "addon": "namingng", "errorId": "namingConvention", "extra": ""}\n', + ] + else: + target = [ + '[namingng_test.c:8] (style) Variable badui32 violates naming convention [namingng-namingConvention]\n', + '[namingng_test.c:11] (style) Variable a violates naming convention [namingng-namingConvention]\n', + '[namingng_test.c:29] (style) Variable badui32 violates naming convention [namingng-namingConvention]\n', + '[namingng_test.c:20] (style) Function ui16bad_underscore violates naming convention [namingng-namingConvention]\n', + '[namingng_test.c:25] (style) Function u32Bad violates naming convention [namingng-namingConvention]\n', + '[namingng_test.c:37] (style) Function Badui16 violates naming convention [namingng-namingConvention]\n', + ] diff = set(errors) - set(target) if len(diff): print("Not the right errors found {}".format(str(diff))) @@ -246,7 +239,7 @@ def process(dumpfiles, configfile, debugprint=False): print("Verification done\n") sys.exit(0) - if len(errors): + if len(errors) and not args.cli: print('Found errors: {}'.format(len(errors))) sys.exit(1)