Skip to content

Commit 24133d4

Browse files
authored
addons/namingng.py: Fix commandline use. (#5793)
namingng.py was only usable in standalone mode, but now supports CLI mode, i.e. with cppcheck --addon=namingng. It uses the generic reporting provided by cppcheckdata.reportError(). All output other than reported errors is suppressed. A local function reportNamingError() is implemented to call through to cppcheckdata.reportError(), filling in common defaults. The collection of errors and the --verify feature are removed, including related workflow and a test file. These are replaced by a unit test.
1 parent b7c5505 commit 24133d4

9 files changed

Lines changed: 138 additions & 138 deletions

File tree

.github/workflows/CI-unixish.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,6 @@ jobs:
446446
python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump
447447
../../cppcheck --dump naming_test.cpp
448448
python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump
449-
../../cppcheck --dump namingng_test.c
450-
python3 ../namingng.py --configfile ../naming.json --verify namingng_test.c.dump
451449
452450
- name: Build democlient
453451
if: matrix.os == 'ubuntu-22.04'

.github/workflows/CI-windows.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,4 @@ jobs:
202202
rem python3 ..\naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump || exit /b !errorlevel!
203203
..\..\cppcheck --dump naming_test.cpp || exit /b !errorlevel!
204204
python3 ..\naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump || exit /b !errorlevel!
205-
..\..\cppcheck --dump namingng_test.c || exit /b !errorlevel!
206-
python3 ..\namingng.py --configfile ..\naming.json --verify namingng_test.c.dump || exit /b !errorlevel!
207205

addons/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ Addons are scripts that analyses Cppcheck dump files to check compatibility with
3333
Helper class for reading Cppcheck dump files within an addon.
3434
- misra_9.py
3535
Implementation of the MISRA 9.x rules used by `misra` addon.
36-
- naming.json
36+
- namingng.config.json
3737
Example configuration for `namingng` addon.
38+
- namingng.json
39+
Example JSON file that can be used using --addon=namingng.json, referring to namingng.py and namingng.config.json
3840
- ROS_naming.json
3941
Example configuration for the `namingng` addon enforcing the [ROS naming convention for C++ ](http://wiki.ros.org/CppStyleGuide#Files).
4042
- runaddon.py

addons/namingng.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"script":"namingng.py",
3+
"args":[
4+
"--configfile=namingng.config.json"
5+
]
6+
}

addons/namingng.py

Lines changed: 31 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -29,70 +29,59 @@
2929
import argparse
3030
import json
3131

32-
3332
# Auxiliary class
3433
class DataStruct:
3534
def __init__(self, file, linenr, string):
3635
self.file = file
3736
self.linenr = linenr
3837
self.str = string
38+
self.column = 0
3939

40-
41-
def reportError(filename, linenr, severity, msg):
42-
message = "[{filename}:{linenr}] ( {severity} ) naming.py: {msg}\n".format(
43-
filename=filename,
44-
linenr=linenr,
45-
severity=severity,
46-
msg=msg
47-
)
48-
sys.stderr.write(message)
49-
return message
50-
40+
def reportNamingError(location,message,errorId='namingConvention',severity='style',extra=''):
41+
cppcheckdata.reportError(location,severity,message,'namingng',errorId,extra)
5142

5243
def loadConfig(configfile):
5344
with open(configfile) as fh:
5445
data = json.load(fh)
5546
return data
5647

5748

58-
def checkTrueRegex(data, expr, msg, errors):
49+
def checkTrueRegex(data, expr, msg):
5950
res = re.match(expr, data.str)
6051
if res:
61-
errors.append(reportError(data.file, data.linenr, 'style', msg))
52+
reportNamingError(data,msg)
6253

6354

64-
def checkFalseRegex(data, expr, msg, errors):
55+
def checkFalseRegex(data, expr, msg):
6556
res = re.match(expr, data.str)
6657
if not res:
67-
errors.append(reportError(data.file, data.linenr, 'style', msg))
58+
reportNamingError(data,msg)
6859

6960

70-
def evalExpr(conf, exp, mockToken, msgType, errors):
61+
def evalExpr(conf, exp, mockToken, msgType):
7162
if isinstance(conf, dict):
7263
if conf[exp][0]:
7364
msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1]
74-
checkTrueRegex(mockToken, exp, msg, errors)
65+
checkTrueRegex(mockToken, exp, msg)
7566
elif ~conf[exp][0]:
7667
msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1]
77-
checkFalseRegex(mockToken, exp, msg, errors)
68+
checkFalseRegex(mockToken, exp, msg)
7869
else:
7970
msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][0]
80-
checkFalseRegex(mockToken, exp, msg, errors)
71+
checkFalseRegex(mockToken, exp, msg)
8172
else:
8273
msg = msgType + ' ' + mockToken.str + ' violates naming convention'
83-
checkFalseRegex(mockToken, exp, msg, errors)
74+
checkFalseRegex(mockToken, exp, msg)
8475

8576

8677
def process(dumpfiles, configfile, debugprint=False):
87-
88-
errors = []
89-
9078
conf = loadConfig(configfile)
9179

9280
for afile in dumpfiles:
9381
if not afile[-5:] == '.dump':
9482
continue
95-
print('Checking ' + afile + '...')
83+
if not args.cli:
84+
print('Checking ' + afile + '...')
9685
data = cppcheckdata.CppcheckData(afile)
9786

9887
# Check File naming
@@ -104,7 +93,8 @@ def process(dumpfiles, configfile, debugprint=False):
10493
good |= bool(re.match(exp, source_file))
10594
good |= bool(re.match(exp, basename))
10695
if not good:
107-
errors.append(reportError(source_file, 0, 'style', 'File name ' + source_file + ' violates naming convention'))
96+
mockToken = DataStruct(source_file, 0, basename)
97+
reportNamingError(mockToken, 'File name ' + basename + ' violates naming convention')
10898

10999
# Check Namespace naming
110100
if "RE_NAMESPACE" in conf and conf["RE_NAMESPACE"]:
@@ -113,10 +103,11 @@ def process(dumpfiles, configfile, debugprint=False):
113103
mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str)
114104
msgType = 'Namespace'
115105
for exp in conf["RE_NAMESPACE"]:
116-
evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType, errors)
106+
evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType)
117107

118108
for cfg in data.configurations:
119-
print('Checking %s, config %s...' % (afile, cfg.name))
109+
if not args.cli:
110+
print('Checking %s, config %s...' % (afile, cfg.name))
120111
if "RE_VARNAME" in conf and conf["RE_VARNAME"]:
121112
for var in cfg.variables:
122113
if var.nameToken and var.access != 'Global' and var.access != 'Public' and var.access != 'Private':
@@ -139,18 +130,15 @@ def process(dumpfiles, configfile, debugprint=False):
139130
continue
140131
if varType in conf.get("var_prefixes",{}):
141132
if not var.nameToken.str.startswith(conf["var_prefixes"][varType]):
142-
errors.append(reportError(
143-
var.typeStartToken.file,
144-
var.typeStartToken.linenr,
145-
'style',
133+
reportNamingError(var.typeStartToken,
146134
'Variable ' +
147135
var.nameToken.str +
148-
' violates naming convention'))
136+
' violates naming convention')
149137

150138
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
151139
msgType = 'Variable'
152140
for exp in conf["RE_VARNAME"]:
153-
evalExpr(conf["RE_VARNAME"], exp, mockToken, msgType, errors)
141+
evalExpr(conf["RE_VARNAME"], exp, mockToken, msgType)
154142

155143
# Check Private Variable naming
156144
if "RE_PRIVATE_MEMBER_VARIABLE" in conf and conf["RE_PRIVATE_MEMBER_VARIABLE"]:
@@ -161,7 +149,7 @@ def process(dumpfiles, configfile, debugprint=False):
161149
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
162150
msgType = 'Private member variable'
163151
for exp in conf["RE_PRIVATE_MEMBER_VARIABLE"]:
164-
evalExpr(conf["RE_PRIVATE_MEMBER_VARIABLE"], exp, mockToken, msgType, errors)
152+
evalExpr(conf["RE_PRIVATE_MEMBER_VARIABLE"], exp, mockToken, msgType)
165153

166154
# Check Public Member Variable naming
167155
if "RE_PUBLIC_MEMBER_VARIABLE" in conf and conf["RE_PUBLIC_MEMBER_VARIABLE"]:
@@ -171,7 +159,7 @@ def process(dumpfiles, configfile, debugprint=False):
171159
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
172160
msgType = 'Public member variable'
173161
for exp in conf["RE_PUBLIC_MEMBER_VARIABLE"]:
174-
evalExpr(conf["RE_PUBLIC_MEMBER_VARIABLE"], exp, mockToken, msgType, errors)
162+
evalExpr(conf["RE_PUBLIC_MEMBER_VARIABLE"], exp, mockToken, msgType)
175163

176164
# Check Global Variable naming
177165
if "RE_GLOBAL_VARNAME" in conf and conf["RE_GLOBAL_VARNAME"]:
@@ -181,7 +169,7 @@ def process(dumpfiles, configfile, debugprint=False):
181169
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
182170
msgType = 'Public member variable'
183171
for exp in conf["RE_GLOBAL_VARNAME"]:
184-
evalExpr(conf["RE_GLOBAL_VARNAME"], exp, mockToken, msgType, errors)
172+
evalExpr(conf["RE_GLOBAL_VARNAME"], exp, mockToken, msgType)
185173

186174
# Check Functions naming
187175
if "RE_FUNCTIONNAME" in conf and conf["RE_FUNCTIONNAME"]:
@@ -199,12 +187,11 @@ def process(dumpfiles, configfile, debugprint=False):
199187

200188
if retval and retval in conf.get("function_prefixes",{}):
201189
if not token.function.name.startswith(conf["function_prefixes"][retval]):
202-
errors.append(reportError(
203-
token.file, token.linenr, 'style', 'Function ' + token.function.name + ' violates naming convention'))
190+
reportNamingError(token, 'Function ' + token.function.name + ' violates naming convention')
204191
mockToken = DataStruct(token.file, token.linenr, token.function.name)
205192
msgType = 'Function'
206193
for exp in conf["RE_FUNCTIONNAME"]:
207-
evalExpr(conf["RE_FUNCTIONNAME"], exp, mockToken, msgType, errors)
194+
evalExpr(conf["RE_FUNCTIONNAME"], exp, mockToken, msgType)
208195

209196
# Check Class naming
210197
if "RE_CLASS_NAME" in conf and conf["RE_CLASS_NAME"]:
@@ -214,45 +201,16 @@ def process(dumpfiles, configfile, debugprint=False):
214201
mockToken = DataStruct(fnc.tokenDef.file, fnc.tokenDef.linenr, fnc.name)
215202
msgType = 'Class ' + fnc.type
216203
for exp in conf["RE_CLASS_NAME"]:
217-
evalExpr(conf["RE_CLASS_NAME"], exp, mockToken, msgType, errors)
218-
return errors
219-
204+
evalExpr(conf["RE_CLASS_NAME"], exp, mockToken, msgType)
220205

221206
if __name__ == "__main__":
222-
parser = argparse.ArgumentParser(description='Naming verification')
223-
parser.add_argument('dumpfiles', type=str, nargs='+',
224-
help='A set of dumpfiles to process')
207+
parser = cppcheckdata.ArgumentParser()
225208
parser.add_argument("--debugprint", action="store_true", default=False,
226209
help="Add debug prints")
227-
parser.add_argument("--configfile", type=str, default="naming.json",
210+
parser.add_argument("--configfile", type=str, default="namingng.config.json",
228211
help="Naming check config file")
229-
parser.add_argument("--verify", action="store_true", default=False,
230-
help="verify this script. Must be executed in test folder !")
231212

232213
args = parser.parse_args()
233-
errors = process(args.dumpfiles, args.configfile, args.debugprint)
234-
235-
if args.verify:
236-
print(errors)
237-
if len(errors) < 6:
238-
print("Not enough errors found")
239-
sys.exit(1)
240-
target = [
241-
'[namingng_test.c:8] ( style ) naming.py: Variable badui32 violates naming convention\n',
242-
'[namingng_test.c:11] ( style ) naming.py: Variable a violates naming convention\n',
243-
'[namingng_test.c:29] ( style ) naming.py: Variable badui32 violates naming convention\n',
244-
'[namingng_test.c:20] ( style ) naming.py: Function ui16bad_underscore violates naming convention\n',
245-
'[namingng_test.c:25] ( style ) naming.py: Function u32Bad violates naming convention\n',
246-
'[namingng_test.c:37] ( style ) naming.py: Function Badui16 violates naming convention\n']
247-
diff = set(errors) - set(target)
248-
if len(diff):
249-
print("Not the right errors found {}".format(str(diff)))
250-
sys.exit(1)
251-
print("Verification done\n")
252-
sys.exit(0)
253-
254-
if len(errors):
255-
print('Found errors: {}'.format(len(errors)))
256-
sys.exit(1)
214+
process(args.dumpfile, args.configfile, args.debugprint)
257215

258216
sys.exit(0)

addons/test/namingng_test.c

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)