From 542bfe357015e24504377c7347a8811797126ee3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 20 Nov 2014 00:18:31 +0530 Subject: [PATCH] +match_if_let --- src/lib.rs | 7 ++++--- src/misc.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/misc.rs diff --git a/src/lib.rs b/src/lib.rs index 934232dceec..4528585c82c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ -#![feature(globs, phase, plugin_registrar)] +#![feature(globs, phase, plugin_registrar, if_let)] +#![allow(unused_imports)] #[phase(plugin,link)] extern crate syntax; @@ -12,10 +13,10 @@ use rustc::plugin::Registry; use rustc::lint::LintPassObject; pub mod types; +pub mod misc; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - //reg.register_syntax_extension(intern("jstraceable"), base::ItemDecorator(box expand_jstraceable)); - //reg.register_macro("factorial", expand) reg.register_lint_pass(box types::TypePass as LintPassObject); + reg.register_lint_pass(box misc::MiscPass as LintPassObject); } \ No newline at end of file diff --git a/src/misc.rs b/src/misc.rs new file mode 100644 index 00000000000..c70d4b48c1c --- /dev/null +++ b/src/misc.rs @@ -0,0 +1,46 @@ +use syntax::ptr::P; +use syntax::ast; +use syntax::ast::*; +use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; +use syntax::codemap::Span; + +use types::span_note_and_lint; + +/// Handles uncategorized lints +/// Currently handles linting of if-let-able matches +pub struct MiscPass; + + +declare_lint!(CLIPPY_SINGLE_MATCH, Warn, + "Warn on usage of matches with a single nontrivial arm") + +impl LintPass for MiscPass { + fn get_lints(&self) -> LintArray { + lint_array!(CLIPPY_SINGLE_MATCH) + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let ExprMatch(ref ex, ref arms, MatchNormal) = expr.node { + if arms.len() == 2 { + if arms[0].guard.is_none() && arms[1].pats.len() == 1 { + match arms[1].body.node { + ExprTup(ref v) if v.len() == 0 && arms[1].guard.is_none() => (), + ExprBlock(ref b) if b.stmts.len() == 0 && arms[1].guard.is_none() => (), + _ => return + } + // In some cases, an exhaustive match is preferred to catch situations when + // an enum is extended. So we only consider cases where a `_` wildcard is used + if arms[1].pats[0].node == PatWild(PatWildSingle) && arms[0].pats.len() == 1 { + let map = cx.sess().codemap(); + span_note_and_lint(cx, CLIPPY_SINGLE_MATCH, expr.span, + "You seem to be trying to use match for destructuring a single type. Did you mean to use `if let`?", + format!("Try if let {} = {} {{ ... }}", + map.span_to_snippet(arms[0].pats[0].span).unwrap_or("..".to_string()), + map.span_to_snippet(ex.span).unwrap_or("..".to_string())).as_slice() + ); + } + } + } + } + } +}