add lint to check for enums where all variants have the same pre-/postfix
This commit is contained in:
parent
fd906c043f
commit
328d2c7626
3 changed files with 95 additions and 1 deletions
|
@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code.
|
|||
[Jump to usage instructions](#usage)
|
||||
|
||||
##Lints
|
||||
There are 105 lints included in this crate:
|
||||
There are 106 lints included in this crate:
|
||||
|
||||
name | default | meaning
|
||||
---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -30,6 +30,7 @@ name
|
|||
[derive_hash_not_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_not_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly
|
||||
[duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | Function arguments having names which only differ by an underscore
|
||||
[empty_loop](https://github.com/Manishearth/rust-clippy/wiki#empty_loop) | warn | empty `loop {}` detected
|
||||
[enum_variant_names](https://github.com/Manishearth/rust-clippy/wiki#enum_variant_names) | warn | finds enums where all variants share a prefix/postfix
|
||||
[eq_op](https://github.com/Manishearth/rust-clippy/wiki#eq_op) | warn | equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`)
|
||||
[expl_impl_clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types
|
||||
[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do
|
||||
|
|
90
src/enum_variants.rs
Normal file
90
src/enum_variants.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
//! lint on enum variants that are prefixed or suffixed by the same characters
|
||||
|
||||
use rustc::lint::*;
|
||||
use syntax::attr::*;
|
||||
use syntax::ast::*;
|
||||
use syntax::parse::token::InternedString;
|
||||
|
||||
use utils::span_help_and_lint;
|
||||
|
||||
/// **What it does:** Warns on enum variants that are prefixed or suffixed by the same characters
|
||||
///
|
||||
/// **Why is this bad?** Enum variant names should specify their variant, not the enum, too.
|
||||
///
|
||||
/// **Known problems:** None
|
||||
///
|
||||
/// **Example:** enum Cake { BlackForestCake, HummingbirdCake }
|
||||
declare_lint! { pub ENUM_VARIANT_NAMES, Warn,
|
||||
"finds enums where all variants share a prefix/postfix" }
|
||||
|
||||
pub struct EnumVariantNames;
|
||||
|
||||
impl LintPass for EnumVariantNames {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(ENUM_VARIANT_NAMES)
|
||||
}
|
||||
}
|
||||
|
||||
fn var2str(var: &Variant) -> InternedString {
|
||||
var.node.name.name.as_str()
|
||||
}
|
||||
|
||||
fn partial_match(left: &str, right: &str) -> usize {
|
||||
left.chars().zip(right.chars()).take_while(|&(l, r)| l == r).count()
|
||||
}
|
||||
|
||||
fn partial_rmatch(left: &str, right: &str) -> usize {
|
||||
left.chars().rev().zip(right.chars().rev()).take_while(|&(l, r)| l == r).count()
|
||||
}
|
||||
|
||||
impl EarlyLintPass for EnumVariantNames {
|
||||
fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
|
||||
if let ItemEnum(ref def, _) = item.node {
|
||||
if def.variants.len() < 2 {
|
||||
return;
|
||||
}
|
||||
let first = var2str(&*def.variants[0]);
|
||||
let mut pre = first.to_string();
|
||||
let mut post = pre.clone();
|
||||
for var in &def.variants[1..] {
|
||||
let name = var2str(var);
|
||||
let pre_match = partial_match(&pre, &name);
|
||||
let post_match = partial_rmatch(&post, &name);
|
||||
pre.truncate(pre_match);
|
||||
let post_end = post.len() - post_match;
|
||||
post.drain(..post_end);
|
||||
}
|
||||
if let Some(c) = first[pre.len()..].chars().next() {
|
||||
if !c.is_uppercase() {
|
||||
// non camel case prefix
|
||||
pre.clear()
|
||||
}
|
||||
}
|
||||
if let Some(c) = first[..(first.len() - post.len())].chars().rev().next() {
|
||||
if let Some(c1) = post.chars().next() {
|
||||
if !c.is_lowercase() || !c1.is_uppercase() {
|
||||
// non camel case postfix
|
||||
post.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
if pre == "_" {
|
||||
// don't lint on underscores which are meant to allow dead code
|
||||
pre.clear();
|
||||
}
|
||||
let (what, value) = if !pre.is_empty() {
|
||||
("pre", pre)
|
||||
} else if !post.is_empty() {
|
||||
("post", post)
|
||||
} else {
|
||||
return
|
||||
};
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ pub mod ptr_arg;
|
|||
pub mod needless_bool;
|
||||
pub mod approx_const;
|
||||
pub mod eta_reduction;
|
||||
pub mod enum_variants;
|
||||
pub mod identity_op;
|
||||
pub mod items_after_statements;
|
||||
pub mod minmax;
|
||||
|
@ -93,6 +94,7 @@ pub fn plugin_registrar(reg: &mut 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_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);
|
||||
|
@ -183,6 +185,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||
derive::DERIVE_HASH_NOT_EQ,
|
||||
derive::EXPL_IMPL_CLONE_ON_COPY,
|
||||
entry::MAP_ENTRY,
|
||||
enum_variants::ENUM_VARIANT_NAMES,
|
||||
eq_op::EQ_OP,
|
||||
escape::BOXED_LOCAL,
|
||||
eta_reduction::REDUNDANT_CLOSURE,
|
||||
|
|
Loading…
Reference in a new issue