From e03b71606ba7682e46603302a679ecdc30ce8373 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Thu, 13 Aug 2015 10:32:35 +0200 Subject: [PATCH] update_lints: add a check mode for travis runs --- .travis.yml | 1 + README.md | 4 +-- src/strings.rs | 8 ++--- util/update_lints.py | 73 +++++++++++++++++++++++++++----------------- 4 files changed, 52 insertions(+), 34 deletions(-) mode change 100644 => 100755 util/update_lints.py diff --git a/.travis.yml b/.travis.yml index 0f9d6128e..e14785c92 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,6 @@ rust: nightly sudo: false script: + - python util/update_lints.py -c - cargo build - cargo test diff --git a/README.md b/README.md index 5f9f59c31..f6b65b952 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ redundant_closure | warn | using redundant closures, i.e. `|a| foo(a)` (wh result_unwrap_used | allow | using `Result.unwrap()`, which might be better handled single_match | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead str_to_string | warn | using `to_string()` on a str, which should be `to_owned()` -string_add | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead -string_add_assign | allow | expressions of the form `x = x + ..` where x is a `String` +string_add | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead +string_add_assign | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead string_to_string | warn | calling `String.to_string()` which is a no-op toplevel_ref_arg | warn | a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`) zero_width_space | deny | using a zero-width space in a string literal, which is confusing diff --git a/src/strings.rs b/src/strings.rs index 84512dfe7..7b7bab49b 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -14,13 +14,13 @@ use utils::{match_def_path, span_lint, walk_ptrs_ty, get_parent_expr}; declare_lint! { pub STRING_ADD_ASSIGN, Allow, - "expressions of the form `x = x + ..` where x is a `String`" + "using `x = x + ..` where x is a `String`; suggests using `push_str()` instead" } declare_lint! { pub STRING_ADD, Allow, - "using `x = x + ..` where x is a `String`; suggests using `push_str()` instead" + "using `x + ..` where x is a `String`; suggests using `push_str()` instead" } #[derive(Copy, Clone)] @@ -48,13 +48,13 @@ impl LintPass for StringAdd { //TODO check for duplicates span_lint(cx, STRING_ADD, e.span, "you added something to a string. \ - Consider using `String::push_str()` instead.") + Consider using `String::push_str()` instead") } } else if let &ExprAssign(ref target, ref src) = &e.node { if is_string(cx, target) && is_add(src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. \ - Consider using `String::push_str()` instead.") + Consider using `String::push_str()` instead") } } } diff --git a/util/update_lints.py b/util/update_lints.py old mode 100644 new mode 100755 index c2a9e08c9..ed2663705 --- a/util/update_lints.py +++ b/util/update_lints.py @@ -1,5 +1,7 @@ +#!/usr/bin/env python # Generate a Markdown table of all lints, and put it in README.md. # With -n option, only print the new table to stdout. +# With -c option, print a warning and set exit status to 1 if a file would be changed. import os import re @@ -31,27 +33,27 @@ def collect(lints, fn): desc.replace('\\"', '"'))) -def write_tbl(lints, fp): +def gen_table(lints): """Write lint table in Markdown format.""" # first and third column widths w_name = max(len(l[1]) for l in lints) w_desc = max(len(l[3]) for l in lints) # header and underline - fp.write('%-*s | default | meaning\n' % (w_name, 'name')) - fp.write('%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc)) + yield '%-*s | default | meaning\n' % (w_name, 'name') + yield '%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc) # one table row per lint for (_, name, default, meaning) in sorted(lints, key=lambda l: l[1]): - fp.write('%-*s | %-7s | %s\n' % (w_name, name, default, meaning)) + yield '%-*s | %-7s | %s\n' % (w_name, name, default, meaning) -def write_group(lints, fp): +def gen_group(lints): """Write lint group (list of all lints in the form module::NAME).""" for (module, name, _, _) in sorted(lints): - fp.write(' %s::%s,\n' % (module, name.upper())) + yield ' %s::%s,\n' % (module, name.upper()) def replace_region(fn, region_start, region_end, callback, - replace_start=True): + replace_start=True, write_back=True): """Replace a region in a file delimited by two lines matching regexes. A callback is called to write the new region. If `replace_start` is true, @@ -63,24 +65,32 @@ def replace_region(fn, region_start, region_end, callback, lines = list(fp) # replace old region with new region - with open(fn, 'w') as fp: - in_old_region = False - for line in lines: - if in_old_region: - if re.search(region_end, line): - in_old_region = False - fp.write(line) - elif re.search(region_start, line): - if not replace_start: - fp.write(line) - # old region starts here - in_old_region = True - callback(fp) - else: - fp.write(line) + new_lines = [] + in_old_region = False + for line in lines: + if in_old_region: + if re.search(region_end, line): + in_old_region = False + new_lines.extend(callback()) + new_lines.append(line) + elif re.search(region_start, line): + if not replace_start: + new_lines.append(line) + # old region starts here + in_old_region = True + else: + new_lines.append(line) + + # write back to file + if write_back: + with open(fn, 'w') as fp: + fp.writelines(new_lines) + + # if something changed, return true + return lines != new_lines -def main(print_only=False): +def main(print_only=False, check=False): lints = [] # check directory @@ -95,16 +105,23 @@ def main(print_only=False): collect(lints, os.path.join(root, fn)) if print_only: - write_tbl(lints, sys.stdout) + sys.stdout.writelines(gen_table(lints)) return # replace table in README.md - replace_region('README.md', r'^name +\|', '^$', lambda fp: write_tbl(lints, fp)) + changed = replace_region('README.md', r'^name +\|', '^$', + lambda: gen_table(lints), + write_back=not check) # same for "clippy" lint collection - replace_region('src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', - lambda fp: write_group(lints, fp), replace_start=False) + changed |= replace_region('src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', + lambda: gen_group(lints), replace_start=False, + write_back=not check) + + if check and changed: + print('Please run util/update_lints.py to regenerate lints lists.') + return 1 if __name__ == '__main__': - main(print_only='-n' in sys.argv) + sys.exit(main(print_only='-n' in sys.argv, check='-c' in sys.argv))