use syntax::{
- algo::SyntaxRewriter,
- ast::{self, edit::AstNodeEdit, VisibilityOwner},
+ ast::{self, make, HasVisibility},
+ ted::{self, Position},
AstNode, SyntaxKind,
};
// use std::fmt::Display;
// ```
pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
- let tree: ast::UseTree = ctx.find_node_at_offset()?;
+ let tree: ast::UseTree = ctx.find_node_at_offset::<ast::UseTree>()?.clone_for_update();
let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
if tree_list.use_trees().count() < 2 {
let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
let path = resolve_full_path(&tree)?;
+ let old_parent_range = use_.syntax().parent()?.text_range();
+ let new_parent = use_.syntax().parent()?;
+
let target = tree.syntax().text_range();
acc.add(
AssistId("unmerge_use", AssistKind::RefactorRewrite),
"Unmerge use",
target,
|builder| {
- let new_use = ast::make::use_(
+ let new_use = make::use_(
use_.visibility(),
- ast::make::use_tree(
+ make::use_tree(
path,
tree.use_tree_list(),
tree.rename(),
tree.star_token().is_some(),
),
- );
-
- let mut rewriter = SyntaxRewriter::default();
- rewriter += tree.remove();
- rewriter.insert_after(use_.syntax(), &ast::make::tokens::single_newline());
- if let ident_level @ 1..=usize::MAX = use_.indent_level().0 as usize {
- rewriter.insert_after(
- use_.syntax(),
- &ast::make::tokens::whitespace(&" ".repeat(4 * ident_level)),
- );
- }
- rewriter.insert_after(use_.syntax(), new_use.syntax());
-
- builder.rewrite(rewriter);
+ )
+ .clone_for_update();
+
+ tree.remove();
+ ted::insert(Position::after(use_.syntax()), new_use.syntax());
+
+ builder.replace(old_parent_range, new_parent.to_string());
},
)
}
fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
- let mut paths = tree
+ let paths = tree
.syntax()
.ancestors()
- .take_while(|n| n.kind() != SyntaxKind::USE_KW)
+ .take_while(|n| n.kind() != SyntaxKind::USE)
.filter_map(ast::UseTree::cast)
.filter_map(|t| t.path());
- let mut final_path = paths.next()?;
- for path in paths {
- final_path = ast::make::path_concat(path, final_path)
+ let final_path = paths.reduce(|prev, next| make::path_concat(next, prev))?;
+ if final_path.segment().map_or(false, |it| it.self_token().is_some()) {
+ final_path.qualifier()
+ } else {
+ Some(final_path)
}
- Some(final_path)
}
#[cfg(test)]
",
);
}
+
+ #[test]
+ fn unmerge_use_item_on_self() {
+ check_assist(
+ unmerge_use,
+ r"use std::process::{Command, self$0};",
+ r"use std::process::{Command};
+use std::process;",
+ );
+ }
}