match .map(Clone::clone)
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc_front::hir::*;
|
use rustc_front::hir::*;
|
||||||
use syntax::ast::Ident;
|
use syntax::ast::Ident;
|
||||||
use utils::OPTION_PATH;
|
use utils::{CLONE_PATH, OPTION_PATH};
|
||||||
use utils::{is_adjusted, match_trait_method, match_type, snippet, span_help_and_lint};
|
use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint};
|
||||||
use utils::{walk_ptrs_ty, walk_ptrs_ty_depth};
|
use utils::{walk_ptrs_ty, walk_ptrs_ty_depth};
|
||||||
|
|
||||||
declare_lint!(pub MAP_CLONE, Warn,
|
declare_lint!(pub MAP_CLONE, Warn,
|
||||||
@@ -14,12 +14,13 @@ pub struct MapClonePass;
|
|||||||
|
|
||||||
impl LateLintPass for MapClonePass {
|
impl LateLintPass for MapClonePass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||||
|
// call to .map()
|
||||||
|
if let ExprMethodCall(name, _, ref args) = expr.node {
|
||||||
|
if name.node.as_str() == "map" && args.len() == 2 {
|
||||||
|
match args[1].node {
|
||||||
|
ExprClosure(_, ref decl, ref blk) => {
|
||||||
if_let_chain! {
|
if_let_chain! {
|
||||||
[
|
[
|
||||||
// call to .map()
|
|
||||||
let ExprMethodCall(name, _, ref args) = expr.node,
|
|
||||||
name.node.as_str() == "map" && args.len() == 2,
|
|
||||||
let ExprClosure(_, ref decl, ref blk) = args[1].node,
|
|
||||||
// just one expression in the closure
|
// just one expression in the closure
|
||||||
blk.stmts.is_empty(),
|
blk.stmts.is_empty(),
|
||||||
let Some(ref closure_expr) = blk.expr,
|
let Some(ref closure_expr) = blk.expr,
|
||||||
@@ -54,6 +55,20 @@ impl LateLintPass for MapClonePass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
ExprPath(_, ref path) => {
|
||||||
|
if match_path(path, &CLONE_PATH) {
|
||||||
|
let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_");
|
||||||
|
span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
|
||||||
|
"you seem to be using .map() to clone the contents of an {}, consider \
|
||||||
|
using `.cloned()`", type_name),
|
||||||
|
&format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"];
|
|||||||
pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];
|
pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];
|
||||||
pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"];
|
pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"];
|
||||||
pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"];
|
pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"];
|
||||||
|
pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"];
|
||||||
|
|
||||||
/// Produce a nested chain of if-lets and ifs from the patterns:
|
/// Produce a nested chain of if-lets and ifs from the patterns:
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ fn map_clone_iter() {
|
|||||||
//~^ HELP try
|
//~^ HELP try
|
||||||
x.iter().map(|y| *y); //~ ERROR you seem to be using .map()
|
x.iter().map(|y| *y); //~ ERROR you seem to be using .map()
|
||||||
//~^ HELP try
|
//~^ HELP try
|
||||||
|
x.iter().map(Clone::clone); //~ ERROR you seem to be using .map()
|
||||||
|
//~^ HELP try
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_clone_option() {
|
fn map_clone_option() {
|
||||||
|
|||||||
Reference in New Issue
Block a user