added parent method, also changed match-if-let note to help

This commit is contained in:
llogiq 2015-08-11 15:07:21 +02:00
parent 228f06a960
commit f0eb36c2af
3 changed files with 139 additions and 117 deletions

View file

@ -7,8 +7,7 @@ use rustc::lint::{Context, LintPass, LintArray, Lint, Level};
use rustc::middle::ty; use rustc::middle::ty;
use syntax::codemap::{Span, Spanned}; use syntax::codemap::{Span, Spanned};
use types::span_note_and_lint; use utils::{match_path, snippet, span_lint, span_help_and_lint};
use utils::{match_path, snippet, span_lint};
pub fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> { pub fn walk_ty<'t>(ty: ty::Ty<'t>) -> ty::Ty<'t> {
match ty.sty { match ty.sty {
@ -42,9 +41,12 @@ impl LintPass for MiscPass {
} }
// In some cases, an exhaustive match is preferred to catch situations when // 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 // 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 { if arms[1].pats[0].node == PatWild(PatWildSingle) &&
span_note_and_lint(cx, SINGLE_MATCH, expr.span, arms[0].pats.len() == 1 {
"You seem to be trying to use match for destructuring a single type. Did you mean to use `if let`?", span_help_and_lint(cx, 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 {} = {} {{ ... }}", &*format!("Try if let {} = {} {{ ... }}",
snippet(cx, arms[0].pats[0].span, ".."), snippet(cx, arms[0].pats[0].span, ".."),
snippet(cx, ex.span, "..")) snippet(cx, ex.span, ".."))
@ -136,7 +138,8 @@ impl LintPass for CmpNan {
fn check_nan(cx: &Context, path: &Path, span: Span) { fn check_nan(cx: &Context, path: &Path, span: Span) {
path.segments.last().map(|seg| if seg.identifier.name == "NAN" { path.segments.last().map(|seg| if seg.identifier.name == "NAN" {
span_lint(cx, CMP_NAN, span, "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead"); span_lint(cx, CMP_NAN, span,
"Doomed comparison with NAN, use std::{f32,f64}::is_nan instead");
}); });
} }

View file

@ -1,7 +1,8 @@
use rustc::lint::{Context, Lint}; use rustc::lint::{Context, Lint, Level};
use syntax::ast::{DefId, Name, Path}; use syntax::ast::{DefId, Expr, Name, NodeId, Path};
use syntax::codemap::{ExpnInfo, Span}; use syntax::codemap::{ExpnInfo, Span};
use syntax::ptr::P; use syntax::ptr::P;
use rustc::ast_map::Node::NodeExpr;
use rustc::middle::ty; use rustc::middle::ty;
use std::borrow::{Cow, IntoCow}; use std::borrow::{Cow, IntoCow};
use std::convert::From; use std::convert::From;
@ -50,6 +51,16 @@ pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> {
cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default)) cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default))
} }
/// get a parent expr if any this is useful to constrain a lint
pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> {
let map = &cx.tcx.map;
let node_id : NodeId = e.id;
let parent_id : NodeId = map.get_parent_node(node_id);
if node_id == parent_id { return None; }
map.find(parent_id).and_then(|node|
if let NodeExpr(parent) = node { Some(parent) } else { None } )
}
/// dereference a P<T> and return a ref on the result /// dereference a P<T> and return a ref on the result
pub fn de_p<T>(p: &P<T>) -> &T { &*p } pub fn de_p<T>(p: &P<T>) -> &T { &*p }
@ -65,3 +76,11 @@ pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) {
// http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string
cx.span_lint(lint, sp, msg); cx.span_lint(lint, sp, msg);
} }
pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span,
msg: &str, help: &str) {
span_lint(cx, lint, span, msg);
if cx.current_level(lint) != Level::Allow {
cx.sess().span_help(span, help);
}
}

View file

@ -6,7 +6,7 @@
fn main(){ fn main(){
let x = Some(1u8); let x = Some(1u8);
match x { //~ ERROR You seem to be trying to use match match x { //~ ERROR You seem to be trying to use match
//~^ NOTE Try if let Some(y) = x { ... } //~^ HELP Try if let Some(y) = x { ... }
Some(y) => println!("{:?}", y), Some(y) => println!("{:?}", y),
_ => () _ => ()
} }
@ -17,7 +17,7 @@ fn main(){
} }
let z = (1u8,1u8); let z = (1u8,1u8);
match z { //~ ERROR You seem to be trying to use match match z { //~ ERROR You seem to be trying to use match
//~^ NOTE Try if let (2...3, 7...9) = z { ... } //~^ HELP Try if let (2...3, 7...9) = z { ... }
(2...3, 7...9) => println!("{:?}", z), (2...3, 7...9) => println!("{:?}", z),
_ => {} _ => {}
} }