11use either:: Either ;
22use ide_db:: imports:: {
33 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 } ,
55} ;
6+ use itertools:: Itertools ;
67use syntax:: {
78 algo:: neighbor,
89 ast:: { self , edit_in_place:: Removable } ,
@@ -32,24 +33,13 @@ use Edit::*;
3233pub ( crate ) fn merge_imports ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
3334 let ( target, edits) = if ctx. has_empty_selection ( ) {
3435 // Merge a neighbor
35- let mut tree: ast:: UseTree = ctx. find_node_at_offset ( ) ?;
36- if ctx. config . insert_use . granularity == ImportGranularity :: One
37- && tree. parent_use_tree_list ( ) . is_some ( )
38- {
39- cov_mark:: hit!( resolve_top_use_tree_for_import_one) ;
40- tree = tree. top_use_tree ( ) ;
41- }
36+ cov_mark:: hit!( merge_with_use_item_neighbors) ;
37+ let tree = ctx. find_node_at_offset :: < ast:: UseTree > ( ) ?. top_use_tree ( ) ;
4238 let target = tree. syntax ( ) . text_range ( ) ;
4339
44- let edits = if let Some ( use_item) = tree. syntax ( ) . parent ( ) . and_then ( ast:: Use :: cast) {
45- cov_mark:: hit!( merge_with_use_item_neighbors) ;
46- let mut neighbor = next_prev ( ) . find_map ( |dir| neighbor ( & use_item, dir) ) . into_iter ( ) ;
47- use_item. try_merge_from ( & mut neighbor, & ctx. config . insert_use )
48- } else {
49- cov_mark:: hit!( merge_with_use_tree_neighbors) ;
50- let mut neighbor = next_prev ( ) . find_map ( |dir| neighbor ( & tree, dir) ) . into_iter ( ) ;
51- tree. clone ( ) . try_merge_from ( & mut neighbor, & ctx. config . insert_use )
52- } ;
40+ let use_item = tree. syntax ( ) . parent ( ) . and_then ( ast:: Use :: cast) ?;
41+ let mut neighbor = next_prev ( ) . find_map ( |dir| neighbor ( & use_item, dir) ) . into_iter ( ) ;
42+ let edits = use_item. try_merge_from ( & mut neighbor, & ctx. config . insert_use ) ;
5343 ( target, edits?)
5444 } else {
5545 // Merge selected
@@ -94,7 +84,35 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
9484 for edit in edits_mut {
9585 match edit {
9686 Remove ( it) => it. as_ref ( ) . either ( Removable :: remove, Removable :: remove) ,
97- 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+ }
98116 }
99117 }
100118 } ,
@@ -201,20 +219,17 @@ use std::fmt$0::{Display, Debug};
201219use std::fmt::{Display, Debug};
202220" ,
203221 r"
204- use std::fmt::{Display, Debug };
222+ use std::fmt::{Debug, Display };
205223" ,
206224 ) ;
207225
208226 // The assist macro below calls `check_assist_import_one` 4 times with different input
209- // use item variations based on the first 2 input parameters, but only 2 calls
210- // contain `use {std::fmt$0::{Display, Debug}};` for which the top use tree will need
211- // to be resolved.
212- cov_mark:: check_count!( resolve_top_use_tree_for_import_one, 2 ) ;
227+ // use item variations based on the first 2 input parameters.
213228 cov_mark:: check_count!( merge_with_use_item_neighbors, 4 ) ;
214229 check_assist_import_one_variations ! (
215230 "std::fmt$0::{Display, Debug}" ,
216231 "std::fmt::{Display, Debug}" ,
217- "use {std::fmt::{Display, Debug }};"
232+ "use {std::fmt::{Debug, Display }};"
218233 ) ;
219234 }
220235
@@ -257,7 +272,7 @@ use std::fmt::{Debug, Display};
257272 }
258273
259274 #[ test]
260- fn merge_self1 ( ) {
275+ fn merge_self ( ) {
261276 check_assist (
262277 merge_imports,
263278 r"
@@ -276,21 +291,8 @@ use std::fmt::{self, Display};
276291 }
277292
278293 #[ test]
279- fn merge_self2 ( ) {
280- check_assist (
281- merge_imports,
282- r"
283- use std::{fmt, $0fmt::Display};
284- " ,
285- r"
286- use std::{fmt::{self, Display}};
287- " ,
288- ) ;
289- }
290-
291- #[ test]
292- fn not_applicable_to_single_one_style_import ( ) {
293- cov_mark:: check!( resolve_top_use_tree_for_import_one) ;
294+ fn not_applicable_to_single_import ( ) {
295+ check_assist_not_applicable ( merge_imports, "use std::{fmt, $0fmt::Display};" ) ;
294296 check_assist_not_applicable_for_import_one (
295297 merge_imports,
296298 "use {std::{fmt, $0fmt::Display}};" ,
@@ -385,14 +387,14 @@ pub(in this::path) use std::fmt::{Debug, Display};
385387
386388 #[ test]
387389 fn test_merge_nested ( ) {
388- cov_mark:: check!( merge_with_use_tree_neighbors) ;
389390 check_assist (
390391 merge_imports,
391392 r"
392- use std::{fmt$0::Debug, fmt::Display};
393+ use std::{fmt$0::Debug, fmt::Error};
394+ use std::{fmt::Write, fmt::Display};
393395" ,
394396 r"
395- use std::{ fmt::{Debug, Display} };
397+ use std::fmt::{Debug, Display, Error, Write };
396398" ,
397399 ) ;
398400 }
@@ -402,10 +404,11 @@ use std::{fmt::{Debug, Display}};
402404 check_assist (
403405 merge_imports,
404406 r"
405- use std::{fmt::Debug, fmt$0::Display};
407+ use std::{fmt::Debug, fmt$0::Error};
408+ use std::{fmt::Write, fmt::Display};
406409" ,
407410 r"
408- use std::{ fmt::{Debug, Display} };
411+ use std::fmt::{Debug, Display, Error, Write };
409412" ,
410413 ) ;
411414 }
@@ -419,13 +422,13 @@ use std$0::{fmt::{Write, Display}};
419422use std::{fmt::{self, Debug}};
420423" ,
421424 r"
422- use std::{ fmt::{self, Debug, Display, Write} };
425+ use std::fmt::{self, Debug, Display, Write};
423426" ,
424427 ) ;
425428 check_assist_import_one_variations ! (
426429 "std$0::{fmt::{Write, Display}}" ,
427430 "std::{fmt::{self, Debug}}" ,
428- "use {std::{ fmt::{self, Debug, Display, Write} }};"
431+ "use {std::fmt::{self, Debug, Display, Write}};"
429432 ) ;
430433 }
431434
@@ -438,26 +441,13 @@ use std$0::{fmt::{self, Debug}};
438441use std::{fmt::{Write, Display}};
439442" ,
440443 r"
441- use std::{ fmt::{self, Debug, Display, Write} };
444+ use std::fmt::{self, Debug, Display, Write};
442445" ,
443446 ) ;
444447 check_assist_import_one_variations ! (
445448 "std$0::{fmt::{self, Debug}}" ,
446449 "std::{fmt::{Write, Display}}" ,
447- "use {std::{fmt::{self, Debug, Display, Write}}};"
448- ) ;
449- }
450-
451- #[ test]
452- fn test_merge_self_with_nested_self_item ( ) {
453- check_assist (
454- merge_imports,
455- r"
456- use std::{fmt$0::{self, Debug}, fmt::{Write, Display}};
457- " ,
458- r"
459- use std::{fmt::{self, Debug, Display, Write}};
460- " ,
450+ "use {std::fmt::{self, Debug, Display, Write}};"
461451 ) ;
462452 }
463453
@@ -470,13 +460,13 @@ use foo::$0{bar::{self}};
470460use foo::{bar};
471461" ,
472462 r"
473- use foo::{ bar::{self}} ;
463+ use foo::bar;
474464" ,
475465 ) ;
476466 check_assist_import_one_variations ! (
477467 "foo::$0{bar::{self}}" ,
478468 "foo::{bar}" ,
479- "use {foo::{ bar::{self}} };"
469+ "use {foo::bar};"
480470 ) ;
481471 }
482472
@@ -489,13 +479,13 @@ use foo::$0{bar};
489479use foo::{bar::{self}};
490480" ,
491481 r"
492- use foo::{ bar::{self}} ;
482+ use foo::bar;
493483" ,
494484 ) ;
495485 check_assist_import_one_variations ! (
496486 "foo::$0{bar}" ,
497487 "foo::{bar::{self}}" ,
498- "use {foo::{ bar::{self}} };"
488+ "use {foo::bar};"
499489 ) ;
500490 }
501491
@@ -508,13 +498,13 @@ use std$0::{fmt::*};
508498use std::{fmt::{self, Display}};
509499" ,
510500 r"
511- use std::{ fmt::{self, Display, *} };
501+ use std::fmt::{self, Display, *};
512502" ,
513503 ) ;
514504 check_assist_import_one_variations ! (
515505 "std$0::{fmt::*}" ,
516506 "std::{fmt::{self, Display}}" ,
517- "use {std::{ fmt::{self, Display, *} }};"
507+ "use {std::fmt::{self, Display, *}};"
518508 ) ;
519509 }
520510
@@ -579,29 +569,27 @@ use foo::{bar, baz};
579569 check_assist (
580570 merge_imports,
581571 r"
582- use {
583- foo$0::bar,
584- foo::baz,
572+ use foo$0::{
573+ bar, baz,
585574};
575+ use foo::qux;
586576" ,
587577 r"
588- use {
589- foo::{ bar, baz} ,
578+ use foo:: {
579+ bar, baz, qux ,
590580};
591581" ,
592582 ) ;
593583 check_assist (
594584 merge_imports,
595585 r"
596- use {
597- foo::baz,
598- foo$0::bar,
586+ use foo::{
587+ baz, bar,
599588};
589+ use foo$0::qux;
600590" ,
601591 r"
602- use {
603- foo::{bar, baz},
604- };
592+ use foo::{bar, baz, qux};
605593" ,
606594 ) ;
607595 }
@@ -711,12 +699,19 @@ use std::{
711699};" ,
712700 ) ;
713701
714- // FIXME: Remove redundant braces. See also unnecessary-braces diagnostic.
715702 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) ;
716711 check_assist (
717712 merge_imports,
718713 r"use std::$0{fmt::Display, fmt::Debug}$0;" ,
719- r"use std::{ fmt::{Debug, Display} };" ,
714+ r"use std::fmt::{Debug, Display};" ,
720715 ) ;
721716 }
722717}
0 commit comments