diff --git a/CHANGELOG.md b/CHANGELOG.md index 790bbc04691b..3c2f9e1a622e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -240,6 +240,7 @@ All notable changes to this project will be documented in this file. [`string_add_assign`]: https://github.com/Manishearth/rust-clippy/wiki#string_add_assign [`string_lit_as_bytes`]: https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes [`string_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#string_to_string +[`stutter`]: https://github.com/Manishearth/rust-clippy/wiki#stutter [`suspicious_assignment_formatting`]: https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting [`suspicious_else_formatting`]: https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting [`temporary_assignment`]: https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment diff --git a/README.md b/README.md index 85e9ed70bf84..a8e8cbb3a5ad 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 153 lints included in this crate: +There are 154 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -144,6 +144,7 @@ name [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead [string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead +[stutter](https://github.com/Manishearth/rust-clippy/wiki#stutter) | allow | finds type names prefixed/postfixed with their containing module's name [suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=` [suspicious_else_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting) | warn | suspicious formatting of `else if` [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 6d842ce64fc2..967fd8b47c60 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -37,15 +37,15 @@ const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[(f64::E, "E", 4), (f64::SQRT_2, "SQRT_2", 5)]; #[derive(Copy,Clone)] -pub struct ApproxConstant; +pub struct Pass; -impl LintPass for ApproxConstant { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(APPROX_CONSTANT) } } -impl LateLintPass for ApproxConstant { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprLit(ref lit) = e.node { check_lit(cx, lit, e); diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index fc9e95f94955..4306204e5270 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -80,7 +80,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a } #[allow(while_let_loop)] // #362 -pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span)]) -> Result<(), ()> { +fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span)]) -> Result<(), ()> { // In markdown, `_` can be used to emphasize something, or, is a raw `_` depending on context. // There really is no markdown specification that would disambiguate this properly. This is // what GitHub and Rustdoc do: diff --git a/clippy_lints/src/drop_ref.rs b/clippy_lints/src/drop_ref.rs index 268497f99d44..8c299b8f2d6d 100644 --- a/clippy_lints/src/drop_ref.rs +++ b/clippy_lints/src/drop_ref.rs @@ -23,15 +23,15 @@ declare_lint! { } #[allow(missing_copy_implementations)] -pub struct DropRefPass; +pub struct Pass; -impl LintPass for DropRefPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(DROP_REF) } } -impl LateLintPass for DropRefPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprCall(ref path, ref args) = expr.node { if let ExprPath(None, _) = path.node { diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 39c31864f397..0390cd6c5d64 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -18,15 +18,15 @@ declare_lint! { "finds C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`" } -pub struct EnumClikeUnportableVariant; +pub struct UnportableVariant; -impl LintPass for EnumClikeUnportableVariant { +impl LintPass for UnportableVariant { fn get_lints(&self) -> LintArray { lint_array!(ENUM_CLIKE_UNPORTABLE_VARIANT) } } -impl LateLintPass for EnumClikeUnportableVariant { +impl LateLintPass for UnportableVariant { #[allow(cast_possible_truncation, cast_sign_loss)] fn check_item(&mut self, cx: &LateContext, item: &Item) { if let ItemEnum(ref def, _) = item.node { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 67a8495e1557..4bf65ec42973 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -2,9 +2,10 @@ use rustc::lint::*; use syntax::ast::*; +use syntax::codemap::Span; use syntax::parse::token::InternedString; -use utils::span_help_and_lint; -use utils::{camel_case_from, camel_case_until}; +use utils::{span_help_and_lint, span_lint}; +use utils::{camel_case_from, camel_case_until, in_macro}; /// **What it does:** Warns on enum variants that are prefixed or suffixed by the same characters /// @@ -18,11 +19,26 @@ declare_lint! { "finds enums where all variants share a prefix/postfix" } -pub struct EnumVariantNames; +/// **What it does:** Warns on type names that are prefixed or suffixed by the containing module's name +/// +/// **Why is this bad?** It requires the user to type the module name twice +/// +/// **Known problems:** None +/// +/// **Example:** mod cake { struct BlackForestCake; } +declare_lint! { + pub STUTTER, Allow, + "finds type names prefixed/postfixed with their containing module's name" +} + +#[derive(Default)] +pub struct EnumVariantNames { + modules: Vec, +} impl LintPass for EnumVariantNames { fn get_lints(&self) -> LintArray { - lint_array!(ENUM_VARIANT_NAMES) + lint_array!(ENUM_VARIANT_NAMES, STUTTER) } } @@ -30,75 +46,126 @@ fn var2str(var: &Variant) -> InternedString { var.node.name.name.as_str() } -// FIXME: waiting for https://github.com/rust-lang/rust/pull/31700 -// fn partial_match(pre: &str, name: &str) -> usize { -// // skip(1) to ensure that the prefix never takes the whole variant name -// pre.chars().zip(name.chars().rev().skip(1).rev()).take_while(|&(l, r)| l == r).count() -// } -// -// fn partial_rmatch(post: &str, name: &str) -> usize { -// // skip(1) to ensure that the postfix never takes the whole variant name -// post.chars().rev().zip(name.chars().skip(1).rev()).take_while(|&(l, r)| l == r).count() -// } - +/// Returns the number of chars that match from the start fn partial_match(pre: &str, name: &str) -> usize { let mut name_iter = name.chars(); let _ = name_iter.next_back(); // make sure the name is never fully matched pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count() } +/// Returns the number of chars that match from the end fn partial_rmatch(post: &str, name: &str) -> usize { let mut name_iter = name.chars(); let _ = name_iter.next(); // make sure the name is never fully matched post.chars().rev().zip(name_iter.rev()).take_while(|&(l, r)| l == r).count() } -impl EarlyLintPass for EnumVariantNames { - // FIXME: #600 - #[allow(while_let_on_iterator)] - fn check_item(&mut self, cx: &EarlyContext, item: &Item) { - if let ItemKind::Enum(ref def, _) = item.node { - if def.variants.len() < 2 { - return; +// FIXME: #600 +#[allow(while_let_on_iterator)] +fn check_variant(cx: &EarlyContext, def: &EnumDef, item_name: &str, item_name_chars: usize, span: Span) { + for var in &def.variants { + let name = var2str(var); + if partial_match(item_name, &name) == item_name_chars { + span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name starts with the enum's name"); + } + if partial_rmatch(item_name, &name) == item_name_chars { + span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name ends with the enum's name"); + } + } + if def.variants.len() < 2 { + return; + } + let first = var2str(&def.variants[0]); + let mut pre = &first[..camel_case_until(&*first)]; + let mut post = &first[camel_case_from(&*first)..]; + for var in &def.variants { + let name = var2str(var); + + let pre_match = partial_match(pre, &name); + pre = &pre[..pre_match]; + let pre_camel = camel_case_until(pre); + pre = &pre[..pre_camel]; + while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { + if next.is_lowercase() { + let last = pre.len() - last.len_utf8(); + let last_camel = camel_case_until(&pre[..last]); + pre = &pre[..last_camel]; + } else { + break; } - let first = var2str(&def.variants[0]); - let mut pre = &first[..camel_case_until(&*first)]; - let mut post = &first[camel_case_from(&*first)..]; - for var in &def.variants { - let name = var2str(var); + } - let pre_match = partial_match(pre, &name); - pre = &pre[..pre_match]; - let pre_camel = camel_case_until(pre); - pre = &pre[..pre_camel]; - while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { - if next.is_lowercase() { - let last = pre.len() - last.len_utf8(); - let last_camel = camel_case_until(&pre[..last]); - pre = &pre[..last_camel]; - } else { - break; + let post_match = partial_rmatch(post, &name); + let post_end = post.len() - post_match; + post = &post[post_end..]; + let post_camel = camel_case_from(post); + post = &post[post_camel..]; + } + let (what, value) = match (pre.is_empty(), post.is_empty()) { + (true, true) => return, + (false, _) => ("pre", pre), + (true, false) => ("post", post), + }; + span_help_and_lint(cx, + ENUM_VARIANT_NAMES, + span, + &format!("All variants have the same {}fix: `{}`", what, value), + &format!("remove the {}fixes and use full paths to \ + the variants instead of glob imports", + what)); +} + +fn to_camel_case(item_name: &str) -> String { + let mut s = String::new(); + let mut up = true; + for c in item_name.chars() { + if c.is_uppercase() { + // we only turn snake case text into CamelCase + return item_name.to_string(); + } + if c == '_' { + up = true; + continue; + } + if up { + up = false; + s.extend(c.to_uppercase()); + } else { + s.push(c); + } + } + s +} + +impl EarlyLintPass for EnumVariantNames { + fn check_item_post(&mut self, _cx: &EarlyContext, _item: &Item) { + let last = self.modules.pop(); + assert!(last.is_some()); + } + + fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + let item_name = item.ident.name.as_str(); + let item_name_chars = item_name.chars().count(); + let item_camel = to_camel_case(&item_name); + if item.vis == Visibility::Public && !in_macro(cx, item.span) { + if let Some(mod_camel) = self.modules.last() { + // constants don't have surrounding modules + if !mod_camel.is_empty() { + let matching = partial_match(mod_camel, &item_camel); + let rmatching = partial_rmatch(mod_camel, &item_camel); + let nchars = mod_camel.chars().count(); + if matching == nchars { + span_lint(cx, STUTTER, item.span, &format!("Item name ({}) starts with its containing module's name ({})", item_camel, mod_camel)); + } + if rmatching == nchars { + span_lint(cx, STUTTER, item.span, &format!("Item name ({}) ends with its containing module's name ({})", item_camel, mod_camel)); } } - - let post_match = partial_rmatch(post, &name); - let post_end = post.len() - post_match; - post = &post[post_end..]; - let post_camel = camel_case_from(post); - post = &post[post_camel..]; } - let (what, value) = match (pre.is_empty(), post.is_empty()) { - (true, true) => return, - (false, _) => ("pre", pre), - (true, false) => ("post", post), - }; - span_help_and_lint(cx, - ENUM_VARIANT_NAMES, - item.span, - &format!("All variants have the same {}fix: `{}`", what, value), - &format!("remove the {}fixes and use full paths to \ - the variants instead of glob imports", - what)); } + if let ItemKind::Enum(ref def, _) = item.node { + check_variant(cx, def, &item_name, item_name_chars, item.span); + } + self.modules.push(item_camel); } } diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index b5172269a1e9..2bdfe91a9086 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -11,7 +11,7 @@ use syntax::ast::NodeId; use syntax::codemap::Span; use utils::span_lint; -pub struct EscapePass; +pub struct Pass; /// **What it does:** This lint checks for usage of `Box` where an unboxed `T` would work fine. /// @@ -44,13 +44,13 @@ struct EscapeDelegate<'a, 'tcx: 'a> { set: NodeSet, } -impl LintPass for EscapePass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(BOXED_LOCAL) } } -impl LateLintPass for EscapePass { +impl LateLintPass for Pass { fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) { let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id); diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 0123dec070fc..2b3835d780fa 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -23,15 +23,15 @@ declare_lint! { } #[derive(Copy, Clone, Debug)] -pub struct FormatMacLint; +pub struct Pass; -impl LintPass for FormatMacLint { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array![USELESS_FORMAT] } } -impl LateLintPass for FormatMacLint { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let Some(span) = is_expn_of(cx, expr.span, "format") { match expr.node { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d64f653dd4cc..b68596f25355 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -132,7 +132,7 @@ mod reexport { #[cfg_attr(rustfmt, rustfmt_skip)] pub fn register_plugins(reg: &mut rustc_plugin::Registry) { - let conf = match utils::conf::conf_file(reg.args()) { + let conf = match utils::conf::file(reg.args()) { Ok(file_name) => { // if the user specified a file, it must exist, otherwise default to `clippy.toml` but // do not require the file to exist @@ -142,7 +142,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ("clippy.toml", false) }; - let (conf, errors) = utils::conf::read_conf(file_name, must_exist); + let (conf, errors) = utils::conf::read(file_name, must_exist); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { @@ -171,14 +171,14 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box misc::TopLevelRefPass); reg.register_late_lint_pass(box misc::CmpNan); reg.register_late_lint_pass(box eq_op::EqOp); - reg.register_early_lint_pass(box enum_variants::EnumVariantNames); + reg.register_early_lint_pass(box enum_variants::EnumVariantNames::default()); reg.register_late_lint_pass(box enum_glob_use::EnumGlobUse); - reg.register_late_lint_pass(box enum_clike::EnumClikeUnportableVariant); + reg.register_late_lint_pass(box enum_clike::UnportableVariant); reg.register_late_lint_pass(box bit_mask::BitMask); reg.register_late_lint_pass(box ptr_arg::PtrArg); reg.register_late_lint_pass(box needless_bool::NeedlessBool); reg.register_late_lint_pass(box needless_bool::BoolComparison); - reg.register_late_lint_pass(box approx_const::ApproxConstant); + reg.register_late_lint_pass(box approx_const::Pass); reg.register_late_lint_pass(box misc::FloatCmp); reg.register_early_lint_pass(box precedence::Precedence); reg.register_late_lint_pass(box eta_reduction::EtaPass); @@ -195,11 +195,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); - reg.register_late_lint_pass(box methods::MethodsPass); - reg.register_late_lint_pass(box shadow::ShadowPass); + reg.register_late_lint_pass(box methods::Pass); + reg.register_late_lint_pass(box shadow::Pass); reg.register_late_lint_pass(box types::LetPass); reg.register_late_lint_pass(box types::UnitCmp); - reg.register_late_lint_pass(box loops::LoopsPass); + reg.register_late_lint_pass(box loops::Pass); reg.register_late_lint_pass(box lifetimes::LifetimePass); reg.register_late_lint_pass(box entry::HashMapLint); reg.register_late_lint_pass(box ranges::StepByZero); @@ -208,35 +208,35 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box matches::MatchPass); reg.register_late_lint_pass(box misc::PatternPass); reg.register_late_lint_pass(box minmax::MinMaxPass); - reg.register_late_lint_pass(box open_options::NonSensicalOpenOptions); - reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); + reg.register_late_lint_pass(box open_options::NonSensical); + reg.register_late_lint_pass(box zero_div_zero::Pass); reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); - reg.register_late_lint_pass(box needless_update::NeedlessUpdatePass); + reg.register_late_lint_pass(box needless_update::Pass); reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); - reg.register_late_lint_pass(box no_effect::NoEffectPass); - reg.register_late_lint_pass(box map_clone::MapClonePass); - reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); + reg.register_late_lint_pass(box no_effect::Pass); + reg.register_late_lint_pass(box map_clone::Pass); + reg.register_late_lint_pass(box temporary_assignment::Pass); reg.register_late_lint_pass(box transmute::Transmute); reg.register_late_lint_pass(box cyclomatic_complexity::CyclomaticComplexity::new(conf.cyclomatic_complexity_threshold)); - reg.register_late_lint_pass(box escape::EscapePass); + reg.register_late_lint_pass(box escape::Pass); reg.register_early_lint_pass(box misc_early::MiscEarly); reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); reg.register_late_lint_pass(box array_indexing::ArrayIndexing); - reg.register_late_lint_pass(box panic::PanicPass); + reg.register_late_lint_pass(box panic::Pass); reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); - reg.register_late_lint_pass(box print::PrintLint); - reg.register_late_lint_pass(box vec::UselessVec); + reg.register_late_lint_pass(box print::Pass); + reg.register_late_lint_pass(box vec::Pass); reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { max_single_char_names: conf.max_single_char_names, }); - reg.register_late_lint_pass(box drop_ref::DropRefPass); + reg.register_late_lint_pass(box drop_ref::Pass); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); reg.register_late_lint_pass(box types::InvalidUpcastComparisons); - reg.register_late_lint_pass(box regex::RegexPass::default()); + reg.register_late_lint_pass(box regex::Pass::default()); reg.register_late_lint_pass(box copies::CopyAndPaste); - reg.register_late_lint_pass(box format::FormatMacLint); + reg.register_late_lint_pass(box format::Pass); reg.register_early_lint_pass(box formatting::Formatting); reg.register_late_lint_pass(box swap::Swap); reg.register_early_lint_pass(box if_not_else::IfNotElse); @@ -263,6 +263,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { array_indexing::INDEXING_SLICING, booleans::NONMINIMAL_BOOL, enum_glob_use::ENUM_GLOB_USE, + enum_variants::STUTTER, if_not_else::IF_NOT_ELSE, items_after_statements::ITEMS_AFTER_STATEMENTS, matches::SINGLE_MATCH_ELSE, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f3f10fae16e4..bcb62ec01b6c 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -205,9 +205,9 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct LoopsPass; +pub struct Pass; -impl LintPass for LoopsPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, @@ -222,7 +222,7 @@ impl LintPass for LoopsPass { } } -impl LateLintPass for LoopsPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let Some((pat, arg, body)) = recover_for_loop(expr) { check_for_loop(cx, pat, arg, body, expr); diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 168aade325de..5959d70d9bcb 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -18,9 +18,9 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct MapClonePass; +pub struct Pass; -impl LateLintPass for MapClonePass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { // call to .map() if let ExprMethodCall(name, _, ref args) = expr.node { @@ -119,7 +119,7 @@ fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Name) -> bool { } } -impl LintPass for MapClonePass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(MAP_CLONE) } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index da1420c3add7..45d2e259dfad 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -17,7 +17,7 @@ use utils::MethodArgs; use utils::paths; #[derive(Clone)] -pub struct MethodsPass; +pub struct Pass; /// **What it does:** This lint checks for `.unwrap()` calls on `Option`s. /// @@ -336,7 +336,7 @@ declare_lint! { "using `.iter().nth()` on a slice or Vec" } -impl LintPass for MethodsPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(EXTEND_FROM_SLICE, OPTION_UNWRAP_USED, @@ -359,7 +359,7 @@ impl LintPass for MethodsPass { } } -impl LateLintPass for MethodsPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { if in_macro(cx, expr.span) { return; diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index d8ae9dc34716..f46cfc5f123b 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -17,15 +17,15 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct NeedlessUpdatePass; +pub struct Pass; -impl LintPass for NeedlessUpdatePass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_UPDATE) } } -impl LateLintPass for NeedlessUpdatePass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { let ty = cx.tcx.expr_ty(expr); diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index a9ac0a248561..5b34348219c8 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -78,15 +78,15 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { } #[derive(Copy, Clone)] -pub struct NoEffectPass; +pub struct Pass; -impl LintPass for NoEffectPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(NO_EFFECT, UNNECESSARY_OPERATION) } } -impl LateLintPass for NoEffectPass { +impl LateLintPass for Pass { fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { if let StmtSemi(ref expr, _) = stmt.node { if has_no_effect(cx, expr) { diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 1d760599e3fb..935edbb1f562 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -19,15 +19,15 @@ declare_lint! { #[derive(Copy,Clone)] -pub struct NonSensicalOpenOptions; +pub struct NonSensical; -impl LintPass for NonSensicalOpenOptions { +impl LintPass for NonSensical { fn get_lints(&self) -> LintArray { lint_array!(NONSENSICAL_OPEN_OPTIONS) } } -impl LateLintPass for NonSensicalOpenOptions { +impl LateLintPass for NonSensical { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprMethodCall(ref name, _, ref arguments) = e.node { let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index d744d2a6308a..d3306b4bc6fe 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -17,15 +17,15 @@ declare_lint! { } #[allow(missing_copy_implementations)] -pub struct PanicPass; +pub struct Pass; -impl LintPass for PanicPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(PANIC_PARAMS) } } -impl LateLintPass for PanicPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if_let_chain! {[ let ExprBlock(ref block) = expr.node, diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index d426286dba48..56fefb24f756 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -31,15 +31,15 @@ declare_lint! { } #[derive(Copy, Clone, Debug)] -pub struct PrintLint; +pub struct Pass; -impl LintPass for PrintLint { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(PRINT_STDOUT, USE_DEBUG) } } -impl LateLintPass for PrintLint { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprCall(ref fun, ref args) = expr.node { if let ExprPath(_, ref path) = fun.node { diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index c2c37fcf6866..26c8568473dd 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -56,18 +56,18 @@ declare_lint! { } #[derive(Clone, Default)] -pub struct RegexPass { +pub struct Pass { spans: HashSet, last: Option, } -impl LintPass for RegexPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX) } } -impl LateLintPass for RegexPass { +impl LateLintPass for Pass { fn check_crate(&mut self, _: &LateContext, _: &Crate) { self.spans.clear(); } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 0954d92cf9a5..c42f9cb32d87 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -45,15 +45,15 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct ShadowPass; +pub struct Pass; -impl LintPass for ShadowPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) } } -impl LateLintPass for ShadowPass { +impl LateLintPass for Pass { fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) { if in_external_macro(cx, block.span) { return; diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 1496a45dac24..5bc3853ac5e0 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -24,15 +24,15 @@ fn is_temporary(expr: &Expr) -> bool { } #[derive(Copy, Clone)] -pub struct TemporaryAssignmentPass; +pub struct Pass; -impl LintPass for TemporaryAssignmentPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(TEMPORARY_ASSIGNMENT) } } -impl LateLintPass for TemporaryAssignmentPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { if let ExprAssign(ref target, _) = expr.node { match target.node { diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 0c238400308f..323c65364961 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -5,7 +5,7 @@ use syntax::parse::token; use toml; /// Get the configuration file from arguments. -pub fn conf_file(args: &[ptr::P]) -> Result, (&'static str, codemap::Span)> { +pub fn file(args: &[ptr::P]) -> Result, (&'static str, codemap::Span)> { for arg in args { match arg.node { ast::MetaItemKind::Word(ref name) | @@ -31,18 +31,18 @@ pub fn conf_file(args: &[ptr::P]) -> Result), - TypeError(&'static str, &'static str, &'static str), +pub enum Error { + Io(io::Error), + Toml(Vec), + Type(&'static str, &'static str, &'static str), UnknownKey(String), } -impl fmt::Display for ConfError { +impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - ConfError::IoError(ref err) => err.fmt(f), - ConfError::TomlError(ref errs) => { + Error::Io(ref err) => err.fmt(f), + Error::Toml(ref errs) => { let mut first = true; for err in errs { if !first { @@ -55,17 +55,17 @@ impl fmt::Display for ConfError { Ok(()) } - ConfError::TypeError(ref key, ref expected, ref got) => { + Error::Type(ref key, ref expected, ref got) => { write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) } - ConfError::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), + Error::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), } } } -impl From for ConfError { +impl From for Error { fn from(e: io::Error) -> Self { - ConfError::IoError(e) + Error::Io(e) } } @@ -87,7 +87,7 @@ macro_rules! define_Conf { impl Conf { /// Set the property `name` (which must be the `toml` name) to the given value #[allow(cast_sign_loss)] - fn set(&mut self, name: String, value: toml::Value) -> Result<(), ConfError> { + fn set(&mut self, name: String, value: toml::Value) -> Result<(), Error> { match name.as_str() { $( define_Conf!(PAT $toml_name) => { @@ -95,9 +95,9 @@ macro_rules! define_Conf { self.$rust_name = value; } else { - return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), - stringify!($($ty)+), - value.type_str())); + return Err(Error::Type(define_Conf!(EXPR $toml_name), + stringify!($($ty)+), + value.type_str())); } }, )+ @@ -106,7 +106,7 @@ macro_rules! define_Conf { return Ok(()); } _ => { - return Err(ConfError::UnknownKey(name)); + return Err(Error::UnknownKey(name)); } } @@ -163,7 +163,7 @@ define_Conf! { /// Read the `toml` configuration file. The function will ignore “File not found” errors iif /// `!must_exist`, in which case, it will return the default configuration. /// In case of error, the function tries to continue as much as possible. -pub fn read_conf(path: &str, must_exist: bool) -> (Conf, Vec) { +pub fn read(path: &str, must_exist: bool) -> (Conf, Vec) { let mut conf = Conf::default(); let mut errors = Vec::new(); @@ -191,7 +191,7 @@ pub fn read_conf(path: &str, must_exist: bool) -> (Conf, Vec) { let toml = if let Some(toml) = parser.parse() { toml } else { - errors.push(ConfError::TomlError(parser.errors)); + errors.push(Error::Toml(parser.errors)); return (conf, errors); }; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index e62a8f9c4595..73f2fb7caa81 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -22,15 +22,15 @@ declare_lint! { } #[derive(Copy, Clone, Debug)] -pub struct UselessVec; +pub struct Pass; -impl LintPass for UselessVec { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(USELESS_VEC) } } -impl LateLintPass for UselessVec { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_let_chain!{[ @@ -51,12 +51,12 @@ impl LateLintPass for UselessVec { } fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { - if let Some(vec_args) = unexpand_vec(cx, vec) { + if let Some(vec_args) = unexpand(cx, vec) { let snippet = match vec_args { - VecArgs::Repeat(elem, len) => { + Args::Repeat(elem, len) => { format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() } - VecArgs::Vec(args) => { + Args::Vec(args) => { if let Some(last) = args.iter().last() { let span = Span { lo: args[0].span.lo, @@ -78,7 +78,7 @@ fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { } /// Represent the pre-expansion arguments of a `vec!` invocation. -pub enum VecArgs<'a> { +pub enum Args<'a> { /// `vec![elem; len]` Repeat(&'a P, &'a P), /// `vec![a, b, c]` @@ -86,7 +86,7 @@ pub enum VecArgs<'a> { } /// Returns the arguments of the `vec!` macro if this expression was expanded from `vec!`. -pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option> { +pub fn unexpand<'e>(cx: &LateContext, expr: &'e Expr) -> Option> { if_let_chain!{[ let ExprCall(ref fun, ref args) = expr.node, let ExprPath(_, ref path) = fun.node, @@ -94,7 +94,7 @@ pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option> ], { return if match_path(path, &paths::VEC_FROM_ELEM) && args.len() == 2 { // `vec![elem; size]` case - Some(VecArgs::Repeat(&args[0], &args[1])) + Some(Args::Repeat(&args[0], &args[1])) } else if match_path(path, &["into_vec"]) && args.len() == 1 { // `vec![a, b, c]` case @@ -102,7 +102,7 @@ pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option> let ExprBox(ref boxed) = args[0].node, let ExprVec(ref args) = boxed.node ], { - return Some(VecArgs::Vec(&*args)); + return Some(Args::Vec(&*args)); }} None diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 041ac94836cd..8c9f98712288 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -3,10 +3,10 @@ use rustc::lint::*; use rustc::hir::*; use utils::span_help_and_lint; -/// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists +/// `Pass` is a pass that checks for a binary expression that consists /// `of 0.0/0.0`, which is always `NaN`. It is more clear to replace instances of /// `0.0/0.0` with `std::f32::NaN` or `std::f64::NaN`, depending on the precision. -pub struct ZeroDivZeroPass; +pub struct Pass; /// **What it does:** This lint checks for `0.0 / 0.0`. /// @@ -21,13 +21,13 @@ declare_lint! { "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN" } -impl LintPass for ZeroDivZeroPass { +impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(ZERO_DIVIDED_BY_ZERO) } } -impl LateLintPass for ZeroDivZeroPass { +impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { // check for instances of 0.0/0.0 if_let_chain! {[ diff --git a/tests/compile-fail/enum_variants.rs b/tests/compile-fail/enum_variants.rs index 6589bd35fd3d..ed7f7823f8fa 100644 --- a/tests/compile-fail/enum_variants.rs +++ b/tests/compile-fail/enum_variants.rs @@ -11,7 +11,8 @@ enum FakeCallType2 { } enum Foo { - cFoo, cBar, + cFoo, //~ ERROR: Variant name ends with the enum's name + cBar, } enum BadCallType { //~ ERROR: All variants have the same prefix: `CallType` @@ -68,4 +69,12 @@ enum NonCaps { //~ ERROR: All variants have the same prefix: `Prefix` PrefixCake, } +enum Stuff { + BadStuff, //~ ERROR: Variant name ends with the enum's name +} + +enum Food { + FoodGood, //~ ERROR: Variant name starts with the enum's name +} + fn main() {}