aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2021-01-22 22:29:51 +0000
committerDániel Buga <[email protected]>2021-01-22 22:29:51 +0000
commit24f0cd8293c73b376a5e448dcbadcf189e8698aa (patch)
treeb71a6ee26c86248d3e8ddb779b3194851f3c52d6 /crates
parentf301da3c3d1c73dd9d438cb0736e23430287dba7 (diff)
replace_if_let_with_match: don't assume sad pattern
Diffstat (limited to 'crates')
-rw-r--r--crates/assists/src/handlers/replace_if_let_with_match.rs90
-rw-r--r--crates/ide_db/src/ty_filter.rs15
2 files changed, 103 insertions, 2 deletions
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::{
5 ast::{ 5 ast::{
6 self, 6 self,
7 edit::{AstNodeEdit, IndentLevel}, 7 edit::{AstNodeEdit, IndentLevel},
8 make, 8 make, Pat,
9 }, 9 },
10 AstNode, 10 AstNode,
11}; 11};
@@ -66,7 +66,13 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
66 .sema 66 .sema
67 .type_of_pat(&pat) 67 .type_of_pat(&pat)
68 .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty)) 68 .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty))
69 .map(|it| it.sad_pattern()) 69 .map(|it| {
70 if does_pat_match_variant(&pat, &it.sad_pattern()) {
71 it.happy_pattern()
72 } else {
73 it.sad_pattern()
74 }
75 })
70 .unwrap_or_else(|| make::wildcard_pat().into()); 76 .unwrap_or_else(|| make::wildcard_pat().into());
71 let else_expr = unwrap_trivial_block(else_block); 77 let else_expr = unwrap_trivial_block(else_block);
72 make::match_arm(vec![pattern], else_expr) 78 make::match_arm(vec![pattern], else_expr)
@@ -81,6 +87,26 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
81 ) 87 )
82} 88}
83 89
90fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool {
91 let first_node_text = |pat: &Pat| pat.syntax().first_child().map(|node| node.text());
92
93 let pat_head = match pat {
94 Pat::IdentPat(bind_pat) => {
95 if let Some(p) = bind_pat.pat() {
96 first_node_text(&p)
97 } else {
98 return pat.syntax().text() == var.syntax().text();
99 }
100 }
101 pat => first_node_text(pat),
102 };
103
104 let var_head = first_node_text(var);
105 println!("{:?} {:?}", pat_head, var_head);
106
107 pat_head == var_head
108}
109
84// Assist: replace_match_with_if_let 110// Assist: replace_match_with_if_let
85// 111//
86// Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression. 112// Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression.
@@ -279,6 +305,36 @@ fn foo(x: Option<i32>) {
279 } 305 }
280 306
281 #[test] 307 #[test]
308 fn special_case_inverted_option() {
309 check_assist(
310 replace_if_let_with_match,
311 r#"
312enum Option<T> { Some(T), None }
313use Option::*;
314
315fn foo(x: Option<i32>) {
316 $0if let None = x {
317 println!("none")
318 } else {
319 println!("some")
320 }
321}
322 "#,
323 r#"
324enum Option<T> { Some(T), None }
325use Option::*;
326
327fn foo(x: Option<i32>) {
328 match x {
329 None => println!("none"),
330 Some(_) => println!("some"),
331 }
332}
333 "#,
334 );
335 }
336
337 #[test]
282 fn special_case_result() { 338 fn special_case_result() {
283 check_assist( 339 check_assist(
284 replace_if_let_with_match, 340 replace_if_let_with_match,
@@ -309,6 +365,36 @@ fn foo(x: Result<i32, ()>) {
309 } 365 }
310 366
311 #[test] 367 #[test]
368 fn special_case_inverted_result() {
369 check_assist(
370 replace_if_let_with_match,
371 r#"
372enum Result<T, E> { Ok(T), Err(E) }
373use Result::*;
374
375fn foo(x: Result<i32, ()>) {
376 $0if let Err(x) = x {
377 println!("{}", x)
378 } else {
379 println!("ok")
380 }
381}
382 "#,
383 r#"
384enum Result<T, E> { Ok(T), Err(E) }
385use Result::*;
386
387fn foo(x: Result<i32, ()>) {
388 match x {
389 Err(x) => println!("{}", x),
390 Ok(_) => println!("ok"),
391 }
392}
393 "#,
394 );
395 }
396
397 #[test]
312 fn nested_indent() { 398 fn nested_indent() {
313 check_assist( 399 check_assist(
314 replace_if_let_with_match, 400 replace_if_let_with_match,
diff --git a/crates/ide_db/src/ty_filter.rs b/crates/ide_db/src/ty_filter.rs
index 63a945282..f8406851b 100644
--- a/crates/ide_db/src/ty_filter.rs
+++ b/crates/ide_db/src/ty_filter.rs
@@ -49,6 +49,21 @@ impl TryEnum {
49 } 49 }
50 } 50 }
51 51
52 pub fn happy_pattern(self) -> ast::Pat {
53 match self {
54 TryEnum::Result => make::tuple_struct_pat(
55 make::path_unqualified(make::path_segment(make::name_ref("Ok"))),
56 iter::once(make::wildcard_pat().into()),
57 )
58 .into(),
59 TryEnum::Option => make::tuple_struct_pat(
60 make::path_unqualified(make::path_segment(make::name_ref("Some"))),
61 iter::once(make::wildcard_pat().into()),
62 )
63 .into(),
64 }
65 }
66
52 fn type_name(self) -> &'static str { 67 fn type_name(self) -> &'static str {
53 match self { 68 match self {
54 TryEnum::Result => "Result", 69 TryEnum::Result => "Result",