diff options
| author | bors <bors@rust-lang.org> | 2023-05-21 12:40:29 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-05-21 12:40:29 +0000 |
| commit | 7ac161ce77dfa31dc39337c2543a1d777e70c16e (patch) | |
| tree | b25477f1987e18f486757c08eae51702ef35be33 | |
| parent | a04d8456be1d289c814846178cc1ff63b4fc297b (diff) | |
| parent | 7b70988d48373f6d43874346c1cbcd15712a88c7 (diff) | |
| download | rust-7ac161ce77dfa31dc39337c2543a1d777e70c16e.tar.gz rust-7ac161ce77dfa31dc39337c2543a1d777e70c16e.zip | |
Auto merge of #14863 - lowr:fix/extract-fn-nested-tt, r=lnicola
fix: consider all tokens in macro expr when analyzing locals Fixes #14687 2 fixes for `extract_function` assist (related closely enough that I squashed into one commit): - Locals in macro expressions have been analyzed only when they are in the top-level token tree the macro call wraps. We should consider all descendant tokens. - `self` in macro expressions haven't been analyzed.
| -rw-r--r-- | crates/ide-assists/src/handlers/extract_function.rs | 93 |
1 files changed, 86 insertions, 7 deletions
diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index 58605f7ed57..c29721b4648 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -707,7 +707,7 @@ impl FunctionBody { ) -> (FxIndexSet<Local>, Option<ast::SelfParam>) { let mut self_param = None; let mut res = FxIndexSet::default(); - let mut cb = |name_ref: Option<_>| { + let mut add_name_if_local = |name_ref: Option<_>| { let local_ref = match name_ref.and_then(|name_ref| NameRefClass::classify(sema, &name_ref)) { Some( @@ -731,21 +731,24 @@ impl FunctionBody { }; self.walk_expr(&mut |expr| match expr { ast::Expr::PathExpr(path_expr) => { - cb(path_expr.path().and_then(|it| it.as_single_name_ref())) + add_name_if_local(path_expr.path().and_then(|it| it.as_single_name_ref())) } ast::Expr::ClosureExpr(closure_expr) => { if let Some(body) = closure_expr.body() { - body.syntax().descendants().map(ast::NameRef::cast).for_each(|it| cb(it)); + body.syntax() + .descendants() + .map(ast::NameRef::cast) + .for_each(&mut add_name_if_local); } } ast::Expr::MacroExpr(expr) => { if let Some(tt) = expr.macro_call().and_then(|call| call.token_tree()) { tt.syntax() - .children_with_tokens() - .flat_map(SyntaxElement::into_token) - .filter(|it| it.kind() == SyntaxKind::IDENT) + .descendants_with_tokens() + .filter_map(SyntaxElement::into_token) + .filter(|it| matches!(it.kind(), SyntaxKind::IDENT | T![self])) .flat_map(|t| sema.descend_into_macros(t)) - .for_each(|t| cb(t.parent().and_then(ast::NameRef::cast))); + .for_each(|t| add_name_if_local(t.parent().and_then(ast::NameRef::cast))); } } _ => (), @@ -4345,6 +4348,82 @@ fn $0fun_name(n: i32) -> i32 { } #[test] + fn param_usage_in_macro_with_nested_tt() { + check_assist( + extract_function, + r#" +macro_rules! m { + ($val:expr) => { $val }; +} + +fn foo() { + let n = 1; + let t = 1; + $0let k = n * m!((n) + { t });$0 + let m = k + 1; +} +"#, + r#" +macro_rules! m { + ($val:expr) => { $val }; +} + +fn foo() { + let n = 1; + let t = 1; + let k = fun_name(n, t); + let m = k + 1; +} + +fn $0fun_name(n: i32, t: i32) -> i32 { + let k = n * m!((n) + { t }); + k +} +"#, + ) + } + + #[test] + fn param_usage_in_macro_with_nested_tt_2() { + check_assist( + extract_function, + r#" +macro_rules! m { + ($val:expr) => { $val }; +} + +struct S(i32); +impl S { + fn foo(&self) { + let n = 1; + $0let k = n * m!((n) + { self.0 });$0 + let m = k + 1; + } +} +"#, + r#" +macro_rules! m { + ($val:expr) => { $val }; +} + +struct S(i32); +impl S { + fn foo(&self) { + let n = 1; + let k = self.fun_name(n); + let m = k + 1; + } + + fn $0fun_name(&self, n: i32) -> i32 { + let k = n * m!((n) + { self.0 }); + k + } +} +"#, + ) + } + + #[test] fn extract_with_await() { check_assist( extract_function, |
