about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-19 15:16:02 +0000
committerbors <bors@rust-lang.org>2024-07-19 15:16:02 +0000
commitd16acea62cec60642fb5fc71437de54a412cf492 (patch)
treec2398d797bccd45c5fdd0b2dcc5920ecd5a05179
parentfd240c00e0b1ded479ee43f599712e58276ca962 (diff)
parent9dcd4ba0ef179433eef35d8dac79c9f3f5d24e96 (diff)
downloadrust-d16acea62cec60642fb5fc71437de54a412cf492.tar.gz
rust-d16acea62cec60642fb5fc71437de54a412cf492.zip
Auto merge of #17622 - roife:fix-issue-17602, r=Veykril
fix: handle synonymous imports with different renaming in 'merge imports'

fix #17602
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs69
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs18
2 files changed, 82 insertions, 5 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
index 7f751c93e48..41712308369 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
@@ -164,6 +164,7 @@ impl Merge for ast::UseTree {
     }
 }
 
+#[derive(Debug)]
 enum Edit {
     Remove(Either<ast::Use, ast::UseTree>),
     Replace(SyntaxNode, SyntaxNode),
@@ -733,4 +734,72 @@ use std::{
             r"use std::fmt::{Debug, Display};",
         );
     }
+
+    #[test]
+    fn test_merge_with_synonymous_imports_1() {
+        check_assist(
+            merge_imports,
+            r"
+mod top {
+    pub(crate) mod a {
+        pub(crate) struct A;
+    }
+    pub(crate) mod b {
+        pub(crate) struct B;
+        pub(crate) struct D;
+    }
+}
+
+use top::a::A;
+use $0top::b::{B, B as C};
+",
+            r"
+mod top {
+    pub(crate) mod a {
+        pub(crate) struct A;
+    }
+    pub(crate) mod b {
+        pub(crate) struct B;
+        pub(crate) struct D;
+    }
+}
+
+use top::{a::A, b::{B, B as C}};
+",
+        );
+    }
+
+    #[test]
+    fn test_merge_with_synonymous_imports_2() {
+        check_assist(
+            merge_imports,
+            r"
+mod top {
+    pub(crate) mod a {
+        pub(crate) struct A;
+    }
+    pub(crate) mod b {
+        pub(crate) struct B;
+        pub(crate) struct D;
+    }
+}
+
+use top::a::A;
+use $0top::b::{B as D, B as C};
+",
+            r"
+mod top {
+    pub(crate) mod a {
+        pub(crate) struct A;
+    }
+    pub(crate) mod b {
+        pub(crate) struct B;
+        pub(crate) struct D;
+    }
+}
+
+use top::{a::A, b::{B as D, B as C}};
+",
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs
index 9cacb6b1a60..926fae0d317 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs
@@ -93,17 +93,25 @@ fn try_merge_trees_mut(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehav
         let rhs_path = rhs.path()?;
 
         let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?;
-        if !(lhs.is_simple_path()
+        if lhs.is_simple_path()
             && rhs.is_simple_path()
             && lhs_path == lhs_prefix
-            && rhs_path == rhs_prefix)
+            && rhs_path == rhs_prefix
         {
-            lhs.split_prefix(&lhs_prefix);
-            rhs.split_prefix(&rhs_prefix);
-        } else {
+            // we can't merge if the renames are different (`A as a` and `A as b`),
+            // and we can safely return here
+            let lhs_name = lhs.rename().and_then(|lhs_name| lhs_name.name());
+            let rhs_name = rhs.rename().and_then(|rhs_name| rhs_name.name());
+            if lhs_name != rhs_name {
+                return None;
+            }
+
             ted::replace(lhs.syntax(), rhs.syntax());
             // we can safely return here, in this case `recursive_merge` doesn't do anything
             return Some(());
+        } else {
+            lhs.split_prefix(&lhs_prefix);
+            rhs.split_prefix(&rhs_prefix);
         }
     }
     recursive_merge(lhs, rhs, merge)