Skip to content

Commit b874721

Browse files
committed
Fix merge imports failing if the self module import is in the wrong tree
1 parent cd6cd91 commit b874721

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

crates/assists/src/utils/insert_use.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -149,31 +149,31 @@ fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -
149149
}
150150

151151
pub(crate) fn try_merge_imports(
152-
old: &ast::Use,
153-
new: &ast::Use,
152+
lhs: &ast::Use,
153+
rhs: &ast::Use,
154154
merge_behaviour: MergeBehaviour,
155155
) -> Option<ast::Use> {
156156
// don't merge imports with different visibilities
157-
if !eq_visibility(old.visibility(), new.visibility()) {
157+
if !eq_visibility(lhs.visibility(), rhs.visibility()) {
158158
return None;
159159
}
160-
let old_tree = old.use_tree()?;
161-
let new_tree = new.use_tree()?;
162-
let merged = try_merge_trees(&old_tree, &new_tree, merge_behaviour)?;
163-
Some(old.with_use_tree(merged))
160+
let lhs_tree = lhs.use_tree()?;
161+
let rhs_tree = rhs.use_tree()?;
162+
let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behaviour)?;
163+
Some(lhs.with_use_tree(merged))
164164
}
165165

166166
pub(crate) fn try_merge_trees(
167-
old: &ast::UseTree,
168-
new: &ast::UseTree,
167+
lhs: &ast::UseTree,
168+
rhs: &ast::UseTree,
169169
merge: MergeBehaviour,
170170
) -> Option<ast::UseTree> {
171-
let lhs_path = old.path()?;
172-
let rhs_path = new.path()?;
171+
let lhs_path = lhs.path()?;
172+
let rhs_path = rhs.path()?;
173173

174174
let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?;
175-
let lhs = old.split_prefix(&lhs_prefix);
176-
let rhs = new.split_prefix(&rhs_prefix);
175+
let lhs = lhs.split_prefix(&lhs_prefix);
176+
let rhs = rhs.split_prefix(&rhs_prefix);
177177
recursive_merge(&lhs, &rhs, merge).map(|(merged, _)| merged)
178178
}
179179

@@ -209,13 +209,18 @@ fn recursive_merge(
209209
};
210210
// check if only one of the two trees has a tree list, and whether that then contains `self` or not.
211211
// If this is the case we can skip this iteration since the path without the list is already included in the other one via `self`
212-
if lhs_t
213-
.use_tree_list()
214-
.xor(rhs_t.use_tree_list())
215-
.map(|tree_list| tree_list.use_trees().any(tree_is_self))
216-
.unwrap_or(false)
217-
{
218-
continue;
212+
let tree_contains_self = |tree: &ast::UseTree| {
213+
tree.use_tree_list()
214+
.map(|tree_list| tree_list.use_trees().any(tree_is_self))
215+
.unwrap_or(false)
216+
};
217+
match (tree_contains_self(&lhs_t), tree_contains_self(&rhs_t)) {
218+
(true, false) => continue,
219+
(false, true) => {
220+
*lhs_t = rhs_t;
221+
continue;
222+
}
223+
_ => (),
219224
}
220225

221226
// glob imports arent part of the use-tree lists so we need to special handle them here as well
@@ -255,6 +260,13 @@ fn recursive_merge(
255260
None => use_trees.insert(idx, rhs_t),
256261
}
257262
}
263+
Err(_)
264+
if merge == MergeBehaviour::Last
265+
&& use_trees.len() > 0
266+
&& rhs_t.use_tree_list().is_some() =>
267+
{
268+
return None
269+
}
258270
Err(idx) => {
259271
use_trees.insert(idx, rhs_t);
260272
}
@@ -819,8 +831,8 @@ use std::io;",
819831
fn merge_glob_nested() {
820832
check_full(
821833
"foo::bar::quux::Fez",
822-
r"use foo::bar::{Baz, quux::*;",
823-
r"use foo::bar::{Baz, quux::{self::*, Fez}}",
834+
r"use foo::bar::{Baz, quux::*};",
835+
r"use foo::bar::{Baz, quux::{self::*, Fez}};",
824836
)
825837
}
826838

0 commit comments

Comments
 (0)