1 use ide_db::helpers::merge_imports::{try_merge_imports, try_merge_trees, MergeBehavior};
2 use syntax::{algo::neighbor, ast, ted, AstNode};
5 assist_context::{AssistContext, Assists},
10 // Assist: merge_imports
12 // Merges two imports with a common prefix.
15 // use std::$0fmt::Formatter;
20 // use std::{fmt::Formatter, io};
22 pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
23 let tree: ast::UseTree = ctx.find_node_at_offset()?;
25 let mut imports = None;
27 if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) {
28 let (merged, to_remove) =
29 next_prev().filter_map(|dir| neighbor(&use_item, dir)).find_map(|use_item2| {
30 try_merge_imports(&use_item, &use_item2, MergeBehavior::Crate).zip(Some(use_item2))
33 imports = Some((use_item, merged, to_remove));
35 let (merged, to_remove) =
36 next_prev().filter_map(|dir| neighbor(&tree, dir)).find_map(|use_tree| {
37 try_merge_trees(&tree, &use_tree, MergeBehavior::Crate).zip(Some(use_tree))
40 uses = Some((tree.clone(), merged, to_remove))
43 let target = tree.syntax().text_range();
45 AssistId("merge_imports", AssistKind::RefactorRewrite),
49 if let Some((to_replace, replacement, to_remove)) = imports {
50 let to_replace = builder.make_mut(to_replace);
51 let to_remove = builder.make_mut(to_remove);
53 ted::replace(to_replace.syntax(), replacement.syntax());
57 if let Some((to_replace, replacement, to_remove)) = uses {
58 let to_replace = builder.make_mut(to_replace);
59 let to_remove = builder.make_mut(to_remove);
61 ted::replace(to_replace.syntax(), replacement.syntax());
70 use crate::tests::{check_assist, check_assist_not_applicable};
75 fn test_merge_equal() {
79 use std::fmt$0::{Display, Debug};
80 use std::fmt::{Display, Debug};
83 use std::fmt::{Debug, Display};
89 fn test_merge_first() {
93 use std::fmt$0::Debug;
94 use std::fmt::Display;
97 use std::fmt::{Debug, Display};
103 fn test_merge_second() {
108 use std::fmt$0::Display;
111 use std::fmt::{Debug, Display};
122 use std::fmt::Display;
125 use std::fmt::{self, Display};
135 use std::{fmt, $0fmt::Display};
138 use std::{fmt::{self, Display}};
145 check_assist_not_applicable(
148 pub use std::fmt$0::Debug;
149 use std::fmt::Display;
156 check_assist_not_applicable(
159 use std::fmt$0::Debug;
160 pub use std::fmt::Display;
166 fn skip_pub_crate_pub() {
167 check_assist_not_applicable(
170 pub(crate) use std::fmt$0::Debug;
171 pub use std::fmt::Display;
177 fn skip_pub_pub_crate() {
178 check_assist_not_applicable(
181 pub use std::fmt$0::Debug;
182 pub(crate) use std::fmt::Display;
192 pub use std::fmt$0::Debug;
193 pub use std::fmt::Display;
196 pub use std::fmt::{Debug, Display};
202 fn merge_pub_crate() {
206 pub(crate) use std::fmt$0::Debug;
207 pub(crate) use std::fmt::Display;
210 pub(crate) use std::fmt::{Debug, Display};
216 fn merge_pub_in_path_crate() {
220 pub(in this::path) use std::fmt$0::Debug;
221 pub(in this::path) use std::fmt::Display;
224 pub(in this::path) use std::fmt::{Debug, Display};
230 fn test_merge_nested() {
234 use std::{fmt$0::Debug, fmt::Display};
237 use std::{fmt::{Debug, Display}};
243 fn test_merge_nested2() {
247 use std::{fmt::Debug, fmt$0::Display};
250 use std::{fmt::{Debug, Display}};
256 fn test_merge_single_wildcard_diff_prefixes() {
264 use std::{cell::*, str};
270 fn test_merge_both_wildcard_diff_prefixes() {
278 use std::{cell::*, str::*};
284 fn removes_just_enough_whitespace() {
302 fn works_with_trailing_comma() {
334 fn test_double_comma() {
344 use foo::{FooBar, bar::baz};
350 fn test_empty_use() {
351 check_assist_not_applicable(