1
1
use either:: Either ;
2
- use ide_db:: imports:: merge_imports:: { try_merge_imports, try_merge_trees, MergeBehavior } ;
2
+ use ide_db:: imports:: {
3
+ insert_use:: { ImportGranularity , InsertUseConfig } ,
4
+ merge_imports:: { try_merge_imports, try_merge_trees, MergeBehavior } ,
5
+ } ;
3
6
use syntax:: {
4
7
algo:: neighbor,
5
8
ast:: { self , edit_in_place:: Removable } ,
@@ -16,7 +19,7 @@ use Edit::*;
16
19
17
20
// Assist: merge_imports
18
21
//
19
- // Merges two imports with a common prefix.
22
+ // Merges neighbor imports with a common prefix.
20
23
//
21
24
// ```
22
25
// use std::$0fmt::Formatter;
@@ -29,15 +32,23 @@ use Edit::*;
29
32
pub ( crate ) fn merge_imports ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
30
33
let ( target, edits) = if ctx. has_empty_selection ( ) {
31
34
// Merge a neighbor
32
- let tree: ast:: UseTree = ctx. find_node_at_offset ( ) ?;
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
+ }
33
42
let target = tree. syntax ( ) . text_range ( ) ;
34
43
35
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) ;
36
46
let mut neighbor = next_prev ( ) . find_map ( |dir| neighbor ( & use_item, dir) ) . into_iter ( ) ;
37
- use_item. try_merge_from ( & mut neighbor)
47
+ use_item. try_merge_from ( & mut neighbor, & ctx . config . insert_use )
38
48
} else {
49
+ cov_mark:: hit!( merge_with_use_tree_neighbors) ;
39
50
let mut neighbor = next_prev ( ) . find_map ( |dir| neighbor ( & tree, dir) ) . into_iter ( ) ;
40
- tree. try_merge_from ( & mut neighbor)
51
+ tree. clone ( ) . try_merge_from ( & mut neighbor, & ctx . config . insert_use )
41
52
} ;
42
53
( target, edits?)
43
54
} else {
@@ -54,10 +65,12 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
54
65
let edits = match_ast ! {
55
66
match first_selected {
56
67
ast:: Use ( use_item) => {
57
- use_item. try_merge_from( & mut selected_nodes. filter_map( ast:: Use :: cast) )
68
+ cov_mark:: hit!( merge_with_selected_use_item_neighbors) ;
69
+ use_item. try_merge_from( & mut selected_nodes. filter_map( ast:: Use :: cast) , & ctx. config. insert_use)
58
70
} ,
59
71
ast:: UseTree ( use_tree) => {
60
- use_tree. try_merge_from( & mut selected_nodes. filter_map( ast:: UseTree :: cast) )
72
+ cov_mark:: hit!( merge_with_selected_use_tree_neighbors) ;
73
+ use_tree. try_merge_from( & mut selected_nodes. filter_map( ast:: UseTree :: cast) , & ctx. config. insert_use)
61
74
} ,
62
75
_ => return None ,
63
76
}
@@ -89,11 +102,15 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
89
102
}
90
103
91
104
trait Merge : AstNode + Clone {
92
- fn try_merge_from ( self , items : & mut dyn Iterator < Item = Self > ) -> Option < Vec < Edit > > {
105
+ fn try_merge_from (
106
+ self ,
107
+ items : & mut dyn Iterator < Item = Self > ,
108
+ cfg : & InsertUseConfig ,
109
+ ) -> Option < Vec < Edit > > {
93
110
let mut edits = Vec :: new ( ) ;
94
111
let mut merged = self . clone ( ) ;
95
112
for item in items {
96
- merged = merged. try_merge ( & item) ?;
113
+ merged = merged. try_merge ( & item, cfg ) ?;
97
114
edits. push ( Edit :: Remove ( item. into_either ( ) ) ) ;
98
115
}
99
116
if !edits. is_empty ( ) {
@@ -103,21 +120,25 @@ trait Merge: AstNode + Clone {
103
120
None
104
121
}
105
122
}
106
- fn try_merge ( & self , other : & Self ) -> Option < Self > ;
123
+ fn try_merge ( & self , other : & Self , cfg : & InsertUseConfig ) -> Option < Self > ;
107
124
fn into_either ( self ) -> Either < ast:: Use , ast:: UseTree > ;
108
125
}
109
126
110
127
impl Merge for ast:: Use {
111
- fn try_merge ( & self , other : & Self ) -> Option < Self > {
112
- try_merge_imports ( self , other, MergeBehavior :: Crate )
128
+ fn try_merge ( & self , other : & Self , cfg : & InsertUseConfig ) -> Option < Self > {
129
+ let mb = match cfg. granularity {
130
+ ImportGranularity :: One => MergeBehavior :: One ,
131
+ _ => MergeBehavior :: Crate ,
132
+ } ;
133
+ try_merge_imports ( self , other, mb)
113
134
}
114
135
fn into_either ( self ) -> Either < ast:: Use , ast:: UseTree > {
115
136
Either :: Left ( self )
116
137
}
117
138
}
118
139
119
140
impl Merge for ast:: UseTree {
120
- fn try_merge ( & self , other : & Self ) -> Option < Self > {
141
+ fn try_merge ( & self , other : & Self , _ : & InsertUseConfig ) -> Option < Self > {
121
142
try_merge_trees ( self , other, MergeBehavior :: Crate )
122
143
}
123
144
fn into_either ( self ) -> Either < ast:: Use , ast:: UseTree > {
@@ -138,12 +159,41 @@ impl Edit {
138
159
139
160
#[ cfg( test) ]
140
161
mod tests {
141
- use crate :: tests:: { check_assist, check_assist_not_applicable} ;
162
+ use crate :: tests:: {
163
+ check_assist, check_assist_import_one, check_assist_not_applicable,
164
+ check_assist_not_applicable_for_import_one,
165
+ } ;
142
166
143
167
use super :: * ;
144
168
169
+ macro_rules! check_assist_import_one_variations {
170
+ ( $first: literal, $second: literal, $expected: literal) => {
171
+ check_assist_import_one(
172
+ merge_imports,
173
+ concat!( concat!( "use " , $first, ";" ) , concat!( "use " , $second, ";" ) ) ,
174
+ $expected,
175
+ ) ;
176
+ check_assist_import_one(
177
+ merge_imports,
178
+ concat!( concat!( "use {" , $first, "};" ) , concat!( "use " , $second, ";" ) ) ,
179
+ $expected,
180
+ ) ;
181
+ check_assist_import_one(
182
+ merge_imports,
183
+ concat!( concat!( "use " , $first, ";" ) , concat!( "use {" , $second, "};" ) ) ,
184
+ $expected,
185
+ ) ;
186
+ check_assist_import_one(
187
+ merge_imports,
188
+ concat!( concat!( "use {" , $first, "};" ) , concat!( "use {" , $second, "};" ) ) ,
189
+ $expected,
190
+ ) ;
191
+ } ;
192
+ }
193
+
145
194
#[ test]
146
195
fn test_merge_equal ( ) {
196
+ cov_mark:: check!( merge_with_use_item_neighbors) ;
147
197
check_assist (
148
198
merge_imports,
149
199
r"
@@ -153,7 +203,19 @@ use std::fmt::{Display, Debug};
153
203
r"
154
204
use std::fmt::{Display, Debug};
155
205
" ,
156
- )
206
+ ) ;
207
+
208
+ // 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 ) ;
213
+ cov_mark:: check_count!( merge_with_use_item_neighbors, 4 ) ;
214
+ check_assist_import_one_variations ! (
215
+ "std::fmt$0::{Display, Debug}" ,
216
+ "std::fmt::{Display, Debug}" ,
217
+ "use {std::fmt::{Display, Debug}};"
218
+ ) ;
157
219
}
158
220
159
221
#[ test]
@@ -167,7 +229,12 @@ use std::fmt::Display;
167
229
r"
168
230
use std::fmt::{Debug, Display};
169
231
" ,
170
- )
232
+ ) ;
233
+ check_assist_import_one_variations ! (
234
+ "std::fmt$0::Debug" ,
235
+ "std::fmt::Display" ,
236
+ "use {std::fmt::{Debug, Display}};"
237
+ ) ;
171
238
}
172
239
173
240
#[ test]
@@ -182,6 +249,11 @@ use std::fmt$0::Display;
182
249
use std::fmt::{Debug, Display};
183
250
" ,
184
251
) ;
252
+ check_assist_import_one_variations ! (
253
+ "std::fmt::Debug" ,
254
+ "std::fmt$0::Display" ,
255
+ "use {std::fmt::{Debug, Display}};"
256
+ ) ;
185
257
}
186
258
187
259
#[ test]
@@ -196,6 +268,11 @@ use std::fmt::Display;
196
268
use std::fmt::{self, Display};
197
269
" ,
198
270
) ;
271
+ check_assist_import_one_variations ! (
272
+ "std::fmt$0" ,
273
+ "std::fmt::Display" ,
274
+ "use {std::fmt::{self, Display}};"
275
+ ) ;
199
276
}
200
277
201
278
#[ test]
@@ -211,6 +288,15 @@ use std::{fmt::{self, Display}};
211
288
) ;
212
289
}
213
290
291
+ #[ test]
292
+ fn not_applicable_to_single_one_style_import ( ) {
293
+ cov_mark:: check!( resolve_top_use_tree_for_import_one) ;
294
+ check_assist_not_applicable_for_import_one (
295
+ merge_imports,
296
+ "use {std::{fmt, $0fmt::Display}};" ,
297
+ ) ;
298
+ }
299
+
214
300
#[ test]
215
301
fn skip_pub1 ( ) {
216
302
check_assist_not_applicable (
@@ -299,6 +385,7 @@ pub(in this::path) use std::fmt::{Debug, Display};
299
385
300
386
#[ test]
301
387
fn test_merge_nested ( ) {
388
+ cov_mark:: check!( merge_with_use_tree_neighbors) ;
302
389
check_assist (
303
390
merge_imports,
304
391
r"
@@ -335,6 +422,11 @@ use std::{fmt::{self, Debug}};
335
422
use std::{fmt::{self, Debug, Display, Write}};
336
423
" ,
337
424
) ;
425
+ check_assist_import_one_variations ! (
426
+ "std$0::{fmt::{Write, Display}}" ,
427
+ "std::{fmt::{self, Debug}}" ,
428
+ "use {std::{fmt::{self, Debug, Display, Write}}};"
429
+ ) ;
338
430
}
339
431
340
432
#[ test]
@@ -349,6 +441,11 @@ use std::{fmt::{Write, Display}};
349
441
use std::{fmt::{self, Debug, Display, Write}};
350
442
" ,
351
443
) ;
444
+ check_assist_import_one_variations ! (
445
+ "std$0::{fmt::{self, Debug}}" ,
446
+ "std::{fmt::{Write, Display}}" ,
447
+ "use {std::{fmt::{self, Debug, Display, Write}}};"
448
+ ) ;
352
449
}
353
450
354
451
#[ test]
@@ -375,7 +472,12 @@ use foo::{bar};
375
472
r"
376
473
use foo::{bar::{self}};
377
474
" ,
378
- )
475
+ ) ;
476
+ check_assist_import_one_variations ! (
477
+ "foo::$0{bar::{self}}" ,
478
+ "foo::{bar}" ,
479
+ "use {foo::{bar::{self}}};"
480
+ ) ;
379
481
}
380
482
381
483
#[ test]
@@ -389,7 +491,12 @@ use foo::{bar::{self}};
389
491
r"
390
492
use foo::{bar::{self}};
391
493
" ,
392
- )
494
+ ) ;
495
+ check_assist_import_one_variations ! (
496
+ "foo::$0{bar}" ,
497
+ "foo::{bar::{self}}" ,
498
+ "use {foo::{bar::{self}}};"
499
+ ) ;
393
500
}
394
501
395
502
#[ test]
@@ -403,7 +510,12 @@ use std::{fmt::{self, Display}};
403
510
r"
404
511
use std::{fmt::{self, Display, *}};
405
512
" ,
406
- )
513
+ ) ;
514
+ check_assist_import_one_variations ! (
515
+ "std$0::{fmt::*}" ,
516
+ "std::{fmt::{self, Display}}" ,
517
+ "use {std::{fmt::{self, Display, *}}};"
518
+ ) ;
407
519
}
408
520
409
521
#[ test]
@@ -417,7 +529,12 @@ use std::str;
417
529
r"
418
530
use std::{cell::*, str};
419
531
" ,
420
- )
532
+ ) ;
533
+ check_assist_import_one_variations ! (
534
+ "std$0::cell::*" ,
535
+ "std::str" ,
536
+ "use {std::{cell::*, str}};"
537
+ ) ;
421
538
}
422
539
423
540
#[ test]
@@ -431,7 +548,12 @@ use std::str::*;
431
548
r"
432
549
use std::{cell::*, str::*};
433
550
" ,
434
- )
551
+ ) ;
552
+ check_assist_import_one_variations ! (
553
+ "std$0::cell::*" ,
554
+ "std::str::*" ,
555
+ "use {std::{cell::*, str::*}};"
556
+ ) ;
435
557
}
436
558
437
559
#[ test]
@@ -524,10 +646,16 @@ use foo::bar::Baz;
524
646
use foo::{bar::Baz, *};
525
647
" ,
526
648
) ;
649
+ check_assist_import_one_variations ! (
650
+ "foo::$0*" ,
651
+ "foo::bar::Baz" ,
652
+ "use {foo::{bar::Baz, *}};"
653
+ ) ;
527
654
}
528
655
529
656
#[ test]
530
657
fn merge_selection_uses ( ) {
658
+ cov_mark:: check!( merge_with_selected_use_item_neighbors) ;
531
659
check_assist (
532
660
merge_imports,
533
661
r"
@@ -541,12 +669,30 @@ $0use std::fmt::Result;
541
669
use std::fmt::Error;
542
670
use std::fmt::{Debug, Display, Write};
543
671
use std::fmt::Result;
672
+ " ,
673
+ ) ;
674
+
675
+ cov_mark:: check!( merge_with_selected_use_item_neighbors) ;
676
+ check_assist_import_one (
677
+ merge_imports,
678
+ r"
679
+ use std::fmt::Error;
680
+ $0use std::fmt::Display;
681
+ use std::fmt::Debug;
682
+ use std::fmt::Write;
683
+ $0use std::fmt::Result;
684
+ " ,
685
+ r"
686
+ use std::fmt::Error;
687
+ use {std::fmt::{Debug, Display, Write}};
688
+ use std::fmt::Result;
544
689
" ,
545
690
) ;
546
691
}
547
692
548
693
#[ test]
549
694
fn merge_selection_use_trees ( ) {
695
+ cov_mark:: check!( merge_with_selected_use_tree_neighbors) ;
550
696
check_assist (
551
697
merge_imports,
552
698
r"
@@ -564,7 +710,9 @@ use std::{
564
710
fmt::Result,
565
711
};" ,
566
712
) ;
713
+
567
714
// FIXME: Remove redundant braces. See also unnecessary-braces diagnostic.
715
+ cov_mark:: check!( merge_with_selected_use_tree_neighbors) ;
568
716
check_assist (
569
717
merge_imports,
570
718
r"use std::$0{fmt::Display, fmt::Debug}$0;" ,
0 commit comments