|
| 1 | +use clippy_utils::diagnostics::span_lint_and_then; |
| 2 | +use clippy_utils::source::{indent_of, reindent_multiline, snippet}; |
| 3 | +use clippy_utils::{is_res_lang_ctor, pat_is_wild, path_res}; |
| 4 | +use rustc_ast::util::parser::ExprPrecedence; |
| 5 | +use rustc_errors::Applicability; |
| 6 | +use rustc_hir::LangItem::OptionSome; |
| 7 | +use rustc_hir::{Body, Expr, ExprKind}; |
| 8 | +use rustc_lint::LateContext; |
| 9 | + |
| 10 | +use super::FILTER_SOME; |
| 11 | + |
| 12 | +pub(super) fn check<'tcx>( |
| 13 | + cx: &LateContext<'tcx>, |
| 14 | + expr: &'tcx Expr<'tcx>, |
| 15 | + recv: &'tcx Expr<'tcx>, |
| 16 | + arg: &'tcx Expr<'tcx>, |
| 17 | +) { |
| 18 | + let value = match recv.kind { |
| 19 | + ExprKind::Call(f, [value]) if is_res_lang_ctor(cx, path_res(cx, f), OptionSome) => value, |
| 20 | + _ => return, |
| 21 | + }; |
| 22 | + let condition = if let ExprKind::Closure(c) = arg.kind |
| 23 | + && let Body { |
| 24 | + params: [p], |
| 25 | + value: condition, |
| 26 | + } = cx.tcx.hir_body(c.body) |
| 27 | + && pat_is_wild(cx, &p.pat.kind, arg) |
| 28 | + { |
| 29 | + Some(condition) |
| 30 | + } else { |
| 31 | + None |
| 32 | + }; |
| 33 | + span_lint_and_then(cx, FILTER_SOME, expr.span, "`filter` for `Some`", |diag| { |
| 34 | + let help = "consider using `then_some` instead"; |
| 35 | + if let Some(condition) = condition { |
| 36 | + let parentheses = cx.precedence(condition) < ExprPrecedence::Unambiguous; |
| 37 | + diag.span_suggestion( |
| 38 | + expr.span, |
| 39 | + help, |
| 40 | + reindent_multiline( |
| 41 | + &format!( |
| 42 | + "{}{}{}.then_some({})", |
| 43 | + if parentheses { "(" } else { "" }, |
| 44 | + snippet(cx, condition.span, ".."), |
| 45 | + if parentheses { ")" } else { "" }, |
| 46 | + snippet(cx, value.span, "..") |
| 47 | + ), |
| 48 | + true, |
| 49 | + indent_of(cx, expr.span), |
| 50 | + ), |
| 51 | + Applicability::MaybeIncorrect, |
| 52 | + ); |
| 53 | + diag.note( |
| 54 | + "this change will alter the order in which the condition and \ |
| 55 | + the value are evaluated", |
| 56 | + ); |
| 57 | + } else { |
| 58 | + diag.help(help); |
| 59 | + } |
| 60 | + }); |
| 61 | +} |
0 commit comments