File: naming.py

package info (click to toggle)
cppcheck 2.17.1-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 25,384 kB
  • sloc: cpp: 263,341; python: 19,737; ansic: 7,953; sh: 1,018; makefile: 996; xml: 994; cs: 291
file content (92 lines) | stat: -rwxr-xr-x 3,574 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/env python3
#
# cppcheck addon for naming conventions
#
# 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
#

import cppcheckdata
import sys
import re


def validate_regex(expr):
    try:
        re.compile(expr)
    except re.error:
        print('Error: "{}" is not a valid regular expression.'.format(expr))
        sys.exit(1)


RE_VARNAME = None
RE_CONSTNAME = None
RE_PRIVATE_MEMBER_VARIABLE = None
RE_FUNCTIONNAME = None
for arg in sys.argv[1:]:
    if arg[:6] == '--var=':
        RE_VARNAME = arg[6:]
        validate_regex(RE_VARNAME)
    elif arg.startswith('--const='):
        RE_CONSTNAME = arg[arg.find('=')+1:]
        validate_regex(RE_CONSTNAME)
    elif arg.startswith('--private-member-variable='):
        RE_PRIVATE_MEMBER_VARIABLE = arg[arg.find('=')+1:]
        validate_regex(RE_PRIVATE_MEMBER_VARIABLE)
    elif arg[:11] == '--function=':
        RE_FUNCTIONNAME = arg[11:]
        validate_regex(RE_FUNCTIONNAME)
    # TODO: bail out on unknown parameter


def reportError(token, severity, msg, errorId):
    cppcheckdata.reportError(token, severity, msg, 'naming', errorId)


for arg in sys.argv[1:]:
    if not arg.endswith('.dump'):
        continue
    print('Checking ' + arg + '...')
    data = cppcheckdata.CppcheckData(arg)

    for cfg in data.iterconfigurations():
        print('Checking %s, config %s...' % (arg, cfg.name))
        if RE_VARNAME:
            for var in cfg.variables:
                if var.access == 'Private':
                    continue
                if var.nameToken and not var.isConst:
                    res = re.match(RE_VARNAME, var.nameToken.str)
                    if not res:
                        reportError(var.typeStartToken, 'style', 'Variable ' +
                                    var.nameToken.str + ' violates naming convention', 'varname')
        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')
        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 ' +
                                var.nameToken.str + ' violates naming convention', 'privateMemberVariable')
        if RE_FUNCTIONNAME:
            for scope in cfg.scopes:
                if scope.type == 'Function':
                    function = scope.function
                    if function is not None and function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'):
                        continue
                    res = re.match(RE_FUNCTIONNAME, scope.className)
                    if not res:
                        reportError(
                            scope.bodyStart, 'style', 'Function ' + scope.className + ' violates naming convention', 'functionName')

sys.exit(cppcheckdata.EXIT_CODE)