Skip to content

Commit

Permalink
Auto merge of rust-lang#14863 - lowr:fix/extract-fn-nested-tt, r=lnicola
Browse files Browse the repository at this point in the history
fix: consider all tokens in macro expr when analyzing locals

Fixes rust-lang#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.
  • Loading branch information
bors committed May 21, 2023
2 parents a04d845 + 7b70988 commit 7ac161c
Showing 1 changed file with 86 additions and 7 deletions.
93 changes: 86 additions & 7 deletions crates/ide-assists/src/handlers/extract_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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)));
}
}
_ => (),
Expand Down Expand Up @@ -4344,6 +4347,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(
Expand Down

0 comments on commit 7ac161c

Please sign in to comment.