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 From 5728d7186e64966a20ece3dc479153219a47ba17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 22 Jan 2021 23:31:19 +0100 Subject: Deduplicate variant matching --- crates/assists/src/handlers/fill_match_arms.rs | 21 +---------------- .../src/handlers/replace_if_let_with_match.rs | 27 ++++------------------ 2 files changed, 6 insertions(+), 42 deletions(-) (limited to 'crates/assists/src/handlers') diff --git a/crates/assists/src/handlers/fill_match_arms.rs b/crates/assists/src/handlers/fill_match_arms.rs index da47187e4..7663d211d 100644 --- a/crates/assists/src/handlers/fill_match_arms.rs +++ b/crates/assists/src/handlers/fill_match_arms.rs @@ -8,7 +8,7 @@ use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat}; use test_utils::mark; use crate::{ - utils::{render_snippet, Cursor}, + utils::{does_pat_match_variant, render_snippet, Cursor}, AssistContext, AssistId, AssistKind, Assists, }; @@ -147,25 +147,6 @@ fn is_variant_missing(existing_arms: &mut Vec, var: &Pat) -> bool { }) } -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 false; - } - } - pat => first_node_text(pat), - }; - - let var_head = first_node_text(var); - - pat_head == var_head -} - fn resolve_enum_def(sema: &Semantics, expr: &ast::Expr) -> Option { sema.type_of_expr(&expr)?.autoderef(sema.db).find_map(|ty| match ty.as_adt() { Some(Adt::Enum(e)) => Some(e), 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 abebd4b6a..aee880625 100644 --- a/crates/assists/src/handlers/replace_if_let_with_match.rs +++ b/crates/assists/src/handlers/replace_if_let_with_match.rs @@ -5,12 +5,15 @@ use syntax::{ ast::{ self, edit::{AstNodeEdit, IndentLevel}, - make, Pat, + make, }, AstNode, }; -use crate::{utils::unwrap_trivial_block, AssistContext, AssistId, AssistKind, Assists}; +use crate::{ + utils::{does_pat_match_variant, unwrap_trivial_block}, + AssistContext, AssistId, AssistKind, Assists, +}; // Assist: replace_if_let_with_match // @@ -87,26 +90,6 @@ 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. -- cgit v1.2.3