]>
Commit | Line | Data |
---|---|---|
3c0e092e | 1 | use super::SINGLE_ELEMENT_LOOP; |
cdc7bbd5 XL |
2 | use clippy_utils::diagnostics::span_lint_and_sugg; |
3 | use clippy_utils::single_segment_path; | |
4 | use clippy_utils::source::{indent_of, snippet}; | |
f20569fa XL |
5 | use if_chain::if_chain; |
6 | use rustc_errors::Applicability; | |
7 | use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind}; | |
8 | use rustc_lint::LateContext; | |
9 | ||
10 | pub(super) fn check<'tcx>( | |
11 | cx: &LateContext<'tcx>, | |
12 | pat: &'tcx Pat<'_>, | |
13 | arg: &'tcx Expr<'_>, | |
14 | body: &'tcx Expr<'_>, | |
15 | expr: &'tcx Expr<'_>, | |
16 | ) { | |
cdc7bbd5 XL |
17 | let arg_expr = match arg.kind { |
18 | ExprKind::AddrOf(BorrowKind::Ref, _, ref_arg) => ref_arg, | |
19 | ExprKind::MethodCall(method, _, args, _) if args.len() == 1 && method.ident.name == rustc_span::sym::iter => { | |
20 | &args[0] | |
21 | }, | |
22 | _ => return, | |
23 | }; | |
f20569fa | 24 | if_chain! { |
f20569fa XL |
25 | if let PatKind::Binding(.., target, _) = pat.kind; |
26 | if let ExprKind::Array([arg_expression]) = arg_expr.kind; | |
27 | if let ExprKind::Path(ref list_item) = arg_expression.kind; | |
28 | if let Some(list_item_name) = single_segment_path(list_item).map(|ps| ps.ident.name); | |
cdc7bbd5 | 29 | if let ExprKind::Block(block, _) = body.kind; |
f20569fa XL |
30 | if !block.stmts.is_empty(); |
31 | ||
32 | then { | |
f20569fa XL |
33 | let mut block_str = snippet(cx, block.span, "..").into_owned(); |
34 | block_str.remove(0); | |
35 | block_str.pop(); | |
36 | ||
37 | ||
38 | span_lint_and_sugg( | |
39 | cx, | |
40 | SINGLE_ELEMENT_LOOP, | |
3c0e092e | 41 | expr.span, |
f20569fa XL |
42 | "for loop over a single element", |
43 | "try", | |
44 | format!("{{\n{}let {} = &{};{}}}", " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0)), target.name, list_item_name, block_str), | |
45 | Applicability::MachineApplicable | |
46 | ) | |
47 | } | |
48 | } | |
49 | } |