From 24f0cd8293c73b376a5e448dcbadcf189e8698aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 22 Jan 2021 23:29:51 +0100 Subject: replace_if_let_with_match: don't assume sad pattern --- .../src/handlers/replace_if_let_with_match.rs | 90 +++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) (limited to 'crates/assists/src/handlers') diff --git a/crates/assists/src/handlers/replace_if_let_with_match.rs b/crates/assists/src/handlers/replace_if_let_with_match.rs index aee3397ab..abebd4b6a 100644 --- a/crates/assists/src/handlers/replace_if_let_with_match.rs +++ b/crates/assists/src/handlers/replace_if_let_with_match.rs @@ -5,7 +5,7 @@ use syntax::{ ast::{ self, edit::{AstNodeEdit, IndentLevel}, - make, + make, Pat, }, AstNode, }; @@ -66,7 +66,13 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext) .sema .type_of_pat(&pat) .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty)) - .map(|it| it.sad_pattern()) + .map(|it| { + if does_pat_match_variant(&pat, &it.sad_pattern()) { + it.happy_pattern() + } else { + it.sad_pattern() + } + }) .unwrap_or_else(|| make::wildcard_pat().into()); let else_expr = unwrap_trivial_block(else_block); make::match_arm(vec![pattern], else_expr) @@ -81,6 +87,26 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext) ) } +fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool { + let first_node_text = |pat: &Pat| pat.syntax().first_child().map(|node| node.text()); + + let pat_head = match pat { + Pat::IdentPat(bind_pat) => { + if let Some(p) = bind_pat.pat() { + first_node_text(&p) + } else { + return pat.syntax().text() == var.syntax().text(); + } + } + pat => first_node_text(pat), + }; + + let var_head = first_node_text(var); + println!("{:?} {:?}", pat_head, var_head); + + pat_head == var_head +} + // Assist: replace_match_with_if_let // // Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression. @@ -278,6 +304,36 @@ fn foo(x: Option) { ); } + #[test] + fn special_case_inverted_option() { + check_assist( + replace_if_let_with_match, + r#" +enum Option { Some(T), None } +use Option::*; + +fn foo(x: Option) { + $0if let None = x { + println!("none") + } else { + println!("some") + } +} + "#, + r#" +enum Option { Some(T), None } +use Option::*; + +fn foo(x: Option) { + match x { + None => println!("none"), + Some(_) => println!("some"), + } +} + "#, + ); + } + #[test] fn special_case_result() { check_assist( @@ -308,6 +364,36 @@ fn foo(x: Result) { ); } + #[test] + fn special_case_inverted_result() { + check_assist( + replace_if_let_with_match, + r#" +enum Result { Ok(T), Err(E) } +use Result::*; + +fn foo(x: Result) { + $0if let Err(x) = x { + println!("{}", x) + } else { + println!("ok") + } +} + "#, + r#" +enum Result { Ok(T), Err(E) } +use Result::*; + +fn foo(x: Result) { + match x { + Err(x) => println!("{}", x), + Ok(_) => println!("ok"), + } +} + "#, + ); + } + #[test] fn nested_indent() { check_assist( -- cgit v1.2.3