Merge pull request #154 from birkenfeld/travis_check_script

update_lints: add a check mode for travis runs
This commit is contained in:
llogiq 2015-08-13 15:35:24 +02:00
commit c1416f8827
4 changed files with 52 additions and 34 deletions

View file

@ -3,5 +3,6 @@ rust: nightly
sudo: false sudo: false
script: script:
- python util/update_lints.py -c
- cargo build - cargo build
- cargo test - 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 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 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()` 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 | allow | using `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_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 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))`) 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 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! { declare_lint! {
pub STRING_ADD_ASSIGN, pub STRING_ADD_ASSIGN,
Allow, 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! { declare_lint! {
pub STRING_ADD, pub STRING_ADD,
Allow, 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)] #[derive(Copy, Clone)]
@ -48,13 +48,13 @@ impl LintPass for StringAdd {
//TODO check for duplicates //TODO check for duplicates
span_lint(cx, STRING_ADD, e.span, span_lint(cx, STRING_ADD, e.span,
"you added something to a string. \ "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 { } else if let &ExprAssign(ref target, ref src) = &e.node {
if is_string(cx, target) && is_add(src, target) { if is_string(cx, target) && is_add(src, target) {
span_lint(cx, STRING_ADD_ASSIGN, e.span, span_lint(cx, STRING_ADD_ASSIGN, e.span,
"you assigned the result of adding something to this string. \ "you assigned the result of adding something to this string. \
Consider using `String::push_str()` instead.") Consider using `String::push_str()` instead")
} }
} }
} }

53
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. # Generate a Markdown table of all lints, and put it in README.md.
# With -n option, only print the new table to stdout. # 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 os
import re import re
@ -31,27 +33,27 @@ def collect(lints, fn):
desc.replace('\\"', '"'))) desc.replace('\\"', '"')))
def write_tbl(lints, fp): def gen_table(lints):
"""Write lint table in Markdown format.""" """Write lint table in Markdown format."""
# first and third column widths # first and third column widths
w_name = max(len(l[1]) for l in lints) w_name = max(len(l[1]) for l in lints)
w_desc = max(len(l[3]) for l in lints) w_desc = max(len(l[3]) for l in lints)
# header and underline # header and underline
fp.write('%-*s | default | meaning\n' % (w_name, 'name')) yield '%-*s | default | meaning\n' % (w_name, 'name')
fp.write('%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc)) yield '%s-|-%s-|-%s\n' % ('-' * w_name, '-' * 7, '-' * w_desc)
# one table row per lint # one table row per lint
for (_, name, default, meaning) in sorted(lints, key=lambda l: l[1]): 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).""" """Write lint group (list of all lints in the form module::NAME)."""
for (module, name, _, _) in sorted(lints): 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, 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. """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, 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) lines = list(fp)
# replace old region with new region # replace old region with new region
with open(fn, 'w') as fp: new_lines = []
in_old_region = False in_old_region = False
for line in lines: for line in lines:
if in_old_region: if in_old_region:
if re.search(region_end, line): if re.search(region_end, line):
in_old_region = False in_old_region = False
fp.write(line) new_lines.extend(callback())
new_lines.append(line)
elif re.search(region_start, line): elif re.search(region_start, line):
if not replace_start: if not replace_start:
fp.write(line) new_lines.append(line)
# old region starts here # old region starts here
in_old_region = True in_old_region = True
callback(fp)
else: else:
fp.write(line) 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 = [] lints = []
# check directory # check directory
@ -95,16 +105,23 @@ def main(print_only=False):
collect(lints, os.path.join(root, fn)) collect(lints, os.path.join(root, fn))
if print_only: if print_only:
write_tbl(lints, sys.stdout) sys.stdout.writelines(gen_table(lints))
return return
# replace table in README.md # 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 # same for "clippy" lint collection
replace_region('src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);', changed |= replace_region('src/lib.rs', r'reg.register_lint_group\("clippy"', r'\]\);',
lambda fp: write_group(lints, fp), replace_start=False) 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__': if __name__ == '__main__':
main(print_only='-n' in sys.argv) sys.exit(main(print_only='-n' in sys.argv, check='-c' in sys.argv))