aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs48
-rw-r--r--crates/ide_assists/src/handlers/fill_match_arms.rs22
-rw-r--r--crates/ide_assists/src/handlers/flip_comma.rs18
-rw-r--r--crates/ide_assists/src/lib.rs2
-rw-r--r--crates/ide_assists/src/tests.rs6
5 files changed, 66 insertions, 30 deletions
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index af9543766..059414274 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -736,6 +736,14 @@ fn reference_is_exclusive(
736 736
737/// checks if this expr requires `&mut` access, recurses on field access 737/// checks if this expr requires `&mut` access, recurses on field access
738fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Option<bool> { 738fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Option<bool> {
739 match expr {
740 ast::Expr::MacroCall(_) => {
741 // FIXME: expand macro and check output for mutable usages of the variable?
742 return None;
743 }
744 _ => (),
745 }
746
739 let parent = expr.syntax().parent()?; 747 let parent = expr.syntax().parent()?;
740 748
741 if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) { 749 if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) {
@@ -794,7 +802,7 @@ impl HasTokenAtOffset for SyntaxNode {
794 } 802 }
795} 803}
796 804
797/// find relevant `ast::PathExpr` for reference 805/// find relevant `ast::Expr` for reference
798/// 806///
799/// # Preconditions 807/// # Preconditions
800/// 808///
@@ -811,7 +819,11 @@ fn path_element_of_reference(
811 stdx::never!(false, "cannot find path parent of variable usage: {:?}", token); 819 stdx::never!(false, "cannot find path parent of variable usage: {:?}", token);
812 None 820 None
813 })?; 821 })?;
814 stdx::always!(matches!(path, ast::Expr::PathExpr(_))); 822 stdx::always!(
823 matches!(path, ast::Expr::PathExpr(_) | ast::Expr::MacroCall(_)),
824 "unexpected expression type for variable usage: {:?}",
825 path
826 );
815 Some(path) 827 Some(path)
816} 828}
817 829
@@ -3462,4 +3474,36 @@ fn foo() -> Result<(), i64> {
3462}"##, 3474}"##,
3463 ); 3475 );
3464 } 3476 }
3477
3478 #[test]
3479 fn param_usage_in_macro() {
3480 check_assist(
3481 extract_function,
3482 r"
3483macro_rules! m {
3484 ($val:expr) => { $val };
3485}
3486
3487fn foo() {
3488 let n = 1;
3489 $0let k = n * m!(n);$0
3490 let m = k + 1;
3491}",
3492 r"
3493macro_rules! m {
3494 ($val:expr) => { $val };
3495}
3496
3497fn foo() {
3498 let n = 1;
3499 let k = fun_name(n);
3500 let m = k + 1;
3501}
3502
3503fn $0fun_name(n: i32) -> i32 {
3504 let k = n * m!(n);
3505 k
3506}",
3507 );
3508 }
3465} 3509}
diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs
index 878b3a3fa..80bd1b7e8 100644
--- a/crates/ide_assists/src/handlers/fill_match_arms.rs
+++ b/crates/ide_assists/src/handlers/fill_match_arms.rs
@@ -71,12 +71,6 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
71 return None; 71 return None;
72 } 72 }
73 73
74 // We do not currently support filling match arms for a tuple
75 // containing a single enum.
76 if enum_defs.len() < 2 {
77 return None;
78 }
79
80 // When calculating the match arms for a tuple of enums, we want 74 // When calculating the match arms for a tuple of enums, we want
81 // to create a match arm for each possible combination of enum 75 // to create a match arm for each possible combination of enum
82 // values. The `multi_cartesian_product` method transforms 76 // values. The `multi_cartesian_product` method transforms
@@ -514,10 +508,7 @@ fn main() {
514 508
515 #[test] 509 #[test]
516 fn fill_match_arms_single_element_tuple_of_enum() { 510 fn fill_match_arms_single_element_tuple_of_enum() {
517 // For now we don't hande the case of a single element tuple, but 511 check_assist(
518 // we could handle this in the future if `make::tuple_pat` allowed
519 // creating a tuple with a single pattern.
520 check_assist_not_applicable(
521 fill_match_arms, 512 fill_match_arms,
522 r#" 513 r#"
523 enum A { One, Two } 514 enum A { One, Two }
@@ -528,6 +519,17 @@ fn main() {
528 } 519 }
529 } 520 }
530 "#, 521 "#,
522 r#"
523 enum A { One, Two }
524
525 fn main() {
526 let a = A::One;
527 match (a, ) {
528 $0(A::One,) => {}
529 (A::Two,) => {}
530 }
531 }
532 "#,
531 ); 533 );
532 } 534 }
533 535
diff --git a/crates/ide_assists/src/handlers/flip_comma.rs b/crates/ide_assists/src/handlers/flip_comma.rs
index 7f5e75d34..99be5e090 100644
--- a/crates/ide_assists/src/handlers/flip_comma.rs
+++ b/crates/ide_assists/src/handlers/flip_comma.rs
@@ -66,26 +66,12 @@ mod tests {
66 } 66 }
67 67
68 #[test] 68 #[test]
69 #[should_panic]
70 fn flip_comma_before_punct() { 69 fn flip_comma_before_punct() {
71 // See https://github.com/rust-analyzer/rust-analyzer/issues/1619 70 // See https://github.com/rust-analyzer/rust-analyzer/issues/1619
72 // "Flip comma" assist shouldn't be applicable to the last comma in enum or struct 71 // "Flip comma" assist shouldn't be applicable to the last comma in enum or struct
73 // declaration body. 72 // declaration body.
74 check_assist_target( 73 check_assist_not_applicable(flip_comma, "pub enum Test { A,$0 }");
75 flip_comma, 74 check_assist_not_applicable(flip_comma, "pub struct Test { foo: usize,$0 }");
76 "pub enum Test { \
77 A,$0 \
78 }",
79 ",",
80 );
81
82 check_assist_target(
83 flip_comma,
84 "pub struct Test { \
85 foo: usize,$0 \
86 }",
87 ",",
88 );
89 } 75 }
90 76
91 #[test] 77 #[test]
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index d6a083e1a..8996c1b61 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -28,7 +28,9 @@ pub use assist_config::AssistConfig;
28 28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)] 29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum AssistKind { 30pub enum AssistKind {
31 // FIXME: does the None variant make sense? Probably not.
31 None, 32 None,
33
32 QuickFix, 34 QuickFix,
33 Generate, 35 Generate,
34 Refactor, 36 Refactor,
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index 6f25d3227..49533e7d2 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -84,7 +84,8 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
84 }); 84 });
85 85
86 let actual = { 86 let actual = {
87 let source_change = assist.source_change.unwrap(); 87 let source_change =
88 assist.source_change.expect("Assist did not contain any source changes");
88 let mut actual = before; 89 let mut actual = before;
89 if let Some(source_file_edit) = source_change.get_source_edit(file_id) { 90 if let Some(source_file_edit) = source_change.get_source_edit(file_id) {
90 source_file_edit.apply(&mut actual); 91 source_file_edit.apply(&mut actual);
@@ -121,7 +122,8 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
121 122
122 match (assist, expected) { 123 match (assist, expected) {
123 (Some(assist), ExpectedResult::After(after)) => { 124 (Some(assist), ExpectedResult::After(after)) => {
124 let source_change = assist.source_change.unwrap(); 125 let source_change =
126 assist.source_change.expect("Assist did not contain any source changes");
125 assert!(!source_change.source_file_edits.is_empty()); 127 assert!(!source_change.source_file_edits.is_empty());
126 let skip_header = source_change.source_file_edits.len() == 1 128 let skip_header = source_change.source_file_edits.len() == 1
127 && source_change.file_system_edits.len() == 0; 129 && source_change.file_system_edits.len() == 0;