Unnamed repository; edit this file 'description' to name the repository.
remove insert_use and insert_use_as_alias
bit-aloo 3 weeks ago
parent 64cdaeb · commit fabc5f7
-rw-r--r--crates/ide-db/src/imports/insert_use.rs208
1 files changed, 5 insertions, 203 deletions
diff --git a/crates/ide-db/src/imports/insert_use.rs b/crates/ide-db/src/imports/insert_use.rs
index 7402ec8f5a..16eddcbd35 100644
--- a/crates/ide-db/src/imports/insert_use.rs
+++ b/crates/ide-db/src/imports/insert_use.rs
@@ -6,10 +6,11 @@ use std::cmp::Ordering;
use hir::Semantics;
use syntax::{
- Direction, NodeOrToken, SyntaxKind, SyntaxNode, algo,
- ast::{self, AstNode, HasAttrs, HasModuleItem, HasVisibility, PathSegmentKind, make},
+ NodeOrToken, SyntaxKind, SyntaxNode,
+ ast::{
+ self, AstNode, HasAttrs, HasModuleItem, HasVisibility, PathSegmentKind, edit::IndentLevel,
+ },
syntax_editor::{Position, SyntaxEditor},
- ted,
};
use crate::{
@@ -147,24 +148,6 @@ impl ImportScope {
ImportScopeKind::Block(block) => block.syntax(),
}
}
-
- pub fn clone_for_update(&self) -> Self {
- Self {
- kind: match &self.kind {
- ImportScopeKind::File(file) => ImportScopeKind::File(file.clone_for_update()),
- ImportScopeKind::Module(item_list) => {
- ImportScopeKind::Module(item_list.clone_for_update())
- }
- ImportScopeKind::Block(block) => ImportScopeKind::Block(block.clone_for_update()),
- },
- required_cfgs: self.required_cfgs.iter().map(|attr| attr.clone_for_update()).collect(),
- }
- }
-}
-
-/// 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(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) {
- insert_use_with_alias_option(scope, path, cfg, None);
}
/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
@@ -193,71 +176,7 @@ pub fn insert_use_as_alias(
.expect("Failed to make ast node `Rename`");
let alias = node.rename();
- insert_use_with_alias_option(scope, path, cfg, alias);
-}
-
-fn insert_use_with_alias_option(
- scope: &ImportScope,
- path: ast::Path,
- cfg: &InsertUseConfig,
- alias: Option<ast::Rename>,
-) {
- let _p = tracing::info_span!("insert_use_with_alias_option").entered();
- let mut mb = match cfg.granularity {
- ImportGranularity::Crate => Some(MergeBehavior::Crate),
- ImportGranularity::Module => Some(MergeBehavior::Module),
- ImportGranularity::One => Some(MergeBehavior::One),
- ImportGranularity::Item => None,
- };
- if !cfg.enforce_granularity {
- let file_granularity = guess_granularity_from_scope(scope);
- mb = match file_granularity {
- ImportGranularityGuess::Unknown => mb,
- ImportGranularityGuess::Item => None,
- ImportGranularityGuess::Module => Some(MergeBehavior::Module),
- // We use the user's setting to infer if this is module or item.
- ImportGranularityGuess::ModuleOrItem => match mb {
- Some(MergeBehavior::Module) | None => mb,
- // There isn't really a way to decide between module or item here, so we just pick one.
- // FIXME: Maybe it is possible to infer based on semantic analysis?
- Some(MergeBehavior::One | MergeBehavior::Crate) => Some(MergeBehavior::Module),
- },
- ImportGranularityGuess::Crate => Some(MergeBehavior::Crate),
- ImportGranularityGuess::CrateOrModule => match mb {
- Some(MergeBehavior::Crate | MergeBehavior::Module) => mb,
- Some(MergeBehavior::One) | None => Some(MergeBehavior::Crate),
- },
- ImportGranularityGuess::One => Some(MergeBehavior::One),
- };
- }
-
- let mut use_tree = make::use_tree(path, None, alias, false);
- if mb == Some(MergeBehavior::One) && use_tree.path().is_some() {
- use_tree = use_tree.clone_for_update();
- use_tree.wrap_in_tree_list();
- }
- let use_item = make::use_(None, None, use_tree).clone_for_update();
- for attr in
- scope.required_cfgs.iter().map(|attr| attr.syntax().clone_subtree().clone_for_update())
- {
- ted::insert(ted::Position::first_child_of(use_item.syntax()), attr);
- }
-
- // merge into existing imports if possible
- if let Some(mb) = mb {
- let filter = |it: &_| !(cfg.skip_glob_imports && ast::Use::is_simple_glob(it));
- for existing_use in
- scope.as_syntax_node().children().filter_map(ast::Use::cast).filter(filter)
- {
- if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) {
- ted::replace(existing_use.syntax(), merged.syntax());
- return;
- }
- }
- }
- // either we weren't allowed to merge or there is no import that fits the merge conditions
- // so look for the place we have to insert to
- insert_use_(scope, use_item, cfg.group);
+ insert_use_with_alias_option_with_editor(scope, path, cfg, alias, editor);
}
fn insert_use_with_alias_option_with_editor(
@@ -469,123 +388,6 @@ fn guess_granularity_from_scope(scope: &ImportScope) -> ImportGranularityGuess {
}
}
-fn insert_use_(scope: &ImportScope, use_item: ast::Use, group_imports: bool) {
- let scope_syntax = scope.as_syntax_node();
- let insert_use_tree =
- use_item.use_tree().expect("`use_item` should have a use tree for `insert_path`");
- let group = ImportGroup::new(&insert_use_tree);
- let path_node_iter = scope_syntax
- .children()
- .filter_map(|node| ast::Use::cast(node.clone()).zip(Some(node)))
- .flat_map(|(use_, node)| {
- let tree = use_.use_tree()?;
- Some((tree, node))
- });
-
- if group_imports {
- // Iterator that discards anything that's not in the required grouping
- // This implementation allows the user to rearrange their import groups as this only takes the first group that fits
- let group_iter = path_node_iter
- .clone()
- .skip_while(|(use_tree, ..)| ImportGroup::new(use_tree) != group)
- .take_while(|(use_tree, ..)| ImportGroup::new(use_tree) == group);
-
- // track the last element we iterated over, if this is still None after the iteration then that means we never iterated in the first place
- let mut last = None;
- // find the element that would come directly after our new import
- let post_insert: Option<(_, SyntaxNode)> = group_iter
- .inspect(|(.., node)| last = Some(node.clone()))
- .find(|(use_tree, _)| use_tree_cmp(&insert_use_tree, use_tree) != Ordering::Greater);
-
- if let Some((.., node)) = post_insert {
- cov_mark::hit!(insert_group);
- // insert our import before that element
- return ted::insert(ted::Position::before(node), use_item.syntax());
- }
- if let Some(node) = last {
- cov_mark::hit!(insert_group_last);
- // there is no element after our new import, so append it to the end of the group
- return ted::insert(ted::Position::after(node), use_item.syntax());
- }
-
- // the group we were looking for actually doesn't exist, so insert
-
- let mut last = None;
- // find the group that comes after where we want to insert
- let post_group = path_node_iter
- .inspect(|(.., node)| last = Some(node.clone()))
- .find(|(use_tree, ..)| ImportGroup::new(use_tree) > group);
- if let Some((.., node)) = post_group {
- cov_mark::hit!(insert_group_new_group);
- ted::insert(ted::Position::before(&node), use_item.syntax());
- if let Some(node) = algo::non_trivia_sibling(node.into(), Direction::Prev) {
- ted::insert(ted::Position::after(node), make::tokens::single_newline());
- }
- return;
- }
- // there is no such group, so append after the last one
- if let Some(node) = last {
- cov_mark::hit!(insert_group_no_group);
- ted::insert(ted::Position::after(&node), use_item.syntax());
- ted::insert(ted::Position::after(node), make::tokens::single_newline());
- return;
- }
- } else {
- // There exists a group, so append to the end of it
- if let Some((_, node)) = path_node_iter.last() {
- cov_mark::hit!(insert_no_grouping_last);
- ted::insert(ted::Position::after(node), use_item.syntax());
- return;
- }
- }
-
- let l_curly = match &scope.kind {
- ImportScopeKind::File(_) => None,
- // don't insert the imports before the item list/block expr's opening curly brace
- ImportScopeKind::Module(item_list) => item_list.l_curly_token(),
- // don't insert the imports before the item list's opening curly brace
- ImportScopeKind::Block(block) => block.l_curly_token(),
- };
- // there are no imports in this file at all
- // so put the import after all inner module attributes and possible license header comments
- if let Some(last_inner_element) = scope_syntax
- .children_with_tokens()
- // skip the curly brace
- .skip(l_curly.is_some() as usize)
- .take_while(|child| match child {
- NodeOrToken::Node(node) => {
- is_inner_attribute(node.clone()) && ast::Item::cast(node.clone()).is_none()
- }
- NodeOrToken::Token(token) => {
- [SyntaxKind::WHITESPACE, SyntaxKind::COMMENT, SyntaxKind::SHEBANG]
- .contains(&token.kind())
- }
- })
- .filter(|child| child.as_token().is_none_or(|t| t.kind() != SyntaxKind::WHITESPACE))
- .last()
- {
- cov_mark::hit!(insert_empty_inner_attr);
- ted::insert(ted::Position::after(&last_inner_element), use_item.syntax());
- ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline());
- } else {
- match l_curly {
- Some(b) => {
- cov_mark::hit!(insert_empty_module);
- ted::insert(ted::Position::after(&b), make::tokens::single_newline());
- ted::insert(ted::Position::after(&b), use_item.syntax());
- }
- None => {
- cov_mark::hit!(insert_empty_file);
- ted::insert(
- ted::Position::first_child_of(scope_syntax),
- make::tokens::blank_line(),
- );
- ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
- }
- }
- }
-}
-
fn insert_use_with_editor_(
scope: &ImportScope,
use_item: ast::Use,