From badfbbbbde9b95c3c87c75d3c15fee1fd500befd Mon Sep 17 00:00:00 2001 From: ThibsG Date: Sat, 21 Mar 2020 20:26:55 +0100 Subject: [PATCH] Fix single binding in closure --- clippy_lints/src/matches.rs | 26 ++++++++++++++++++++------ tests/ui/match_single_binding.fixed | 10 ++++++++++ tests/ui/match_single_binding.rs | 9 +++++++++ tests/ui/match_single_binding.stderr | 19 ++++++++++++++++++- 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index b0aae5e30e6e8..40880f78270c4 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -3,9 +3,10 @@ use crate::utils::paths; use crate::utils::sugg::Sugg; use crate::utils::usage::is_unused; use crate::utils::{ - expr_block, get_arg_name, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild, match_qpath, - match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block, snippet_with_applicability, - span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, walk_ptrs_ty, + expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild, + match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block, + snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, + walk_ptrs_ty, }; use if_chain::if_chain; use rustc::lint::in_external_macro; @@ -928,14 +929,27 @@ fn check_match_single_binding<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>, arms: ), ) } else { + // If we are in closure, we need curly braces around suggestion + let mut indent = " ".repeat(indent_of(cx, ex.span).unwrap_or(0)); + let (mut cbrace_start, mut cbrace_end) = ("".to_string(), "".to_string()); + if let Some(parent_expr) = get_parent_expr(cx, expr) { + if let ExprKind::Closure(..) = parent_expr.kind { + cbrace_end = format!("\n{}}}", indent); + // Fix body indent due to the closure + indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0)); + cbrace_start = format!("{{\n{}", indent); + } + }; ( expr.span, format!( - "let {} = {};\n{}{}", + "{}let {} = {};\n{}{}{}", + cbrace_start, snippet_with_applicability(cx, bind_names, "..", &mut applicability), snippet_with_applicability(cx, matched_vars, "..", &mut applicability), - " ".repeat(indent_of(cx, expr.span).unwrap_or(0)), - snippet_body + indent, + snippet_body, + cbrace_end ), ) }; diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed index bc2346a8dbf0b..90f00aa78712d 100644 --- a/tests/ui/match_single_binding.fixed +++ b/tests/ui/match_single_binding.fixed @@ -67,4 +67,14 @@ fn main() { // Lint let Point { x, y } = coords(); let product = x * y; + // Lint + let v = vec![Some(1), Some(2), Some(3), Some(4)]; + #[allow(clippy::let_and_return)] + let _ = v + .iter() + .map(|i| { + let unwrapped = i.unwrap(); + unwrapped + }) + .collect::>(); } diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs index 0517b3bbfbf93..4a4b290036c79 100644 --- a/tests/ui/match_single_binding.rs +++ b/tests/ui/match_single_binding.rs @@ -80,4 +80,13 @@ fn main() { let product = match coords() { Point { x, y } => x * y, }; + // Lint + let v = vec![Some(1), Some(2), Some(3), Some(4)]; + #[allow(clippy::let_and_return)] + let _ = v + .iter() + .map(|i| match i.unwrap() { + unwrapped => unwrapped, + }) + .collect::>(); } diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr index 05ba9e5f7f3cd..cf741a989c2df 100644 --- a/tests/ui/match_single_binding.stderr +++ b/tests/ui/match_single_binding.stderr @@ -150,5 +150,22 @@ LL | let Point { x, y } = coords(); LL | let product = x * y; | -error: aborting due to 10 previous errors +error: this match could be written as a `let` statement + --> $DIR/match_single_binding.rs:88:18 + | +LL | .map(|i| match i.unwrap() { + | __________________^ +LL | | unwrapped => unwrapped, +LL | | }) + | |_________^ + | +help: consider using `let` statement + | +LL | .map(|i| { +LL | let unwrapped = i.unwrap(); +LL | unwrapped +LL | }) + | + +error: aborting due to 11 previous errors