mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
utils: extract utility method for matching trait method calls from loops
This commit is contained in:
parent
5a5b1ba96b
commit
c8a2e848ab
11
src/loops.rs
11
src/loops.rs
@ -1,10 +1,9 @@
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
use syntax::visit::{Visitor, walk_expr};
|
use syntax::visit::{Visitor, walk_expr};
|
||||||
use rustc::middle::ty;
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use utils::{snippet, span_lint, get_parent_expr, match_def_path};
|
use utils::{snippet, span_lint, get_parent_expr, match_trait_method};
|
||||||
|
|
||||||
declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn,
|
declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn,
|
||||||
"for-looping over a range of indices where an iterator over items would do" }
|
"for-looping over a range of indices where an iterator over items would do" }
|
||||||
@ -68,12 +67,7 @@ impl LintPass for LoopsPass {
|
|||||||
object, object));
|
object, object));
|
||||||
// check for looping over Iterator::next() which is not what you want
|
// check for looping over Iterator::next() which is not what you want
|
||||||
} else if method_name == "next" {
|
} else if method_name == "next" {
|
||||||
let method_call = ty::MethodCall::expr(arg.id);
|
if match_trait_method(cx, arg, &["core", "iter", "Iterator"]) {
|
||||||
let trt_id = cx.tcx.tables
|
|
||||||
.borrow().method_map.get(&method_call)
|
|
||||||
.and_then(|callee| cx.tcx.trait_of_item(callee.def_id));
|
|
||||||
if let Some(trt_id) = trt_id {
|
|
||||||
if match_def_path(cx, trt_id, &["core", "iter", "Iterator"]) {
|
|
||||||
span_lint(cx, ITER_NEXT_LOOP, expr.span,
|
span_lint(cx, ITER_NEXT_LOOP, expr.span,
|
||||||
"you are iterating over `Iterator::next()` which is an Option; \
|
"you are iterating over `Iterator::next()` which is an Option; \
|
||||||
this will compile but is probably not what you want");
|
this will compile but is probably not what you want");
|
||||||
@ -84,7 +78,6 @@ impl LintPass for LoopsPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Recover the essential nodes of a desugared for loop:
|
/// Recover the essential nodes of a desugared for loop:
|
||||||
/// `for pat in arg { body }` becomes `(pat, arg, body)`.
|
/// `for pat in arg { body }` becomes `(pat, arg, body)`.
|
||||||
|
13
src/utils.rs
13
src/utils.rs
@ -56,6 +56,19 @@ pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// check if method call given in "expr" belongs to given trait
|
||||||
|
pub fn match_trait_method(cx: &Context, expr: &Expr, path: &[&str]) -> bool {
|
||||||
|
let method_call = ty::MethodCall::expr(expr.id);
|
||||||
|
let trt_id = cx.tcx.tables
|
||||||
|
.borrow().method_map.get(&method_call)
|
||||||
|
.and_then(|callee| cx.tcx.trait_of_item(callee.def_id));
|
||||||
|
if let Some(trt_id) = trt_id {
|
||||||
|
match_def_path(cx, trt_id, path)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// match a Path against a slice of segment string literals, e.g.
|
/// match a Path against a slice of segment string literals, e.g.
|
||||||
/// `match_path(path, &["std", "rt", "begin_unwind"])`
|
/// `match_path(path, &["std", "rt", "begin_unwind"])`
|
||||||
pub fn match_path(path: &Path, segments: &[&str]) -> bool {
|
pub fn match_path(path: &Path, segments: &[&str]) -> bool {
|
||||||
|
Loading…
Reference in New Issue
Block a user