| 
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