aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_db/src/helpers')
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs70
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;
5use syntax::{ 5use 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
11use crate::{ 11use crate::{
@@ -43,16 +43,32 @@ pub struct InsertUseConfig {
43pub enum ImportScope { 43pub 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
48impl ImportScope { 49impl 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