|
1 | 1 | use stdx::format_to; |
2 | 2 | use syntax::{ |
3 | 3 | ast::{self, AstNode}, |
| 4 | + NodeOrToken, |
4 | 5 | SyntaxKind::{ |
5 | 6 | BLOCK_EXPR, BREAK_EXPR, CLOSURE_EXPR, COMMENT, LOOP_EXPR, MATCH_ARM, MATCH_GUARD, |
6 | 7 | PATH_EXPR, RETURN_EXPR, |
@@ -30,20 +31,26 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option |
30 | 31 | if ctx.frange.range.is_empty() { |
31 | 32 | return None; |
32 | 33 | } |
33 | | - let node = ctx.covering_element(); |
34 | | - if node.kind() == COMMENT { |
35 | | - cov_mark::hit!(extract_var_in_comment_is_not_applicable); |
36 | | - return None; |
37 | | - } |
| 34 | + let node = match ctx.covering_element() { |
| 35 | + NodeOrToken::Node(it) => it, |
| 36 | + NodeOrToken::Token(it) if it.kind() == COMMENT => { |
| 37 | + cov_mark::hit!(extract_var_in_comment_is_not_applicable); |
| 38 | + return None; |
| 39 | + } |
| 40 | + NodeOrToken::Token(it) => it.parent()?, |
| 41 | + }; |
| 42 | + let node = node.ancestors().take_while(|anc| anc.text_range() == node.text_range()).last()?; |
38 | 43 | let to_extract = node |
39 | | - .ancestors() |
40 | | - .take_while(|it| it.text_range().contains_range(ctx.frange.range)) |
| 44 | + .descendants() |
| 45 | + .take_while(|it| ctx.frange.range.contains_range(it.text_range())) |
41 | 46 | .find_map(valid_target_expr)?; |
| 47 | + |
42 | 48 | if let Some(ty_info) = ctx.sema.type_of_expr(&to_extract) { |
43 | 49 | if ty_info.adjusted().is_unit() { |
44 | 50 | return None; |
45 | 51 | } |
46 | 52 | } |
| 53 | + |
47 | 54 | let anchor = Anchor::from(&to_extract)?; |
48 | 55 | let indent = anchor.syntax().prev_sibling_or_token()?.as_token()?.clone(); |
49 | 56 | let target = to_extract.syntax().text_range(); |
@@ -146,8 +153,11 @@ enum Anchor { |
146 | 153 |
|
147 | 154 | impl Anchor { |
148 | 155 | fn from(to_extract: &ast::Expr) -> Option<Anchor> { |
149 | | - to_extract.syntax().ancestors().take_while(|it| !ast::Item::can_cast(it.kind())).find_map( |
150 | | - |node| { |
| 156 | + to_extract |
| 157 | + .syntax() |
| 158 | + .ancestors() |
| 159 | + .take_while(|it| !ast::Item::can_cast(it.kind()) || ast::MacroCall::can_cast(it.kind())) |
| 160 | + .find_map(|node| { |
151 | 161 | if let Some(expr) = |
152 | 162 | node.parent().and_then(ast::StmtList::cast).and_then(|it| it.tail_expr()) |
153 | 163 | { |
@@ -181,8 +191,7 @@ impl Anchor { |
181 | 191 | return Some(Anchor::Before(node)); |
182 | 192 | } |
183 | 193 | None |
184 | | - }, |
185 | | - ) |
| 194 | + }) |
186 | 195 | } |
187 | 196 |
|
188 | 197 | fn syntax(&self) -> &SyntaxNode { |
|
0 commit comments