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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
# Common utils for the several housekeeping scripts.
import os
import re
import collections
import logging as log
log.basicConfig(level=log.INFO, format='%(levelname)s: %(message)s')
Lint = collections.namedtuple('Lint', 'name level doc sourcefile group')
Config = collections.namedtuple('Config', 'name ty doc default')
lintname_re = re.compile(r'''pub\s+([A-Z_][A-Z_0-9]*)''')
group_re = re.compile(r'''\s*([a-z_][a-z_0-9]+)''')
conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE)
confvar_re = re.compile(
r'''/// Lint: ([\w,\s]+)\. (.*)\n\s*\([^,]+,\s+"([^"]+)":\s+([^,]+),\s+([^\.\)]+).*\),''', re.MULTILINE)
comment_re = re.compile(r'''\s*/// ?(.*)''')
lint_levels = {
"correctness": 'Deny',
"style": 'Warn',
"complexity": 'Warn',
"perf": 'Warn',
"restriction": 'Allow',
"pedantic": 'Allow',
"nursery": 'Allow',
"cargo": 'Allow',
}
def parse_lints(lints, filepath):
comment = []
clippy = False
deprecated = False
name = ""
with open(filepath) as fp:
for line in fp:
if clippy or deprecated:
m = lintname_re.search(line)
if m:
name = m.group(1).lower()
line = next(fp)
if deprecated:
level = "Deprecated"
group = "deprecated"
else:
while True:
g = group_re.search(line)
if g:
group = g.group(1).lower()
level = lint_levels.get(group, None)
break
line = next(fp)
if level is None:
continue
log.info("found %s with level %s in %s",
name, level, filepath)
lints.append(Lint(name, level, comment, filepath, group))
comment = []
clippy = False
deprecated = False
name = ""
else:
m = comment_re.search(line)
if m:
comment.append(m.group(1))
elif line.startswith("declare_clippy_lint!"):
clippy = True
deprecated = False
elif line.startswith("declare_deprecated_lint!"):
clippy = False
deprecated = True
elif line.startswith("declare_lint!"):
import sys
print(
"don't use `declare_lint!` in Clippy, "
"use `declare_clippy_lint!` instead"
)
sys.exit(42)
def parse_configs(path):
configs = {}
with open(os.path.join(path, 'utils/conf.rs')) as fp:
contents = fp.read()
match = re.search(conf_re, contents)
confvars = re.findall(confvar_re, match.group(1))
for (lints, doc, name, ty, default) in confvars:
for lint in lints.split(','):
configs[lint.strip().lower()] = Config(name.replace("_", "-"), ty, doc, default)
return configs
def parse_all(path="clippy_lints/src"):
lints = []
for root, dirs, files in os.walk(path):
for fn in files:
if fn.endswith('.rs'):
parse_lints(lints, os.path.join(root, fn))
log.info("got %s lints", len(lints))
configs = parse_configs(path)
log.info("got %d configs", len(configs))
return lints, configs
|