Skip to content

Commit

Permalink
Perform another layer of pattern equality checking before spelling th…
Browse files Browse the repository at this point in the history
…e lint
  • Loading branch information
nahuakang committed Jan 17, 2021
1 parent 32405b8 commit ff1229a
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 13 deletions.
47 changes: 35 additions & 12 deletions clippy_lints/src/methods/inspect_then_for_each.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,46 @@
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::source_map::Span;

use crate::utils::{match_trait_method, paths, span_lint_and_help};
use crate::utils::{match_trait_method, paths, span_lint_and_help, SpanlessEq};

use super::INSPECT_THEN_FOR_EACH;

/// lint use of `inspect().for_each()` for `Iterators`
pub(super) fn lint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, inspect_span: Span) {
pub(super) fn lint<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx hir::Expr<'_>,
inspect_args: &'tcx [hir::Expr<'_>],
for_each_args: &'tcx [hir::Expr<'_>],
inspect_span: Span,
) {
if match_trait_method(cx, expr, &paths::ITERATOR) {
let msg = "called `inspect(..).for_each(..)` on an `Iterator`";
let hint = "move the code from `inspect(..)` to `for_each(..)` and remove the `inspect(..)`";
span_lint_and_help(
cx,
INSPECT_THEN_FOR_EACH,
inspect_span.with_hi(expr.span.hi()),
msg,
None,
hint,
);
let inspect_closure = &inspect_args[1].kind;
let for_each_closure = &for_each_args[1].kind;

if_chain! {
if let hir::ExprKind::Closure(_, _, inspect_closure_body_id, _, _) = inspect_closure;
if let hir::ExprKind::Closure(_, _, for_each_closure_body_id, _, _) = for_each_closure;

let inspect_closure_pat = cx.tcx.hir().body(*inspect_closure_body_id).params[0].pat;
let for_each_closure_pat = cx.tcx.hir().body(*for_each_closure_body_id).params[0].pat;

if SpanlessEq::new(cx).eq_pat(inspect_closure_pat, for_each_closure_pat);

then {
let msg = "called `inspect(..).for_each(..)` on an `Iterator`";
let hint = "move the code from `inspect(..)` to `for_each(..)` and remove the `inspect(..)`";

span_lint_and_help(
cx,
INSPECT_THEN_FOR_EACH,
inspect_span.with_hi(expr.span.hi()),
msg,
None,
hint,
);
}
}
}
}
4 changes: 3 additions & 1 deletion clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1585,7 +1585,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
["get_or_insert_with", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "get_or_insert"),
["ok_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "ok_or"),
["collect", "map"] => lint_map_collect(cx, expr, arg_lists[1], arg_lists[0]),
["for_each", "inspect"] => inspect_then_for_each::lint(cx, expr, method_spans[1]),
["for_each", "inspect"] => {
inspect_then_for_each::lint(cx, expr, arg_lists[1], arg_lists[0], method_spans[1])
},
_ => {},
}

Expand Down

0 comments on commit ff1229a

Please sign in to comment.