Fix dogfood failures by refactoring open_options

This commit is contained in:
Manish Goregaokar 2016-01-04 10:13:56 +05:30
parent c9342d0121
commit c1a99fdd90
2 changed files with 75 additions and 122 deletions

View file

@ -1,6 +1,7 @@
#![feature(plugin_registrar, box_syntax)]
#![feature(rustc_private, collections)]
#![feature(num_bits_bytes, iter_arith)]
#![feature(custom_attribute)]
#![allow(unknown_lints)]
// this only exists to allow the "dogfood" integration test to work
@ -77,6 +78,7 @@ mod reexport {
}
#[plugin_registrar]
#[rustfmt_skip]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_late_lint_pass(box types::TypePass);
reg.register_late_lint_pass(box misc::TopLevelRefPass);
@ -130,8 +132,8 @@ pub fn plugin_registrar(reg: &mut Registry) {
reg.register_late_lint_pass(box array_indexing::ArrayIndexing);
reg.register_late_lint_pass(box panic::PanicPass);
reg.register_lint_group("clippy_pedantic",
vec![
reg.register_lint_group("clippy_pedantic", vec![
methods::OPTION_UNWRAP_USED,
methods::RESULT_UNWRAP_USED,
methods::WRONG_PUB_SELF_CONVENTION,
@ -150,8 +152,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
unicode::UNICODE_NOT_NFC,
]);
reg.register_lint_group("clippy",
vec![
reg.register_lint_group("clippy", vec![
approx_const::APPROX_CONSTANT,
array_indexing::OUT_OF_BOUNDS_INDEXING,
attrs::INLINE_ALWAYS,

View file

@ -40,7 +40,7 @@ impl LateLintPass for NonSensicalOpenOptions {
}
}
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Argument {
True,
False,
@ -104,130 +104,82 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp
}
}
fn check_for_duplicates(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) {
fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) {
let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false);
let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) = (false,
false,
false,
false,
false);
// This code is almost duplicated (oh, the irony), but I haven't found a way to unify it.
if options.iter()
.filter(|o| {
if let (OpenOption::Create, _) = **o {
true
} else {
false
}
})
.count() > 1 {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"create\" is called more than once");
}
if options.iter()
.filter(|o| {
if let (OpenOption::Append, _) = **o {
true
} else {
false
}
})
.count() > 1 {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"append\" is called more than once");
}
if options.iter()
.filter(|o| {
if let (OpenOption::Truncate, _) = **o {
true
} else {
false
}
})
.count() > 1 {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"truncate\" is called more than once");
}
if options.iter()
.filter(|o| {
if let (OpenOption::Read, _) = **o {
true
} else {
false
}
})
.count() > 1 {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"read\" is called more than once");
}
if options.iter()
.filter(|o| {
if let (OpenOption::Write, _) = **o {
true
} else {
false
}
})
.count() > 1 {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"write\" is called more than once");
}
}
fn check_for_inconsistencies(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) {
// Truncate + read makes no sense.
if options.iter()
.filter(|o| {
if let (OpenOption::Read, Argument::True) = **o {
true
} else {
false
}
})
.count() > 0 &&
options.iter()
.filter(|o| {
if let (OpenOption::Truncate, Argument::True) = **o {
true
} else {
false
}
})
.count() > 0 {
for option in options {
match *option {
(OpenOption::Create, arg) => {
if create {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"create\" is called more than once");
} else {
create = true
}
create_arg = create_arg || (arg == Argument::True);;
}
(OpenOption::Append, arg) => {
if append {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"append\" is called more than once");
} else {
append = true
}
append_arg = append_arg || (arg == Argument::True);;
}
(OpenOption::Truncate, arg) => {
if truncate {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"truncate\" is called more than once");
} else {
truncate = true
}
truncate_arg = truncate_arg || (arg == Argument::True);
}
(OpenOption::Read, arg) => {
if read {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"read\" is called more than once");
} else {
read = true
}
read_arg = read_arg || (arg == Argument::True);;
}
(OpenOption::Write, arg) => {
if write {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"The method \"write\" is called more than once");
} else {
write = true
}
write_arg = write_arg || (arg == Argument::True);;
}
}
}
if read && truncate && read_arg && truncate_arg {
span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "File opened with \"truncate\" and \"read\"");
}
// Append + truncate makes no sense.
if options.iter()
.filter(|o| {
if let (OpenOption::Append, Argument::True) = **o {
true
} else {
false
}
})
.count() > 0 &&
options.iter()
.filter(|o| {
if let (OpenOption::Truncate, Argument::True) = **o {
true
} else {
false
}
})
.count() > 0 {
if append && truncate && append_arg && truncate_arg {
span_lint(cx,
NONSENSICAL_OPEN_OPTIONS,
span,
"File opened with \"append\" and \"truncate\"");
}
}
fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) {
check_for_duplicates(cx, options, span);
check_for_inconsistencies(cx, options, span);
}