diff options
Diffstat (limited to 'crates/ide_db/src/helpers')
-rw-r--r-- | crates/ide_db/src/helpers/merge_imports.rs | 38 |
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 @@ | |||
2 | use std::cmp::Ordering; | 2 | use std::cmp::Ordering; |
3 | 3 | ||
4 | use itertools::{EitherOrBoth, Itertools}; | 4 | use itertools::{EitherOrBoth, Itertools}; |
5 | use syntax::ast::{ | 5 | use 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 | ||
50 | pub fn try_merge_trees( | 53 | pub 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. |