update_lints: add a check mode for travis runs

This commit is contained in:
Georg Brandl 2015-08-13 10:32:35 +02:00
parent 1d64553bc6
commit e03b71606b
4 changed files with 52 additions and 34 deletions

View file

@ -3,5 +3,6 @@ rust: nightly
sudo: false
script:
- python util/update_lints.py -c
- cargo build
- cargo test

View file

@ -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

View file

@ -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")
}
}
}

73
util/update_lints.py Normal file → Executable file
View file

@ -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))