|
1 | 1 | use either::Either;
|
2 | 2 | use ide_db::imports::{
|
3 | 3 | insert_use::{ImportGranularity, InsertUseConfig},
|
4 |
| - merge_imports::{try_merge_imports, try_merge_trees, MergeBehavior}, |
| 4 | + merge_imports::{try_merge_imports, try_merge_trees, try_normalize_use_tree, MergeBehavior}, |
5 | 5 | };
|
| 6 | +use itertools::Itertools; |
6 | 7 | use syntax::{
|
7 | 8 | algo::neighbor,
|
8 | 9 | ast::{self, edit_in_place::Removable},
|
@@ -83,7 +84,35 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
|
83 | 84 | for edit in edits_mut {
|
84 | 85 | match edit {
|
85 | 86 | Remove(it) => it.as_ref().either(Removable::remove, Removable::remove),
|
86 |
| - Replace(old, new) => ted::replace(old, new), |
| 87 | + Replace(old, new) => { |
| 88 | + ted::replace(old, &new); |
| 89 | + |
| 90 | + // If there's a selection and we're replacing a use tree in a tree list, |
| 91 | + // normalize the parent use tree if it only contains the merged subtree. |
| 92 | + if !ctx.has_empty_selection() { |
| 93 | + let normalized_use_tree = ast::UseTree::cast(new) |
| 94 | + .as_ref() |
| 95 | + .and_then(ast::UseTree::parent_use_tree_list) |
| 96 | + .and_then(|use_tree_list| { |
| 97 | + if use_tree_list.use_trees().collect_tuple::<(_,)>().is_some() { |
| 98 | + Some(use_tree_list.parent_use_tree()) |
| 99 | + } else { |
| 100 | + None |
| 101 | + } |
| 102 | + }) |
| 103 | + .and_then(|target_tree| { |
| 104 | + try_normalize_use_tree( |
| 105 | + &target_tree, |
| 106 | + ctx.config.insert_use.granularity.into(), |
| 107 | + ) |
| 108 | + .map(|top_use_tree_flat| (target_tree, top_use_tree_flat)) |
| 109 | + }); |
| 110 | + if let Some((old_tree, new_tree)) = normalized_use_tree { |
| 111 | + cov_mark::hit!(replace_parent_with_normalized_use_tree); |
| 112 | + ted::replace(old_tree.syntax(), new_tree.syntax()); |
| 113 | + } |
| 114 | + } |
| 115 | + } |
87 | 116 | }
|
88 | 117 | }
|
89 | 118 | },
|
@@ -148,7 +177,10 @@ impl Edit {
|
148 | 177 |
|
149 | 178 | #[cfg(test)]
|
150 | 179 | mod tests {
|
151 |
| - use crate::tests::{check_assist, check_assist_import_one, check_assist_not_applicable}; |
| 180 | + use crate::tests::{ |
| 181 | + check_assist, check_assist_import_one, check_assist_not_applicable, |
| 182 | + check_assist_not_applicable_for_import_one, |
| 183 | + }; |
152 | 184 |
|
153 | 185 | use super::*;
|
154 | 186 |
|
@@ -258,6 +290,15 @@ use std::fmt::{self, Display};
|
258 | 290 | );
|
259 | 291 | }
|
260 | 292 |
|
| 293 | + #[test] |
| 294 | + fn not_applicable_to_single_import() { |
| 295 | + check_assist_not_applicable(merge_imports, "use std::{fmt, $0fmt::Display};"); |
| 296 | + check_assist_not_applicable_for_import_one( |
| 297 | + merge_imports, |
| 298 | + "use {std::{fmt, $0fmt::Display}};", |
| 299 | + ); |
| 300 | + } |
| 301 | + |
261 | 302 | #[test]
|
262 | 303 | fn skip_pub1() {
|
263 | 304 | check_assist_not_applicable(
|
@@ -658,12 +699,19 @@ use std::{
|
658 | 699 | };",
|
659 | 700 | );
|
660 | 701 |
|
661 |
| - // FIXME: Remove redundant braces. See also unnecessary-braces diagnostic. |
662 | 702 | cov_mark::check!(merge_with_selected_use_tree_neighbors);
|
| 703 | + check_assist( |
| 704 | + merge_imports, |
| 705 | + r"use std::{fmt::Result, $0fmt::Display, fmt::Debug$0};", |
| 706 | + r"use std::{fmt::Result, fmt::{Debug, Display}};", |
| 707 | + ); |
| 708 | + |
| 709 | + cov_mark::check!(merge_with_selected_use_tree_neighbors); |
| 710 | + cov_mark::check!(replace_parent_with_normalized_use_tree); |
663 | 711 | check_assist(
|
664 | 712 | merge_imports,
|
665 | 713 | r"use std::$0{fmt::Display, fmt::Debug}$0;",
|
666 |
| - r"use std::{fmt::{Debug, Display}};", |
| 714 | + r"use std::fmt::{Debug, Display};", |
667 | 715 | );
|
668 | 716 | }
|
669 | 717 | }
|
0 commit comments