aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2020-09-12 22:54:49 +0100
committerLukas Wirth <[email protected]>2020-09-12 22:54:49 +0100
commitb874721752e07673f28ef07a003fe8582d4f1645 (patch)
tree42b4c9db2325eaac38c2a73bb24c506755db650d /crates
parentcd6cd91bf345d47cbf22e00fc4cddced4ae67ae6 (diff)
Fix merge imports failing if the `self` module import is in the wrong tree
Diffstat (limited to 'crates')
-rw-r--r--crates/assists/src/utils/insert_use.rs56
1 files changed, 34 insertions, 22 deletions
diff --git a/crates/assists/src/utils/insert_use.rs b/crates/assists/src/utils/insert_use.rs
index 99f0b5b75..4972085d6 100644
--- a/crates/assists/src/utils/insert_use.rs
+++ b/crates/assists/src/utils/insert_use.rs
@@ -149,31 +149,31 @@ fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -
149} 149}
150 150
151pub(crate) fn try_merge_imports( 151pub(crate) fn try_merge_imports(
152 old: &ast::Use, 152 lhs: &ast::Use,
153 new: &ast::Use, 153 rhs: &ast::Use,
154 merge_behaviour: MergeBehaviour, 154 merge_behaviour: MergeBehaviour,
155) -> Option<ast::Use> { 155) -> Option<ast::Use> {
156 // don't merge imports with different visibilities 156 // don't merge imports with different visibilities
157 if !eq_visibility(old.visibility(), new.visibility()) { 157 if !eq_visibility(lhs.visibility(), rhs.visibility()) {
158 return None; 158 return None;
159 } 159 }
160 let old_tree = old.use_tree()?; 160 let lhs_tree = lhs.use_tree()?;
161 let new_tree = new.use_tree()?; 161 let rhs_tree = rhs.use_tree()?;
162 let merged = try_merge_trees(&old_tree, &new_tree, merge_behaviour)?; 162 let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behaviour)?;
163 Some(old.with_use_tree(merged)) 163 Some(lhs.with_use_tree(merged))
164} 164}
165 165
166pub(crate) fn try_merge_trees( 166pub(crate) fn try_merge_trees(
167 old: &ast::UseTree, 167 lhs: &ast::UseTree,
168 new: &ast::UseTree, 168 rhs: &ast::UseTree,
169 merge: MergeBehaviour, 169 merge: MergeBehaviour,
170) -> Option<ast::UseTree> { 170) -> Option<ast::UseTree> {
171 let lhs_path = old.path()?; 171 let lhs_path = lhs.path()?;
172 let rhs_path = new.path()?; 172 let rhs_path = rhs.path()?;
173 173
174 let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?; 174 let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?;
175 let lhs = old.split_prefix(&lhs_prefix); 175 let lhs = lhs.split_prefix(&lhs_prefix);
176 let rhs = new.split_prefix(&rhs_prefix); 176 let rhs = rhs.split_prefix(&rhs_prefix);
177 recursive_merge(&lhs, &rhs, merge).map(|(merged, _)| merged) 177 recursive_merge(&lhs, &rhs, merge).map(|(merged, _)| merged)
178} 178}
179 179
@@ -209,13 +209,18 @@ fn recursive_merge(
209 }; 209 };
210 // check if only one of the two trees has a tree list, and whether that then contains `self` or not. 210 // check if only one of the two trees has a tree list, and whether that then contains `self` or not.
211 // 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` 211 // 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 212 let tree_contains_self = |tree: &ast::UseTree| {
213 .use_tree_list() 213 tree.use_tree_list()
214 .xor(rhs_t.use_tree_list()) 214 .map(|tree_list| tree_list.use_trees().any(tree_is_self))
215 .map(|tree_list| tree_list.use_trees().any(tree_is_self)) 215 .unwrap_or(false)
216 .unwrap_or(false) 216 };
217 { 217 match (tree_contains_self(&lhs_t), tree_contains_self(&rhs_t)) {
218 continue; 218 (true, false) => continue,
219 (false, true) => {
220 *lhs_t = rhs_t;
221 continue;
222 }
223 _ => (),
219 } 224 }
220 225
221 // glob imports arent part of the use-tree lists so we need to special handle them here as well 226 // 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(
255 None => use_trees.insert(idx, rhs_t), 260 None => use_trees.insert(idx, rhs_t),
256 } 261 }
257 } 262 }
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 }
258 Err(idx) => { 270 Err(idx) => {
259 use_trees.insert(idx, rhs_t); 271 use_trees.insert(idx, rhs_t);
260 } 272 }
@@ -819,8 +831,8 @@ use std::io;",
819 fn merge_glob_nested() { 831 fn merge_glob_nested() {
820 check_full( 832 check_full(
821 "foo::bar::quux::Fez", 833 "foo::bar::quux::Fez",
822 r"use foo::bar::{Baz, quux::*;", 834 r"use foo::bar::{Baz, quux::*};",
823 r"use foo::bar::{Baz, quux::{self::*, Fez}}", 835 r"use foo::bar::{Baz, quux::{self::*, Fez}};",
824 ) 836 )
825 } 837 }
826 838