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 } ,
@@ -32,24 +33,13 @@ use Edit::*;
32
33
pub ( crate ) fn merge_imports ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
33
34
let ( target, edits) = if ctx. has_empty_selection ( ) {
34
35
// 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 ( ) ;
42
38
let target = tree. syntax ( ) . text_range ( ) ;
43
39
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 ) ;
53
43
( target, edits?)
54
44
} else {
55
45
// Merge selected
@@ -94,7 +84,35 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
94
84
for edit in edits_mut {
95
85
match edit {
96
86
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
+ }
98
116
}
99
117
}
100
118
} ,
@@ -201,20 +219,17 @@ use std::fmt$0::{Display, Debug};
201
219
use std::fmt::{Display, Debug};
202
220
" ,
203
221
r"
204
- use std::fmt::{Display, Debug };
222
+ use std::fmt::{Debug, Display };
205
223
" ,
206
224
) ;
207
225
208
226
// 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.
213
228
cov_mark:: check_count!( merge_with_use_item_neighbors, 4 ) ;
214
229
check_assist_import_one_variations ! (
215
230
"std::fmt$0::{Display, Debug}" ,
216
231
"std::fmt::{Display, Debug}" ,
217
- "use {std::fmt::{Display, Debug }};"
232
+ "use {std::fmt::{Debug, Display }};"
218
233
) ;
219
234
}
220
235
@@ -257,7 +272,7 @@ use std::fmt::{Debug, Display};
257
272
}
258
273
259
274
#[ test]
260
- fn merge_self1 ( ) {
275
+ fn merge_self ( ) {
261
276
check_assist (
262
277
merge_imports,
263
278
r"
@@ -276,21 +291,8 @@ use std::fmt::{self, Display};
276
291
}
277
292
278
293
#[ 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};" ) ;
294
296
check_assist_not_applicable_for_import_one (
295
297
merge_imports,
296
298
"use {std::{fmt, $0fmt::Display}};" ,
@@ -385,14 +387,14 @@ pub(in this::path) use std::fmt::{Debug, Display};
385
387
386
388
#[ test]
387
389
fn test_merge_nested ( ) {
388
- cov_mark:: check!( merge_with_use_tree_neighbors) ;
389
390
check_assist (
390
391
merge_imports,
391
392
r"
392
- use std::{fmt$0::Debug, fmt::Display};
393
+ use std::{fmt$0::Debug, fmt::Error};
394
+ use std::{fmt::Write, fmt::Display};
393
395
" ,
394
396
r"
395
- use std::{ fmt::{Debug, Display} };
397
+ use std::fmt::{Debug, Display, Error, Write };
396
398
" ,
397
399
) ;
398
400
}
@@ -402,10 +404,11 @@ use std::{fmt::{Debug, Display}};
402
404
check_assist (
403
405
merge_imports,
404
406
r"
405
- use std::{fmt::Debug, fmt$0::Display};
407
+ use std::{fmt::Debug, fmt$0::Error};
408
+ use std::{fmt::Write, fmt::Display};
406
409
" ,
407
410
r"
408
- use std::{ fmt::{Debug, Display} };
411
+ use std::fmt::{Debug, Display, Error, Write };
409
412
" ,
410
413
) ;
411
414
}
@@ -419,13 +422,13 @@ use std$0::{fmt::{Write, Display}};
419
422
use std::{fmt::{self, Debug}};
420
423
" ,
421
424
r"
422
- use std::{ fmt::{self, Debug, Display, Write} };
425
+ use std::fmt::{self, Debug, Display, Write};
423
426
" ,
424
427
) ;
425
428
check_assist_import_one_variations ! (
426
429
"std$0::{fmt::{Write, Display}}" ,
427
430
"std::{fmt::{self, Debug}}" ,
428
- "use {std::{ fmt::{self, Debug, Display, Write} }};"
431
+ "use {std::fmt::{self, Debug, Display, Write}};"
429
432
) ;
430
433
}
431
434
@@ -438,26 +441,13 @@ use std$0::{fmt::{self, Debug}};
438
441
use std::{fmt::{Write, Display}};
439
442
" ,
440
443
r"
441
- use std::{ fmt::{self, Debug, Display, Write} };
444
+ use std::fmt::{self, Debug, Display, Write};
442
445
" ,
443
446
) ;
444
447
check_assist_import_one_variations ! (
445
448
"std$0::{fmt::{self, Debug}}" ,
446
449
"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}};"
461
451
) ;
462
452
}
463
453
@@ -470,13 +460,13 @@ use foo::$0{bar::{self}};
470
460
use foo::{bar};
471
461
" ,
472
462
r"
473
- use foo::{ bar::{self}} ;
463
+ use foo::bar;
474
464
" ,
475
465
) ;
476
466
check_assist_import_one_variations ! (
477
467
"foo::$0{bar::{self}}" ,
478
468
"foo::{bar}" ,
479
- "use {foo::{ bar::{self}} };"
469
+ "use {foo::bar};"
480
470
) ;
481
471
}
482
472
@@ -489,13 +479,13 @@ use foo::$0{bar};
489
479
use foo::{bar::{self}};
490
480
" ,
491
481
r"
492
- use foo::{ bar::{self}} ;
482
+ use foo::bar;
493
483
" ,
494
484
) ;
495
485
check_assist_import_one_variations ! (
496
486
"foo::$0{bar}" ,
497
487
"foo::{bar::{self}}" ,
498
- "use {foo::{ bar::{self}} };"
488
+ "use {foo::bar};"
499
489
) ;
500
490
}
501
491
@@ -508,13 +498,13 @@ use std$0::{fmt::*};
508
498
use std::{fmt::{self, Display}};
509
499
" ,
510
500
r"
511
- use std::{ fmt::{self, Display, *} };
501
+ use std::fmt::{self, Display, *};
512
502
" ,
513
503
) ;
514
504
check_assist_import_one_variations ! (
515
505
"std$0::{fmt::*}" ,
516
506
"std::{fmt::{self, Display}}" ,
517
- "use {std::{ fmt::{self, Display, *} }};"
507
+ "use {std::fmt::{self, Display, *}};"
518
508
) ;
519
509
}
520
510
@@ -579,29 +569,27 @@ use foo::{bar, baz};
579
569
check_assist (
580
570
merge_imports,
581
571
r"
582
- use {
583
- foo$0::bar,
584
- foo::baz,
572
+ use foo$0::{
573
+ bar, baz,
585
574
};
575
+ use foo::qux;
586
576
" ,
587
577
r"
588
- use {
589
- foo::{ bar, baz} ,
578
+ use foo:: {
579
+ bar, baz, qux ,
590
580
};
591
581
" ,
592
582
) ;
593
583
check_assist (
594
584
merge_imports,
595
585
r"
596
- use {
597
- foo::baz,
598
- foo$0::bar,
586
+ use foo::{
587
+ baz, bar,
599
588
};
589
+ use foo$0::qux;
600
590
" ,
601
591
r"
602
- use {
603
- foo::{bar, baz},
604
- };
592
+ use foo::{bar, baz, qux};
605
593
" ,
606
594
) ;
607
595
}
@@ -711,12 +699,19 @@ use std::{
711
699
};" ,
712
700
) ;
713
701
714
- // FIXME: Remove redundant braces. See also unnecessary-braces diagnostic.
715
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) ;
716
711
check_assist (
717
712
merge_imports,
718
713
r"use std::$0{fmt::Display, fmt::Debug}$0;" ,
719
- r"use std::{ fmt::{Debug, Display} };" ,
714
+ r"use std::fmt::{Debug, Display};" ,
720
715
) ;
721
716
}
722
717
}
0 commit comments