|
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