aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ide_assists/src/handlers/fill_match_arms.rs148
-rw-r--r--crates/ide_assists/src/tests/generated.rs4
-rw-r--r--crates/syntax/src/ast/edit_in_place.rs21
-rw-r--r--xtask/src/tidy.rs1
4 files changed, 112 insertions, 62 deletions
diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs
index 97435f021..3d2cd739a 100644
--- a/crates/ide_assists/src/handlers/fill_match_arms.rs
+++ b/crates/ide_assists/src/handlers/fill_match_arms.rs
@@ -31,8 +31,8 @@ use crate::{
31// 31//
32// fn handle(action: Action) { 32// fn handle(action: Action) {
33// match action { 33// match action {
34// $0Action::Move { distance } => {} 34// $0Action::Move { distance } => todo!(),
35// Action::Stop => {} 35// Action::Stop => todo!(),
36// } 36// }
37// } 37// }
38// ``` 38// ```
@@ -129,7 +129,7 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
129 |builder| { 129 |builder| {
130 let new_match_arm_list = match_arm_list.clone_for_update(); 130 let new_match_arm_list = match_arm_list.clone_for_update();
131 let missing_arms = missing_pats 131 let missing_arms = missing_pats
132 .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) 132 .map(|pat| make::match_arm(iter::once(pat), make::ext::expr_todo()))
133 .map(|it| it.clone_for_update()); 133 .map(|it| it.clone_for_update());
134 134
135 let catch_all_arm = new_match_arm_list 135 let catch_all_arm = new_match_arm_list
@@ -350,8 +350,8 @@ fn foo(a: bool) {
350 r#" 350 r#"
351fn foo(a: bool) { 351fn foo(a: bool) {
352 match a { 352 match a {
353 $0true => {} 353 $0true => todo!(),
354 false => {} 354 false => todo!(),
355 } 355 }
356} 356}
357"#, 357"#,
@@ -373,7 +373,7 @@ fn foo(a: bool) {
373fn foo(a: bool) { 373fn foo(a: bool) {
374 match a { 374 match a {
375 true => {} 375 true => {}
376 $0false => {} 376 $0false => todo!(),
377 } 377 }
378} 378}
379"#, 379"#,
@@ -410,10 +410,10 @@ fn foo(a: bool) {
410 r#" 410 r#"
411fn foo(a: bool) { 411fn foo(a: bool) {
412 match (a, a) { 412 match (a, a) {
413 $0(true, true) => {} 413 $0(true, true) => todo!(),
414 (true, false) => {} 414 (true, false) => todo!(),
415 (false, true) => {} 415 (false, true) => todo!(),
416 (false, false) => {} 416 (false, false) => todo!(),
417 } 417 }
418} 418}
419"#, 419"#,
@@ -435,9 +435,9 @@ fn foo(a: bool) {
435fn foo(a: bool) { 435fn foo(a: bool) {
436 match (a, a) { 436 match (a, a) {
437 (false, true) => {} 437 (false, true) => {}
438 $0(true, true) => {} 438 $0(true, true) => todo!(),
439 (true, false) => {} 439 (true, false) => todo!(),
440 (false, false) => {} 440 (false, false) => todo!(),
441 } 441 }
442} 442}
443"#, 443"#,
@@ -471,7 +471,7 @@ fn main() {
471 match A::As { 471 match A::As {
472 A::Bs { x, y: Some(_) } => {} 472 A::Bs { x, y: Some(_) } => {}
473 A::Cs(_, Some(_)) => {} 473 A::Cs(_, Some(_)) => {}
474 $0A::As => {} 474 $0A::As => todo!(),
475 } 475 }
476} 476}
477"#, 477"#,
@@ -499,7 +499,7 @@ use Option::*;
499fn main() { 499fn main() {
500 match None { 500 match None {
501 None => {} 501 None => {}
502 Some(${0:_}) => {} 502 Some(${0:_}) => todo!(),
503 } 503 }
504} 504}
505 "#, 505 "#,
@@ -523,7 +523,7 @@ enum A { As, Bs, Cs(Option<i32>) }
523fn main() { 523fn main() {
524 match A::As { 524 match A::As {
525 A::Cs(_) | A::Bs => {} 525 A::Cs(_) | A::Bs => {}
526 $0A::As => {} 526 $0A::As => todo!(),
527 } 527 }
528} 528}
529"#, 529"#,
@@ -553,8 +553,8 @@ fn main() {
553 A::Bs if 0 < 1 => {} 553 A::Bs if 0 < 1 => {}
554 A::Ds(_value) => { let x = 1; } 554 A::Ds(_value) => { let x = 1; }
555 A::Es(B::Xs) => (), 555 A::Es(B::Xs) => (),
556 $0A::As => {} 556 $0A::As => todo!(),
557 A::Cs => {} 557 A::Cs => todo!(),
558 } 558 }
559} 559}
560"#, 560"#,
@@ -580,7 +580,7 @@ fn main() {
580 match A::As { 580 match A::As {
581 A::As(_) => {} 581 A::As(_) => {}
582 a @ A::Bs(_) => {} 582 a @ A::Bs(_) => {}
583 A::Cs(${0:_}) => {} 583 A::Cs(${0:_}) => todo!(),
584 } 584 }
585} 585}
586"#, 586"#,
@@ -605,11 +605,11 @@ enum A { As, Bs, Cs(String), Ds(String, String), Es { x: usize, y: usize } }
605fn main() { 605fn main() {
606 let a = A::As; 606 let a = A::As;
607 match a { 607 match a {
608 $0A::As => {} 608 $0A::As => todo!(),
609 A::Bs => {} 609 A::Bs => todo!(),
610 A::Cs(_) => {} 610 A::Cs(_) => todo!(),
611 A::Ds(_, _) => {} 611 A::Ds(_, _) => todo!(),
612 A::Es { x, y } => {} 612 A::Es { x, y } => todo!(),
613 } 613 }
614} 614}
615"#, 615"#,
@@ -638,10 +638,10 @@ fn main() {
638 let a = A::One; 638 let a = A::One;
639 let b = B::One; 639 let b = B::One;
640 match (a, b) { 640 match (a, b) {
641 $0(A::One, B::One) => {} 641 $0(A::One, B::One) => todo!(),
642 (A::One, B::Two) => {} 642 (A::One, B::Two) => todo!(),
643 (A::Two, B::One) => {} 643 (A::Two, B::One) => todo!(),
644 (A::Two, B::Two) => {} 644 (A::Two, B::Two) => todo!(),
645 } 645 }
646} 646}
647"#, 647"#,
@@ -670,10 +670,10 @@ fn main() {
670 let a = A::One; 670 let a = A::One;
671 let b = B::One; 671 let b = B::One;
672 match (&a, &b) { 672 match (&a, &b) {
673 $0(A::One, B::One) => {} 673 $0(A::One, B::One) => todo!(),
674 (A::One, B::Two) => {} 674 (A::One, B::Two) => todo!(),
675 (A::Two, B::One) => {} 675 (A::Two, B::One) => todo!(),
676 (A::Two, B::Two) => {} 676 (A::Two, B::Two) => todo!(),
677 } 677 }
678} 678}
679"#, 679"#,
@@ -705,9 +705,9 @@ fn main() {
705 let b = B::One; 705 let b = B::One;
706 match (a, b) { 706 match (a, b) {
707 (A::Two, B::One) => {} 707 (A::Two, B::One) => {}
708 $0(A::One, B::One) => {} 708 $0(A::One, B::One) => todo!(),
709 (A::One, B::Two) => {} 709 (A::One, B::Two) => todo!(),
710 (A::Two, B::Two) => {} 710 (A::Two, B::Two) => todo!(),
711 } 711 }
712} 712}
713"#, 713"#,
@@ -736,7 +736,7 @@ fn main() {
736 match (a, b) { 736 match (a, b) {
737 (Some(_), _) => {} 737 (Some(_), _) => {}
738 (None, Some(_)) => {} 738 (None, Some(_)) => {}
739 $0(None, None) => {} 739 $0(None, None) => todo!(),
740 } 740 }
741} 741}
742"#, 742"#,
@@ -801,8 +801,8 @@ enum A { One, Two }
801fn main() { 801fn main() {
802 let a = A::One; 802 let a = A::One;
803 match (a, ) { 803 match (a, ) {
804 $0(A::One,) => {} 804 $0(A::One,) => todo!(),
805 (A::Two,) => {} 805 (A::Two,) => todo!(),
806 } 806 }
807} 807}
808"#, 808"#,
@@ -826,7 +826,7 @@ enum A { As }
826 826
827fn foo(a: &A) { 827fn foo(a: &A) {
828 match a { 828 match a {
829 $0A::As => {} 829 $0A::As => todo!(),
830 } 830 }
831} 831}
832"#, 832"#,
@@ -851,7 +851,7 @@ enum A {
851 851
852fn foo(a: &mut A) { 852fn foo(a: &mut A) {
853 match a { 853 match a {
854 $0A::Es { x, y } => {} 854 $0A::Es { x, y } => todo!(),
855 } 855 }
856} 856}
857"#, 857"#,
@@ -891,8 +891,8 @@ enum E { X, Y }
891 891
892fn main() { 892fn main() {
893 match E::X { 893 match E::X {
894 $0E::X => {} 894 $0E::X => todo!(),
895 E::Y => {} 895 E::Y => todo!(),
896 } 896 }
897} 897}
898"#, 898"#,
@@ -919,8 +919,8 @@ use foo::E::X;
919 919
920fn main() { 920fn main() {
921 match X { 921 match X {
922 $0X => {} 922 $0X => todo!(),
923 foo::E::Y => {} 923 foo::E::Y => todo!(),
924 } 924 }
925} 925}
926"#, 926"#,
@@ -947,7 +947,7 @@ fn foo(a: A) {
947 match a { 947 match a {
948 // foo bar baz 948 // foo bar baz
949 A::One => {} 949 A::One => {}
950 $0A::Two => {} 950 $0A::Two => todo!(),
951 // This is where the rest should be 951 // This is where the rest should be
952 } 952 }
953} 953}
@@ -971,8 +971,8 @@ fn foo(a: A) {
971enum A { One, Two } 971enum A { One, Two }
972fn foo(a: A) { 972fn foo(a: A) {
973 match a { 973 match a {
974 $0A::One => {} 974 $0A::One => todo!(),
975 A::Two => {} 975 A::Two => todo!(),
976 // foo bar baz 976 // foo bar baz
977 } 977 }
978} 978}
@@ -996,8 +996,8 @@ fn foo(a: A) {
996enum A { One, Two, } 996enum A { One, Two, }
997fn foo(a: A) { 997fn foo(a: A) {
998 match a { 998 match a {
999 $0A::One => {} 999 $0A::One => todo!(),
1000 A::Two => {} 1000 A::Two => todo!(),
1001 } 1001 }
1002} 1002}
1003"#, 1003"#,
@@ -1021,8 +1021,8 @@ fn foo(opt: Option<i32>) {
1021 r#" 1021 r#"
1022fn foo(opt: Option<i32>) { 1022fn foo(opt: Option<i32>) {
1023 match opt { 1023 match opt {
1024 Some(${0:_}) => {} 1024 Some(${0:_}) => todo!(),
1025 None => {} 1025 None => todo!(),
1026 } 1026 }
1027} 1027}
1028"#, 1028"#,
@@ -1054,9 +1054,9 @@ enum Test {
1054 1054
1055fn foo(t: Test) { 1055fn foo(t: Test) {
1056 m!(match t { 1056 m!(match t {
1057 $0Test::A => {} 1057 $0Test::A => todo!(),
1058 Test::B => {} 1058 Test::B => todo!(),
1059 Test::C => {} 1059 Test::C => todo!(),
1060}); 1060});
1061}"#, 1061}"#,
1062 ); 1062 );
@@ -1076,4 +1076,44 @@ fn foo(tuple: (A, A)) {
1076"#, 1076"#,
1077 ); 1077 );
1078 } 1078 }
1079
1080 #[test]
1081 fn adds_comma_before_new_arms() {
1082 check_assist(
1083 fill_match_arms,
1084 r#"
1085fn foo(t: bool) {
1086 match $0t {
1087 true => 1 + 2
1088 }
1089}"#,
1090 r#"
1091fn foo(t: bool) {
1092 match t {
1093 true => 1 + 2,
1094 $0false => todo!(),
1095 }
1096}"#,
1097 );
1098 }
1099
1100 #[test]
1101 fn does_not_add_extra_comma() {
1102 check_assist(
1103 fill_match_arms,
1104 r#"
1105fn foo(t: bool) {
1106 match $0t {
1107 true => 1 + 2,
1108 }
1109}"#,
1110 r#"
1111fn foo(t: bool) {
1112 match t {
1113 true => 1 + 2,
1114 $0false => todo!(),
1115 }
1116}"#,
1117 );
1118 }
1079} 1119}
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 8a9b0777c..de5d9e55a 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -455,8 +455,8 @@ enum Action { Move { distance: u32 }, Stop }
455 455
456fn handle(action: Action) { 456fn handle(action: Action) {
457 match action { 457 match action {
458 $0Action::Move { distance } => {} 458 $0Action::Move { distance } => todo!(),
459 Action::Stop => {} 459 Action::Stop => todo!(),
460 } 460 }
461} 461}
462"#####, 462"#####,
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs
index ca8103668..f7ee29d14 100644
--- a/crates/syntax/src/ast/edit_in_place.rs
+++ b/crates/syntax/src/ast/edit_in_place.rs
@@ -356,13 +356,17 @@ impl ast::MatchArm {
356impl ast::MatchArmList { 356impl ast::MatchArmList {
357 pub fn add_arm(&self, arm: ast::MatchArm) { 357 pub fn add_arm(&self, arm: ast::MatchArm) {
358 normalize_ws_between_braces(self.syntax()); 358 normalize_ws_between_braces(self.syntax());
359 let mut elements = Vec::new();
359 let position = match self.arms().last() { 360 let position = match self.arms().last() {
360 Some(last_arm) => { 361 Some(last_arm) => {
361 let curly = last_arm 362 let comma = last_arm
362 .syntax() 363 .syntax()
363 .siblings_with_tokens(Direction::Next) 364 .siblings_with_tokens(Direction::Next)
364 .find(|it| it.kind() == T![,]); 365 .find(|it| it.kind() == T![,]);
365 Position::after(curly.unwrap_or_else(|| last_arm.syntax().clone().into())) 366 if needs_comma(&last_arm) && comma.is_none() {
367 elements.push(make::token(SyntaxKind::COMMA).into());
368 }
369 Position::after(comma.unwrap_or_else(|| last_arm.syntax().clone().into()))
366 } 370 }
367 None => match self.l_curly_token() { 371 None => match self.l_curly_token() {
368 Some(it) => Position::after(it), 372 Some(it) => Position::after(it),
@@ -370,11 +374,16 @@ impl ast::MatchArmList {
370 }, 374 },
371 }; 375 };
372 let indent = IndentLevel::from_node(self.syntax()) + 1; 376 let indent = IndentLevel::from_node(self.syntax()) + 1;
373 let elements = vec![ 377 elements.push(make::tokens::whitespace(&format!("\n{}", indent)).into());
374 make::tokens::whitespace(&format!("\n{}", indent)).into(), 378 elements.push(arm.syntax().clone().into());
375 arm.syntax().clone().into(), 379 if needs_comma(&arm) {
376 ]; 380 elements.push(make::token(SyntaxKind::COMMA).into());
381 }
377 ted::insert_all(position, elements); 382 ted::insert_all(position, elements);
383
384 fn needs_comma(arm: &ast::MatchArm) -> bool {
385 arm.expr().map_or(false, |e| !e.is_block_like())
386 }
378 } 387 }
379} 388}
380 389
diff --git a/xtask/src/tidy.rs b/xtask/src/tidy.rs
index 82b33a7a0..6f687a788 100644
--- a/xtask/src/tidy.rs
+++ b/xtask/src/tidy.rs
@@ -275,6 +275,7 @@ fn check_todo(path: &Path, text: &str) {
275 // Some of our assists generate `todo!()`. 275 // Some of our assists generate `todo!()`.
276 "handlers/add_turbo_fish.rs", 276 "handlers/add_turbo_fish.rs",
277 "handlers/generate_function.rs", 277 "handlers/generate_function.rs",
278 "handlers/fill_match_arms.rs",
278 // To support generating `todo!()` in assists, we have `expr_todo()` in 279 // To support generating `todo!()` in assists, we have `expr_todo()` in
279 // `ast::make`. 280 // `ast::make`.
280 "ast/make.rs", 281 "ast/make.rs",