diff options
Diffstat (limited to 'src/tools/clippy/util/lintlib.py')
| -rw-r--r-- | src/tools/clippy/util/lintlib.py | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/src/tools/clippy/util/lintlib.py b/src/tools/clippy/util/lintlib.py new file mode 100644 index 00000000000..d0d9beb9b2d --- /dev/null +++ b/src/tools/clippy/util/lintlib.py @@ -0,0 +1,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 |
