diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ide_db/src/helpers/insert_use.rs | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs index a4eb31815..4852121a1 100644 --- a/crates/ide_db/src/helpers/insert_use.rs +++ b/crates/ide_db/src/helpers/insert_use.rs | |||
@@ -4,7 +4,7 @@ use std::cmp::Ordering; | |||
4 | use hir::Semantics; | 4 | use hir::Semantics; |
5 | use syntax::{ | 5 | use syntax::{ |
6 | algo, | 6 | algo, |
7 | ast::{self, make, AstNode, PathSegmentKind}, | 7 | ast::{self, make, AstNode, ModuleItemOwner, PathSegmentKind}, |
8 | ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken, | 8 | ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken, |
9 | }; | 9 | }; |
10 | 10 | ||
@@ -88,15 +88,46 @@ impl ImportScope { | |||
88 | ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()), | 88 | ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()), |
89 | } | 89 | } |
90 | } | 90 | } |
91 | |||
92 | fn guess_merge_behavior_from_scope(&self) -> Option<MergeBehavior> { | ||
93 | let use_stmt = |item| match item { | ||
94 | ast::Item::Use(use_) => use_.use_tree(), | ||
95 | _ => None, | ||
96 | }; | ||
97 | let use_stmts = match self { | ||
98 | ImportScope::File(f) => f.items(), | ||
99 | ImportScope::Module(m) => m.items(), | ||
100 | } | ||
101 | .filter_map(use_stmt); | ||
102 | let mut res = None; | ||
103 | for tree in use_stmts { | ||
104 | if let Some(list) = tree.use_tree_list() { | ||
105 | if list.use_trees().any(|tree| tree.use_tree_list().is_some()) { | ||
106 | // double nested tree list, can only be a crate style import at this point | ||
107 | return Some(MergeBehavior::Crate); | ||
108 | } | ||
109 | // has to be at least a module style based import, might be crate style tho so look further | ||
110 | res = Some(MergeBehavior::Module); | ||
111 | } | ||
112 | } | ||
113 | res | ||
114 | } | ||
91 | } | 115 | } |
92 | 116 | ||
93 | /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. | 117 | /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. |
94 | pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: InsertUseConfig) { | 118 | pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: InsertUseConfig) { |
95 | let _p = profile::span("insert_use"); | 119 | let _p = profile::span("insert_use"); |
120 | let mb = match cfg.granularity { | ||
121 | ImportGranularity::Preserve => scope.guess_merge_behavior_from_scope(), | ||
122 | ImportGranularity::Crate => Some(MergeBehavior::Crate), | ||
123 | ImportGranularity::Module => Some(MergeBehavior::Module), | ||
124 | ImportGranularity::Item => None, | ||
125 | }; | ||
126 | |||
96 | let use_item = | 127 | let use_item = |
97 | make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update(); | 128 | make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update(); |
98 | // merge into existing imports if possible | 129 | // merge into existing imports if possible |
99 | if let Some(mb) = cfg.granularity.merge_behavior() { | 130 | if let Some(mb) = mb { |
100 | for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) { | 131 | for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) { |
101 | if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) { | 132 | if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) { |
102 | ted::replace(existing_use.syntax(), merged.syntax()); | 133 | ted::replace(existing_use.syntax(), merged.syntax()); |