diff options
Diffstat (limited to 'crates/ide_db')
-rw-r--r-- | crates/ide_db/src/helpers/insert_use.rs | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs index 4da058cb2..e6b4832e7 100644 --- a/crates/ide_db/src/helpers/insert_use.rs +++ b/crates/ide_db/src/helpers/insert_use.rs | |||
@@ -5,7 +5,7 @@ use hir::Semantics; | |||
5 | use syntax::{ | 5 | use syntax::{ |
6 | algo, | 6 | algo, |
7 | ast::{self, make, AstNode, AttrsOwner, ModuleItemOwner, PathSegmentKind, VisibilityOwner}, | 7 | ast::{self, make, AstNode, AttrsOwner, ModuleItemOwner, PathSegmentKind, VisibilityOwner}, |
8 | ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken, | 8 | match_ast, ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
@@ -43,16 +43,32 @@ pub struct InsertUseConfig { | |||
43 | pub enum ImportScope { | 43 | pub enum ImportScope { |
44 | File(ast::SourceFile), | 44 | File(ast::SourceFile), |
45 | Module(ast::ItemList), | 45 | Module(ast::ItemList), |
46 | Block(ast::BlockExpr), | ||
46 | } | 47 | } |
47 | 48 | ||
48 | impl ImportScope { | 49 | impl ImportScope { |
49 | pub fn from(syntax: SyntaxNode) -> Option<Self> { | 50 | fn from(syntax: SyntaxNode) -> Option<Self> { |
50 | if let Some(module) = ast::Module::cast(syntax.clone()) { | 51 | fn contains_cfg_attr(attrs: &dyn AttrsOwner) -> bool { |
51 | module.item_list().map(ImportScope::Module) | 52 | attrs |
52 | } else if let this @ Some(_) = ast::SourceFile::cast(syntax.clone()) { | 53 | .attrs() |
53 | this.map(ImportScope::File) | 54 | .any(|attr| attr.as_simple_call().map_or(false, |(ident, _)| ident == "cfg")) |
54 | } else { | 55 | } |
55 | ast::ItemList::cast(syntax).map(ImportScope::Module) | 56 | match_ast! { |
57 | match syntax { | ||
58 | ast::Module(module) => module.item_list().map(ImportScope::Module), | ||
59 | ast::SourceFile(file) => Some(ImportScope::File(file)), | ||
60 | ast::Fn(func) => contains_cfg_attr(&func).then(|| func.body().map(ImportScope::Block)).flatten(), | ||
61 | ast::Const(konst) => contains_cfg_attr(&konst).then(|| match konst.body()? { | ||
62 | ast::Expr::BlockExpr(block) => Some(block), | ||
63 | _ => None, | ||
64 | }).flatten().map(ImportScope::Block), | ||
65 | ast::Static(statik) => contains_cfg_attr(&statik).then(|| match statik.body()? { | ||
66 | ast::Expr::BlockExpr(block) => Some(block), | ||
67 | _ => None, | ||
68 | }).flatten().map(ImportScope::Block), | ||
69 | _ => None, | ||
70 | |||
71 | } | ||
56 | } | 72 | } |
57 | } | 73 | } |
58 | 74 | ||
@@ -73,6 +89,7 @@ impl ImportScope { | |||
73 | match self { | 89 | match self { |
74 | ImportScope::File(file) => file.syntax(), | 90 | ImportScope::File(file) => file.syntax(), |
75 | ImportScope::Module(item_list) => item_list.syntax(), | 91 | ImportScope::Module(item_list) => item_list.syntax(), |
92 | ImportScope::Block(block) => block.syntax(), | ||
76 | } | 93 | } |
77 | } | 94 | } |
78 | 95 | ||
@@ -80,6 +97,7 @@ impl ImportScope { | |||
80 | match self { | 97 | match self { |
81 | ImportScope::File(file) => ImportScope::File(file.clone_for_update()), | 98 | ImportScope::File(file) => ImportScope::File(file.clone_for_update()), |
82 | ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()), | 99 | ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()), |
100 | ImportScope::Block(block) => ImportScope::Block(block.clone_for_update()), | ||
83 | } | 101 | } |
84 | } | 102 | } |
85 | 103 | ||
@@ -96,6 +114,7 @@ impl ImportScope { | |||
96 | let mut use_stmts = match self { | 114 | let mut use_stmts = match self { |
97 | ImportScope::File(f) => f.items(), | 115 | ImportScope::File(f) => f.items(), |
98 | ImportScope::Module(m) => m.items(), | 116 | ImportScope::Module(m) => m.items(), |
117 | ImportScope::Block(b) => b.items(), | ||
99 | } | 118 | } |
100 | .filter_map(use_stmt); | 119 | .filter_map(use_stmt); |
101 | let mut res = ImportGranularityGuess::Unknown; | 120 | let mut res = ImportGranularityGuess::Unknown; |
@@ -319,28 +338,29 @@ fn insert_use_( | |||
319 | ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline()); | 338 | ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline()); |
320 | return; | 339 | return; |
321 | } | 340 | } |
322 | match scope { | 341 | let l_curly = match scope { |
323 | ImportScope::File(_) => { | 342 | ImportScope::File(_) => { |
324 | cov_mark::hit!(insert_group_empty_file); | 343 | cov_mark::hit!(insert_group_empty_file); |
325 | ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); | 344 | ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); |
326 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()) | 345 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()); |
346 | return; | ||
327 | } | 347 | } |
348 | // don't insert the imports before the item list/block expr's opening curly brace | ||
349 | ImportScope::Module(item_list) => item_list.l_curly_token(), | ||
328 | // don't insert the imports before the item list's opening curly brace | 350 | // don't insert the imports before the item list's opening curly brace |
329 | ImportScope::Module(item_list) => match item_list.l_curly_token() { | 351 | ImportScope::Block(block) => block.l_curly_token(), |
330 | Some(b) => { | 352 | }; |
331 | cov_mark::hit!(insert_group_empty_module); | 353 | match l_curly { |
332 | ted::insert(ted::Position::after(&b), make::tokens::single_newline()); | 354 | Some(b) => { |
333 | ted::insert(ted::Position::after(&b), use_item.syntax()); | 355 | cov_mark::hit!(insert_group_empty_module); |
334 | } | 356 | ted::insert(ted::Position::after(&b), make::tokens::single_newline()); |
335 | None => { | 357 | ted::insert(ted::Position::after(&b), use_item.syntax()); |
336 | // This should never happens, broken module syntax node | 358 | } |
337 | ted::insert( | 359 | None => { |
338 | ted::Position::first_child_of(scope_syntax), | 360 | // This should never happens, broken module syntax node |
339 | make::tokens::blank_line(), | 361 | ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); |
340 | ); | 362 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()); |
341 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()); | 363 | } |
342 | } | ||
343 | }, | ||
344 | } | 364 | } |
345 | } | 365 | } |
346 | 366 | ||