Merge pull request #994 from oli-obk/stuttter

Stuttter lint
This commit is contained in:
llogiq
2016-06-16 19:00:43 +02:00
committed by GitHub
25 changed files with 245 additions and 166 deletions

View File

@@ -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_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_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 [`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_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 [`suspicious_else_formatting`]: https://github.com/Manishearth/rust-clippy/wiki#suspicious_else_formatting
[`temporary_assignment`]: https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment [`temporary_assignment`]: https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment

View File

@@ -17,7 +17,7 @@ Table of contents:
## Lints ## Lints
There are 153 lints included in this crate: There are 154 lints included in this crate:
name | default | meaning 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](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_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 [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_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` [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 [temporary_assignment](https://github.com/Manishearth/rust-clippy/wiki#temporary_assignment) | warn | assignments to temporaries

View File

@@ -37,15 +37,15 @@ const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[(f64::E, "E", 4),
(f64::SQRT_2, "SQRT_2", 5)]; (f64::SQRT_2, "SQRT_2", 5)];
#[derive(Copy,Clone)] #[derive(Copy,Clone)]
pub struct ApproxConstant; pub struct Pass;
impl LintPass for ApproxConstant { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(APPROX_CONSTANT) lint_array!(APPROX_CONSTANT)
} }
} }
impl LateLintPass for ApproxConstant { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) { fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprLit(ref lit) = e.node { if let ExprLit(ref lit) = e.node {
check_lit(cx, lit, e); check_lit(cx, lit, e);

View File

@@ -80,7 +80,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a
} }
#[allow(while_let_loop)] // #362 #[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. // 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 // There really is no markdown specification that would disambiguate this properly. This is
// what GitHub and Rustdoc do: // what GitHub and Rustdoc do:

View File

@@ -23,15 +23,15 @@ declare_lint! {
} }
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
pub struct DropRefPass; pub struct Pass;
impl LintPass for DropRefPass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(DROP_REF) lint_array!(DROP_REF)
} }
} }
impl LateLintPass for DropRefPass { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprCall(ref path, ref args) = expr.node { if let ExprCall(ref path, ref args) = expr.node {
if let ExprPath(None, _) = path.node { if let ExprPath(None, _) = path.node {

View File

@@ -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`" "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 { fn get_lints(&self) -> LintArray {
lint_array!(ENUM_CLIKE_UNPORTABLE_VARIANT) lint_array!(ENUM_CLIKE_UNPORTABLE_VARIANT)
} }
} }
impl LateLintPass for EnumClikeUnportableVariant { impl LateLintPass for UnportableVariant {
#[allow(cast_possible_truncation, cast_sign_loss)] #[allow(cast_possible_truncation, cast_sign_loss)]
fn check_item(&mut self, cx: &LateContext, item: &Item) { fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let ItemEnum(ref def, _) = item.node { if let ItemEnum(ref def, _) = item.node {

View File

@@ -2,9 +2,10 @@
use rustc::lint::*; use rustc::lint::*;
use syntax::ast::*; use syntax::ast::*;
use syntax::codemap::Span;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use utils::span_help_and_lint; use utils::{span_help_and_lint, span_lint};
use utils::{camel_case_from, camel_case_until}; 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 /// **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" "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<String>,
}
impl LintPass for EnumVariantNames { impl LintPass for EnumVariantNames {
fn get_lints(&self) -> LintArray { 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() var.node.name.name.as_str()
} }
// FIXME: waiting for https://github.com/rust-lang/rust/pull/31700 /// Returns the number of chars that match from the start
// 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()
// }
fn partial_match(pre: &str, name: &str) -> usize { fn partial_match(pre: &str, name: &str) -> usize {
let mut name_iter = name.chars(); let mut name_iter = name.chars();
let _ = name_iter.next_back(); // make sure the name is never fully matched 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() 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 { fn partial_rmatch(post: &str, name: &str) -> usize {
let mut name_iter = name.chars(); let mut name_iter = name.chars();
let _ = name_iter.next(); // make sure the name is never fully matched 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() post.chars().rev().zip(name_iter.rev()).take_while(|&(l, r)| l == r).count()
} }
impl EarlyLintPass for EnumVariantNames { // FIXME: #600
// FIXME: #600 #[allow(while_let_on_iterator)]
#[allow(while_let_on_iterator)] fn check_variant(cx: &EarlyContext, def: &EnumDef, item_name: &str, item_name_chars: usize, span: Span) {
fn check_item(&mut self, cx: &EarlyContext, item: &Item) { for var in &def.variants {
if let ItemKind::Enum(ref def, _) = item.node { let name = var2str(var);
if def.variants.len() < 2 { if partial_match(item_name, &name) == item_name_chars {
return; span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name starts with the enum's name");
} }
let first = var2str(&def.variants[0]); if partial_rmatch(item_name, &name) == item_name_chars {
let mut pre = &first[..camel_case_until(&*first)]; span_lint(cx, ENUM_VARIANT_NAMES, var.span, "Variant name ends with the enum's name");
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,
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 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 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));
}
}
}
}
if let ItemKind::Enum(ref def, _) = item.node {
check_variant(cx, def, &item_name, item_name_chars, item.span);
}
self.modules.push(item_camel);
}
} }

View File

@@ -11,7 +11,7 @@ use syntax::ast::NodeId;
use syntax::codemap::Span; use syntax::codemap::Span;
use utils::span_lint; use utils::span_lint;
pub struct EscapePass; pub struct Pass;
/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. /// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine.
/// ///
@@ -44,13 +44,13 @@ struct EscapeDelegate<'a, 'tcx: 'a> {
set: NodeSet, set: NodeSet,
} }
impl LintPass for EscapePass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(BOXED_LOCAL) 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) { 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); let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id);

View File

@@ -23,15 +23,15 @@ declare_lint! {
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct FormatMacLint; pub struct Pass;
impl LintPass for FormatMacLint { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array![USELESS_FORMAT] lint_array![USELESS_FORMAT]
} }
} }
impl LateLintPass for FormatMacLint { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let Some(span) = is_expn_of(cx, expr.span, "format") { if let Some(span) = is_expn_of(cx, expr.span, "format") {
match expr.node { match expr.node {

View File

@@ -132,7 +132,7 @@ mod reexport {
#[cfg_attr(rustfmt, rustfmt_skip)] #[cfg_attr(rustfmt, rustfmt_skip)]
pub fn register_plugins(reg: &mut rustc_plugin::Registry) { 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) => { Ok(file_name) => {
// if the user specified a file, it must exist, otherwise default to `clippy.toml` but // if the user specified a file, it must exist, otherwise default to `clippy.toml` but
// do not require the file to exist // do not require the file to exist
@@ -142,7 +142,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
("clippy.toml", false) ("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 // all conf errors are non-fatal, we just use the default conf in case of error
for error in errors { 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::TopLevelRefPass);
reg.register_late_lint_pass(box misc::CmpNan); reg.register_late_lint_pass(box misc::CmpNan);
reg.register_late_lint_pass(box eq_op::EqOp); 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_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 bit_mask::BitMask);
reg.register_late_lint_pass(box ptr_arg::PtrArg); 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::NeedlessBool);
reg.register_late_lint_pass(box needless_bool::BoolComparison); 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_late_lint_pass(box misc::FloatCmp);
reg.register_early_lint_pass(box precedence::Precedence); reg.register_early_lint_pass(box precedence::Precedence);
reg.register_late_lint_pass(box eta_reduction::EtaPass); 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 unicode::Unicode);
reg.register_late_lint_pass(box strings::StringAdd); reg.register_late_lint_pass(box strings::StringAdd);
reg.register_early_lint_pass(box returns::ReturnPass); reg.register_early_lint_pass(box returns::ReturnPass);
reg.register_late_lint_pass(box methods::MethodsPass); reg.register_late_lint_pass(box methods::Pass);
reg.register_late_lint_pass(box shadow::ShadowPass); reg.register_late_lint_pass(box shadow::Pass);
reg.register_late_lint_pass(box types::LetPass); reg.register_late_lint_pass(box types::LetPass);
reg.register_late_lint_pass(box types::UnitCmp); 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 lifetimes::LifetimePass);
reg.register_late_lint_pass(box entry::HashMapLint); reg.register_late_lint_pass(box entry::HashMapLint);
reg.register_late_lint_pass(box ranges::StepByZero); 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 matches::MatchPass);
reg.register_late_lint_pass(box misc::PatternPass); reg.register_late_lint_pass(box misc::PatternPass);
reg.register_late_lint_pass(box minmax::MinMaxPass); reg.register_late_lint_pass(box minmax::MinMaxPass);
reg.register_late_lint_pass(box open_options::NonSensicalOpenOptions); reg.register_late_lint_pass(box open_options::NonSensical);
reg.register_late_lint_pass(box zero_div_zero::ZeroDivZeroPass); 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 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 needless_borrow::NeedlessBorrow);
reg.register_late_lint_pass(box no_effect::NoEffectPass); reg.register_late_lint_pass(box no_effect::Pass);
reg.register_late_lint_pass(box map_clone::MapClonePass); reg.register_late_lint_pass(box map_clone::Pass);
reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignmentPass); reg.register_late_lint_pass(box temporary_assignment::Pass);
reg.register_late_lint_pass(box transmute::Transmute); 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 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_early_lint_pass(box misc_early::MiscEarly);
reg.register_late_lint_pass(box misc::UsedUnderscoreBinding); reg.register_late_lint_pass(box misc::UsedUnderscoreBinding);
reg.register_late_lint_pass(box array_indexing::ArrayIndexing); 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 strings::StringLitAsBytes);
reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box derive::Derive);
reg.register_late_lint_pass(box types::CharLitAsU8); reg.register_late_lint_pass(box types::CharLitAsU8);
reg.register_late_lint_pass(box print::PrintLint); reg.register_late_lint_pass(box print::Pass);
reg.register_late_lint_pass(box vec::UselessVec); reg.register_late_lint_pass(box vec::Pass);
reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames {
max_single_char_names: conf.max_single_char_names, 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::AbsurdExtremeComparisons);
reg.register_late_lint_pass(box types::InvalidUpcastComparisons); 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 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_early_lint_pass(box formatting::Formatting);
reg.register_late_lint_pass(box swap::Swap); reg.register_late_lint_pass(box swap::Swap);
reg.register_early_lint_pass(box if_not_else::IfNotElse); 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, array_indexing::INDEXING_SLICING,
booleans::NONMINIMAL_BOOL, booleans::NONMINIMAL_BOOL,
enum_glob_use::ENUM_GLOB_USE, enum_glob_use::ENUM_GLOB_USE,
enum_variants::STUTTER,
if_not_else::IF_NOT_ELSE, if_not_else::IF_NOT_ELSE,
items_after_statements::ITEMS_AFTER_STATEMENTS, items_after_statements::ITEMS_AFTER_STATEMENTS,
matches::SINGLE_MATCH_ELSE, matches::SINGLE_MATCH_ELSE,

View File

@@ -205,9 +205,9 @@ declare_lint! {
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct LoopsPass; pub struct Pass;
impl LintPass for LoopsPass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(NEEDLESS_RANGE_LOOP, lint_array!(NEEDLESS_RANGE_LOOP,
EXPLICIT_ITER_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) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let Some((pat, arg, body)) = recover_for_loop(expr) { if let Some((pat, arg, body)) = recover_for_loop(expr) {
check_for_loop(cx, pat, arg, body, expr); check_for_loop(cx, pat, arg, body, expr);

View File

@@ -18,9 +18,9 @@ declare_lint! {
} }
#[derive(Copy, Clone)] #[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) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
// call to .map() // call to .map()
if let ExprMethodCall(name, _, ref args) = expr.node { 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 { fn get_lints(&self) -> LintArray {
lint_array!(MAP_CLONE) lint_array!(MAP_CLONE)
} }

View File

@@ -17,7 +17,7 @@ use utils::MethodArgs;
use utils::paths; use utils::paths;
#[derive(Clone)] #[derive(Clone)]
pub struct MethodsPass; pub struct Pass;
/// **What it does:** This lint checks for `.unwrap()` calls on `Option`s. /// **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" "using `.iter().nth()` on a slice or Vec"
} }
impl LintPass for MethodsPass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(EXTEND_FROM_SLICE, lint_array!(EXTEND_FROM_SLICE,
OPTION_UNWRAP_USED, 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) { fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
if in_macro(cx, expr.span) { if in_macro(cx, expr.span) {
return; return;

View File

@@ -17,15 +17,15 @@ declare_lint! {
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct NeedlessUpdatePass; pub struct Pass;
impl LintPass for NeedlessUpdatePass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(NEEDLESS_UPDATE) lint_array!(NEEDLESS_UPDATE)
} }
} }
impl LateLintPass for NeedlessUpdatePass { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
let ty = cx.tcx.expr_ty(expr); let ty = cx.tcx.expr_ty(expr);

View File

@@ -78,15 +78,15 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool {
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct NoEffectPass; pub struct Pass;
impl LintPass for NoEffectPass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(NO_EFFECT, UNNECESSARY_OPERATION) lint_array!(NO_EFFECT, UNNECESSARY_OPERATION)
} }
} }
impl LateLintPass for NoEffectPass { impl LateLintPass for Pass {
fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) { fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) {
if let StmtSemi(ref expr, _) = stmt.node { if let StmtSemi(ref expr, _) = stmt.node {
if has_no_effect(cx, expr) { if has_no_effect(cx, expr) {

View File

@@ -19,15 +19,15 @@ declare_lint! {
#[derive(Copy,Clone)] #[derive(Copy,Clone)]
pub struct NonSensicalOpenOptions; pub struct NonSensical;
impl LintPass for NonSensicalOpenOptions { impl LintPass for NonSensical {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(NONSENSICAL_OPEN_OPTIONS) lint_array!(NONSENSICAL_OPEN_OPTIONS)
} }
} }
impl LateLintPass for NonSensicalOpenOptions { impl LateLintPass for NonSensical {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) { fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprMethodCall(ref name, _, ref arguments) = e.node { if let ExprMethodCall(ref name, _, ref arguments) = e.node {
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0])); let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0]));

View File

@@ -17,15 +17,15 @@ declare_lint! {
} }
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
pub struct PanicPass; pub struct Pass;
impl LintPass for PanicPass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(PANIC_PARAMS) lint_array!(PANIC_PARAMS)
} }
} }
impl LateLintPass for PanicPass { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if_let_chain! {[ if_let_chain! {[
let ExprBlock(ref block) = expr.node, let ExprBlock(ref block) = expr.node,

View File

@@ -31,15 +31,15 @@ declare_lint! {
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct PrintLint; pub struct Pass;
impl LintPass for PrintLint { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(PRINT_STDOUT, USE_DEBUG) lint_array!(PRINT_STDOUT, USE_DEBUG)
} }
} }
impl LateLintPass for PrintLint { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprCall(ref fun, ref args) = expr.node { if let ExprCall(ref fun, ref args) = expr.node {
if let ExprPath(_, ref path) = fun.node { if let ExprPath(_, ref path) = fun.node {

View File

@@ -56,18 +56,18 @@ declare_lint! {
} }
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct RegexPass { pub struct Pass {
spans: HashSet<Span>, spans: HashSet<Span>,
last: Option<NodeId>, last: Option<NodeId>,
} }
impl LintPass for RegexPass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX) lint_array!(INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX)
} }
} }
impl LateLintPass for RegexPass { impl LateLintPass for Pass {
fn check_crate(&mut self, _: &LateContext, _: &Crate) { fn check_crate(&mut self, _: &LateContext, _: &Crate) {
self.spans.clear(); self.spans.clear();
} }

View File

@@ -45,15 +45,15 @@ declare_lint! {
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct ShadowPass; pub struct Pass;
impl LintPass for ShadowPass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) 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) { fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) {
if in_external_macro(cx, block.span) { if in_external_macro(cx, block.span) {
return; return;

View File

@@ -24,15 +24,15 @@ fn is_temporary(expr: &Expr) -> bool {
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct TemporaryAssignmentPass; pub struct Pass;
impl LintPass for TemporaryAssignmentPass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(TEMPORARY_ASSIGNMENT) lint_array!(TEMPORARY_ASSIGNMENT)
} }
} }
impl LateLintPass for TemporaryAssignmentPass { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprAssign(ref target, _) = expr.node { if let ExprAssign(ref target, _) = expr.node {
match target.node { match target.node {

View File

@@ -5,7 +5,7 @@ use syntax::parse::token;
use toml; use toml;
/// Get the configuration file from arguments. /// Get the configuration file from arguments.
pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { pub fn file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> {
for arg in args { for arg in args {
match arg.node { match arg.node {
ast::MetaItemKind::Word(ref name) | ast::MetaItemKind::Word(ref name) |
@@ -31,18 +31,18 @@ pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::Interne
/// Error from reading a configuration file. /// Error from reading a configuration file.
#[derive(Debug)] #[derive(Debug)]
pub enum ConfError { pub enum Error {
IoError(io::Error), Io(io::Error),
TomlError(Vec<toml::ParserError>), Toml(Vec<toml::ParserError>),
TypeError(&'static str, &'static str, &'static str), Type(&'static str, &'static str, &'static str),
UnknownKey(String), UnknownKey(String),
} }
impl fmt::Display for ConfError { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self { match *self {
ConfError::IoError(ref err) => err.fmt(f), Error::Io(ref err) => err.fmt(f),
ConfError::TomlError(ref errs) => { Error::Toml(ref errs) => {
let mut first = true; let mut first = true;
for err in errs { for err in errs {
if !first { if !first {
@@ -55,17 +55,17 @@ impl fmt::Display for ConfError {
Ok(()) 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) 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<io::Error> for ConfError { impl From<io::Error> for Error {
fn from(e: io::Error) -> Self { fn from(e: io::Error) -> Self {
ConfError::IoError(e) Error::Io(e)
} }
} }
@@ -87,7 +87,7 @@ macro_rules! define_Conf {
impl Conf { impl Conf {
/// Set the property `name` (which must be the `toml` name) to the given value /// Set the property `name` (which must be the `toml` name) to the given value
#[allow(cast_sign_loss)] #[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() { match name.as_str() {
$( $(
define_Conf!(PAT $toml_name) => { define_Conf!(PAT $toml_name) => {
@@ -95,9 +95,9 @@ macro_rules! define_Conf {
self.$rust_name = value; self.$rust_name = value;
} }
else { else {
return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), return Err(Error::Type(define_Conf!(EXPR $toml_name),
stringify!($($ty)+), stringify!($($ty)+),
value.type_str())); value.type_str()));
} }
}, },
)+ )+
@@ -106,7 +106,7 @@ macro_rules! define_Conf {
return Ok(()); 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 /// 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. /// `!must_exist`, in which case, it will return the default configuration.
/// In case of error, the function tries to continue as much as possible. /// In case of error, the function tries to continue as much as possible.
pub fn read_conf(path: &str, must_exist: bool) -> (Conf, Vec<ConfError>) { pub fn read(path: &str, must_exist: bool) -> (Conf, Vec<Error>) {
let mut conf = Conf::default(); let mut conf = Conf::default();
let mut errors = Vec::new(); let mut errors = Vec::new();
@@ -191,7 +191,7 @@ pub fn read_conf(path: &str, must_exist: bool) -> (Conf, Vec<ConfError>) {
let toml = if let Some(toml) = parser.parse() { let toml = if let Some(toml) = parser.parse() {
toml toml
} else { } else {
errors.push(ConfError::TomlError(parser.errors)); errors.push(Error::Toml(parser.errors));
return (conf, errors); return (conf, errors);
}; };

View File

@@ -22,15 +22,15 @@ declare_lint! {
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct UselessVec; pub struct Pass;
impl LintPass for UselessVec { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(USELESS_VEC) lint_array!(USELESS_VEC)
} }
} }
impl LateLintPass for UselessVec { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
// search for `&vec![_]` expressions where the adjusted type is `&[_]` // search for `&vec![_]` expressions where the adjusted type is `&[_]`
if_let_chain!{[ if_let_chain!{[
@@ -51,12 +51,12 @@ impl LateLintPass for UselessVec {
} }
fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) { 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 { 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() 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() { if let Some(last) = args.iter().last() {
let span = Span { let span = Span {
lo: args[0].span.lo, 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. /// Represent the pre-expansion arguments of a `vec!` invocation.
pub enum VecArgs<'a> { pub enum Args<'a> {
/// `vec![elem; len]` /// `vec![elem; len]`
Repeat(&'a P<Expr>, &'a P<Expr>), Repeat(&'a P<Expr>, &'a P<Expr>),
/// `vec![a, b, c]` /// `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!`. /// 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<VecArgs<'e>> { pub fn unexpand<'e>(cx: &LateContext, expr: &'e Expr) -> Option<Args<'e>> {
if_let_chain!{[ if_let_chain!{[
let ExprCall(ref fun, ref args) = expr.node, let ExprCall(ref fun, ref args) = expr.node,
let ExprPath(_, ref path) = fun.node, let ExprPath(_, ref path) = fun.node,
@@ -94,7 +94,7 @@ pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>>
], { ], {
return if match_path(path, &paths::VEC_FROM_ELEM) && args.len() == 2 { return if match_path(path, &paths::VEC_FROM_ELEM) && args.len() == 2 {
// `vec![elem; size]` case // `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 { else if match_path(path, &["into_vec"]) && args.len() == 1 {
// `vec![a, b, c]` case // `vec![a, b, c]` case
@@ -102,7 +102,7 @@ pub fn unexpand_vec<'e>(cx: &LateContext, expr: &'e Expr) -> Option<VecArgs<'e>>
let ExprBox(ref boxed) = args[0].node, let ExprBox(ref boxed) = args[0].node,
let ExprVec(ref args) = boxed.node let ExprVec(ref args) = boxed.node
], { ], {
return Some(VecArgs::Vec(&*args)); return Some(Args::Vec(&*args));
}} }}
None None

View File

@@ -3,10 +3,10 @@ use rustc::lint::*;
use rustc::hir::*; use rustc::hir::*;
use utils::span_help_and_lint; 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 /// `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. /// `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`. /// **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" "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 { fn get_lints(&self) -> LintArray {
lint_array!(ZERO_DIVIDED_BY_ZERO) lint_array!(ZERO_DIVIDED_BY_ZERO)
} }
} }
impl LateLintPass for ZeroDivZeroPass { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
// check for instances of 0.0/0.0 // check for instances of 0.0/0.0
if_let_chain! {[ if_let_chain! {[

View File

@@ -11,7 +11,8 @@ enum FakeCallType2 {
} }
enum Foo { 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` 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, 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() {} fn main() {}