]> git.lizzy.rs Git - rust.git/blobdiff - crates/ide_assists/src/handlers/unmerge_use.rs
Merge #11481
[rust.git] / crates / ide_assists / src / handlers / unmerge_use.rs
index 616af7c2e6ea13551e462da5cd1ac4015bd14da1..7d73632c7994537bed365a827d2b4fc6981872e9 100644 (file)
@@ -1,6 +1,6 @@
 use syntax::{
-    algo::SyntaxRewriter,
-    ast::{self, edit::AstNodeEdit, VisibilityOwner},
+    ast::{self, make, HasVisibility},
+    ted::{self, Position},
     AstNode, SyntaxKind,
 };
 
@@ -22,7 +22,7 @@
 // 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 {
@@ -33,51 +33,48 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
     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)]
@@ -227,4 +224,14 @@ fn unmerge_use_item_with_visibility() {
 ",
         );
     }
+
+    #[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;",
+        );
+    }
 }