Skip to content

Instantly share code, notes, and snippets.

@payload
Last active August 29, 2015 14:10
Show Gist options
  • Save payload/5496fd7f3bef17139cc2 to your computer and use it in GitHub Desktop.
Save payload/5496fd7f3bef17139cc2 to your computer and use it in GitHub Desktop.
rust compiler plugin to check for `if let` opportunities
#![feature(if_let)]
#[phase(plugin,link)]
extern crate syntax;
#[phase(plugin, link)]
extern crate rustc;
use syntax::ast::{Expr, ExprMatch, PatWild, PatWildSingle, ExprTup};
use rustc::lint::{Context, LintPass, LintArray};
use syntax::codemap::NO_EXPANSION;
declare_lint!(IF_LET_LINT, Warn,
"Warn about possible `if let` opportunity")
pub struct IfLetPass;
impl LintPass for IfLetPass {
fn get_lints(&self) -> LintArray {
lint_array!(IF_LET_LINT)
}
fn check_expr(&mut self, cx: &Context, expr_match: &Expr) {
if expr_match.span.expn_id != NO_EXPANSION { return }
if let ExprMatch(_, ref arms, MatchNormal) = expr_match.node {
if arms.len() != 2 { return }
let ref if_arm = arms[0];
let ref else_arm = arms[1];
if if_arm.pats.len() != 1
|| if_arm.guard != None {
return
}
if else_arm.pats.len() == 0 {
cx.span_lint(IF_LET, expr_match.span, "if let")
}
if else_arm.pats.len() != 1
|| else_arm.guard != None
|| else_arm.pats[0].node != PatWild(PatWildSingle) {
return
}
if is_empty_tuple_expr(&*else_arm.body) {
cx.span_lint(IF_LET, expr_match.span, "if let")
} else {
cx.span_lint(IF_LET, expr_match.span, "if let else")
}
}
}
}
fn is_empty_tuple_expr(expr: &Expr) -> bool {
match expr.node {
ExprTup(ref vec) if vec.len() == 0 => true,
_ => false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment