Implement import-granularity guessing
This commit is contained in:
parent
64f7072c25
commit
b8a99692d1
@ -4,7 +4,7 @@
|
|||||||
use hir::Semantics;
|
use hir::Semantics;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
algo,
|
algo,
|
||||||
ast::{self, make, AstNode, PathSegmentKind},
|
ast::{self, make, AstNode, ModuleItemOwner, PathSegmentKind},
|
||||||
ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken,
|
ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -88,15 +88,46 @@ pub fn clone_for_update(&self) -> Self {
|
|||||||
ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()),
|
ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn guess_merge_behavior_from_scope(&self) -> Option<MergeBehavior> {
|
||||||
|
let use_stmt = |item| match item {
|
||||||
|
ast::Item::Use(use_) => use_.use_tree(),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
let use_stmts = match self {
|
||||||
|
ImportScope::File(f) => f.items(),
|
||||||
|
ImportScope::Module(m) => m.items(),
|
||||||
|
}
|
||||||
|
.filter_map(use_stmt);
|
||||||
|
let mut res = None;
|
||||||
|
for tree in use_stmts {
|
||||||
|
if let Some(list) = tree.use_tree_list() {
|
||||||
|
if list.use_trees().any(|tree| tree.use_tree_list().is_some()) {
|
||||||
|
// double nested tree list, can only be a crate style import at this point
|
||||||
|
return Some(MergeBehavior::Crate);
|
||||||
|
}
|
||||||
|
// has to be at least a module style based import, might be crate style tho so look further
|
||||||
|
res = Some(MergeBehavior::Module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
|
/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
|
||||||
pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: InsertUseConfig) {
|
pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: InsertUseConfig) {
|
||||||
let _p = profile::span("insert_use");
|
let _p = profile::span("insert_use");
|
||||||
|
let mb = match cfg.granularity {
|
||||||
|
ImportGranularity::Preserve => scope.guess_merge_behavior_from_scope(),
|
||||||
|
ImportGranularity::Crate => Some(MergeBehavior::Crate),
|
||||||
|
ImportGranularity::Module => Some(MergeBehavior::Module),
|
||||||
|
ImportGranularity::Item => None,
|
||||||
|
};
|
||||||
|
|
||||||
let use_item =
|
let use_item =
|
||||||
make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update();
|
make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update();
|
||||||
// merge into existing imports if possible
|
// merge into existing imports if possible
|
||||||
if let Some(mb) = cfg.granularity.merge_behavior() {
|
if let Some(mb) = mb {
|
||||||
for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) {
|
for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) {
|
||||||
if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) {
|
if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) {
|
||||||
ted::replace(existing_use.syntax(), merged.syntax());
|
ted::replace(existing_use.syntax(), merged.syntax());
|
||||||
|
Loading…
Reference in New Issue
Block a user