aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_db')
-rw-r--r--crates/ide_db/src/helpers/merge_imports.rs38
1 files changed, 23 insertions, 15 deletions
diff --git a/crates/ide_db/src/helpers/merge_imports.rs b/crates/ide_db/src/helpers/merge_imports.rs
index af2a51a4d..8fb40e837 100644
--- a/crates/ide_db/src/helpers/merge_imports.rs
+++ b/crates/ide_db/src/helpers/merge_imports.rs
@@ -2,8 +2,9 @@
2use std::cmp::Ordering; 2use std::cmp::Ordering;
3 3
4use itertools::{EitherOrBoth, Itertools}; 4use itertools::{EitherOrBoth, Itertools};
5use syntax::ast::{ 5use syntax::{
6 self, edit::AstNodeEdit, make, AstNode, AttrsOwner, PathSegmentKind, VisibilityOwner, 6 ast::{self, make, AstNode, AttrsOwner, PathSegmentKind, VisibilityOwner},
7 ted,
7}; 8};
8 9
9/// What type of merges are allowed. 10/// What type of merges are allowed.
@@ -41,10 +42,12 @@ pub fn try_merge_imports(
41 return None; 42 return None;
42 } 43 }
43 44
45 let lhs = lhs.clone_subtree().clone_for_update();
44 let lhs_tree = lhs.use_tree()?; 46 let lhs_tree = lhs.use_tree()?;
45 let rhs_tree = rhs.use_tree()?; 47 let rhs_tree = rhs.use_tree()?;
46 let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?; 48 let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?;
47 Some(lhs.with_use_tree(merged).clone_for_update()) 49 ted::replace(lhs_tree.syntax(), merged.syntax());
50 Some(lhs)
48} 51}
49 52
50pub fn try_merge_trees( 53pub fn try_merge_trees(
@@ -65,7 +68,7 @@ pub fn try_merge_trees(
65 } else { 68 } else {
66 (lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix)) 69 (lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix))
67 }; 70 };
68 recursive_merge(&lhs, &rhs, merge) 71 recursive_merge(&lhs, &rhs, merge).map(|it| it.clone_for_update())
69} 72}
70 73
71/// Recursively "zips" together lhs and rhs. 74/// Recursively "zips" together lhs and rhs.
@@ -78,7 +81,8 @@ fn recursive_merge(
78 .use_tree_list() 81 .use_tree_list()
79 .into_iter() 82 .into_iter()
80 .flat_map(|list| list.use_trees()) 83 .flat_map(|list| list.use_trees())
81 // we use Option here to early return from this function(this is not the same as a `filter` op) 84 // We use Option here to early return from this function(this is not the
85 // same as a `filter` op).
82 .map(|tree| match merge.is_tree_allowed(&tree) { 86 .map(|tree| match merge.is_tree_allowed(&tree) {
83 true => Some(tree), 87 true => Some(tree),
84 false => None, 88 false => None,
@@ -111,8 +115,10 @@ fn recursive_merge(
111 let tree_is_self = |tree: ast::UseTree| { 115 let tree_is_self = |tree: ast::UseTree| {
112 tree.path().as_ref().map(path_is_self).unwrap_or(false) 116 tree.path().as_ref().map(path_is_self).unwrap_or(false)
113 }; 117 };
114 // check if only one of the two trees has a tree list, and whether that then contains `self` or not. 118 // Check if only one of the two trees has a tree list, and
115 // 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` 119 // whether that then contains `self` or not. If this is the
120 // case we can skip this iteration since the path without
121 // the list is already included in the other one via `self`.
116 let tree_contains_self = |tree: &ast::UseTree| { 122 let tree_contains_self = |tree: &ast::UseTree| {
117 tree.use_tree_list() 123 tree.use_tree_list()
118 .map(|tree_list| tree_list.use_trees().any(tree_is_self)) 124 .map(|tree_list| tree_list.use_trees().any(tree_is_self))
@@ -127,9 +133,11 @@ fn recursive_merge(
127 _ => (), 133 _ => (),
128 } 134 }
129 135
130 // glob imports arent part of the use-tree lists so we need to special handle them here as well 136 // Glob imports aren't part of the use-tree lists so we need
131 // this special handling is only required for when we merge a module import into a glob import of said module 137 // to special handle them here as well this special handling
132 // see the `merge_self_glob` or `merge_mod_into_glob` tests 138 // is only required for when we merge a module import into a
139 // glob import of said module see the `merge_self_glob` or
140 // `merge_mod_into_glob` tests.
133 if lhs_t.star_token().is_some() || rhs_t.star_token().is_some() { 141 if lhs_t.star_token().is_some() || rhs_t.star_token().is_some() {
134 *lhs_t = make::use_tree( 142 *lhs_t = make::use_tree(
135 make::path_unqualified(make::path_segment_self()), 143 make::path_unqualified(make::path_segment_self()),
@@ -165,11 +173,11 @@ fn recursive_merge(
165 } 173 }
166 } 174 }
167 175
168 Some(if let Some(old) = lhs.use_tree_list() { 176 let lhs = lhs.clone_subtree().clone_for_update();
169 lhs.replace_descendant(old, make::use_tree_list(use_trees)).clone_for_update() 177 if let Some(old) = lhs.use_tree_list() {
170 } else { 178 ted::replace(old.syntax(), make::use_tree_list(use_trees).syntax().clone_for_update());
171 lhs.clone() 179 }
172 }) 180 ast::UseTree::cast(lhs.syntax().clone_subtree())
173} 181}
174 182
175/// Traverses both paths until they differ, returning the common prefix of both. 183/// Traverses both paths until they differ, returning the common prefix of both.