11use 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+ } ;
36use syntax:: {
47 algo:: neighbor,
58 ast:: { self , edit_in_place:: Removable } ,
@@ -30,14 +33,36 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
3033 let ( target, edits) = if ctx. has_empty_selection ( ) {
3134 // Merge a neighbor
3235 let tree: ast:: UseTree = ctx. find_node_at_offset ( ) ?;
33- let target = tree. syntax ( ) . text_range ( ) ;
36+ let mut target = tree. syntax ( ) . text_range ( ) ;
3437
3538 let edits = if let Some ( use_item) = tree. syntax ( ) . parent ( ) . and_then ( ast:: Use :: cast) {
3639 let mut neighbor = next_prev ( ) . find_map ( |dir| neighbor ( & use_item, dir) ) . into_iter ( ) ;
37- use_item. try_merge_from ( & mut neighbor)
40+ use_item. try_merge_from ( & mut neighbor, & ctx . config . insert_use )
3841 } else {
3942 let mut neighbor = next_prev ( ) . find_map ( |dir| neighbor ( & tree, dir) ) . into_iter ( ) ;
40- tree. try_merge_from ( & mut neighbor)
43+ let mut edits = tree. clone ( ) . try_merge_from ( & mut neighbor, & ctx. config . insert_use ) ;
44+
45+ if edits. is_none ( ) && ctx. config . insert_use . granularity == ImportGranularity :: One {
46+ let one_tree = tree
47+ . parent_use_tree_list ( )
48+ . map ( |it| it. parent_use_tree ( ) . top_use_tree ( ) )
49+ . filter ( |top_tree| top_tree. path ( ) . is_none ( ) )
50+ . and_then ( |one_tree| {
51+ one_tree. syntax ( ) . parent ( ) . and_then ( ast:: Use :: cast) . zip ( Some ( one_tree) )
52+ } ) ;
53+ if let Some ( ( use_item, one_tree) ) = one_tree {
54+ let mut neighbor = next_prev ( )
55+ . find_map ( |dir| syntax:: algo:: neighbor ( & use_item, dir) )
56+ . into_iter ( ) ;
57+ edits = use_item. try_merge_from ( & mut neighbor, & ctx. config . insert_use ) ;
58+
59+ if edits. is_some ( ) {
60+ target = one_tree. syntax ( ) . text_range ( ) ;
61+ }
62+ }
63+ }
64+
65+ edits
4166 } ;
4267 ( target, edits?)
4368 } else {
@@ -54,10 +79,10 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
5479 let edits = match_ast ! {
5580 match first_selected {
5681 ast:: Use ( use_item) => {
57- use_item. try_merge_from( & mut selected_nodes. filter_map( ast:: Use :: cast) )
82+ use_item. try_merge_from( & mut selected_nodes. filter_map( ast:: Use :: cast) , & ctx . config . insert_use )
5883 } ,
5984 ast:: UseTree ( use_tree) => {
60- use_tree. try_merge_from( & mut selected_nodes. filter_map( ast:: UseTree :: cast) )
85+ use_tree. try_merge_from( & mut selected_nodes. filter_map( ast:: UseTree :: cast) , & ctx . config . insert_use )
6186 } ,
6287 _ => return None ,
6388 }
@@ -89,11 +114,15 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
89114}
90115
91116trait Merge : AstNode + Clone {
92- fn try_merge_from ( self , items : & mut dyn Iterator < Item = Self > ) -> Option < Vec < Edit > > {
117+ fn try_merge_from (
118+ self ,
119+ items : & mut dyn Iterator < Item = Self > ,
120+ cfg : & InsertUseConfig ,
121+ ) -> Option < Vec < Edit > > {
93122 let mut edits = Vec :: new ( ) ;
94123 let mut merged = self . clone ( ) ;
95124 for item in items {
96- merged = merged. try_merge ( & item) ?;
125+ merged = merged. try_merge ( & item, cfg ) ?;
97126 edits. push ( Edit :: Remove ( item. into_either ( ) ) ) ;
98127 }
99128 if !edits. is_empty ( ) {
@@ -103,21 +132,25 @@ trait Merge: AstNode + Clone {
103132 None
104133 }
105134 }
106- fn try_merge ( & self , other : & Self ) -> Option < Self > ;
135+ fn try_merge ( & self , other : & Self , cfg : & InsertUseConfig ) -> Option < Self > ;
107136 fn into_either ( self ) -> Either < ast:: Use , ast:: UseTree > ;
108137}
109138
110139impl Merge for ast:: Use {
111- fn try_merge ( & self , other : & Self ) -> Option < Self > {
112- try_merge_imports ( self , other, MergeBehavior :: Crate )
140+ fn try_merge ( & self , other : & Self , cfg : & InsertUseConfig ) -> Option < Self > {
141+ let mb = match cfg. granularity {
142+ ImportGranularity :: One => MergeBehavior :: One ,
143+ _ => MergeBehavior :: Crate ,
144+ } ;
145+ try_merge_imports ( self , other, mb)
113146 }
114147 fn into_either ( self ) -> Either < ast:: Use , ast:: UseTree > {
115148 Either :: Left ( self )
116149 }
117150}
118151
119152impl Merge for ast:: UseTree {
120- fn try_merge ( & self , other : & Self ) -> Option < Self > {
153+ fn try_merge ( & self , other : & Self , _ : & InsertUseConfig ) -> Option < Self > {
121154 try_merge_trees ( self , other, MergeBehavior :: Crate )
122155 }
123156 fn into_either ( self ) -> Either < ast:: Use , ast:: UseTree > {
@@ -138,10 +171,35 @@ impl Edit {
138171
139172#[ cfg( test) ]
140173mod tests {
141- use crate :: tests:: { check_assist, check_assist_not_applicable} ;
174+ use crate :: tests:: { check_assist, check_assist_import_one , check_assist_not_applicable} ;
142175
143176 use super :: * ;
144177
178+ macro_rules! check_assist_import_one_variations {
179+ ( $first: literal, $second: literal, $expected: literal) => {
180+ check_assist_import_one(
181+ merge_imports,
182+ concat!( concat!( "use " , $first, ";" ) , concat!( "use " , $second, ";" ) ) ,
183+ $expected,
184+ ) ;
185+ check_assist_import_one(
186+ merge_imports,
187+ concat!( concat!( "use {" , $first, "};" ) , concat!( "use " , $second, ";" ) ) ,
188+ $expected,
189+ ) ;
190+ check_assist_import_one(
191+ merge_imports,
192+ concat!( concat!( "use " , $first, ";" ) , concat!( "use {" , $second, "};" ) ) ,
193+ $expected,
194+ ) ;
195+ check_assist_import_one(
196+ merge_imports,
197+ concat!( concat!( "use {" , $first, "};" ) , concat!( "use {" , $second, "};" ) ) ,
198+ $expected,
199+ ) ;
200+ } ;
201+ }
202+
145203 #[ test]
146204 fn test_merge_equal ( ) {
147205 check_assist (
@@ -153,7 +211,12 @@ use std::fmt::{Display, Debug};
153211 r"
154212use std::fmt::{Display, Debug};
155213" ,
156- )
214+ ) ;
215+ check_assist_import_one_variations ! (
216+ "std::fmt$0::{Display, Debug}" ,
217+ "std::fmt::{Display, Debug}" ,
218+ "use {std::fmt::{Display, Debug}};"
219+ ) ;
157220 }
158221
159222 #[ test]
@@ -167,7 +230,12 @@ use std::fmt::Display;
167230 r"
168231use std::fmt::{Debug, Display};
169232" ,
170- )
233+ ) ;
234+ check_assist_import_one_variations ! (
235+ "std::fmt$0::Debug" ,
236+ "std::fmt::Display" ,
237+ "use {std::fmt::{Debug, Display}};"
238+ ) ;
171239 }
172240
173241 #[ test]
@@ -182,6 +250,11 @@ use std::fmt$0::Display;
182250use std::fmt::{Debug, Display};
183251" ,
184252 ) ;
253+ check_assist_import_one_variations ! (
254+ "std::fmt::Debug" ,
255+ "std::fmt$0::Display" ,
256+ "use {std::fmt::{Debug, Display}};"
257+ ) ;
185258 }
186259
187260 #[ test]
@@ -196,6 +269,11 @@ use std::fmt::Display;
196269use std::fmt::{self, Display};
197270" ,
198271 ) ;
272+ check_assist_import_one_variations ! (
273+ "std::fmt$0" ,
274+ "std::fmt::Display" ,
275+ "use {std::fmt::{self, Display}};"
276+ ) ;
199277 }
200278
201279 #[ test]
@@ -207,6 +285,15 @@ use std::{fmt, $0fmt::Display};
207285" ,
208286 r"
209287use std::{fmt::{self, Display}};
288+ " ,
289+ ) ;
290+ check_assist_import_one (
291+ merge_imports,
292+ r"
293+ use {std::{fmt, $0fmt::Display}};
294+ " ,
295+ r"
296+ use {std::{fmt::{self, Display}}};
210297" ,
211298 ) ;
212299 }
@@ -306,6 +393,15 @@ use std::{fmt$0::Debug, fmt::Display};
306393" ,
307394 r"
308395use std::{fmt::{Debug, Display}};
396+ " ,
397+ ) ;
398+ check_assist_import_one (
399+ merge_imports,
400+ r"
401+ use {std::{fmt$0::Debug, fmt::Display}};
402+ " ,
403+ r"
404+ use {std::{fmt::{Debug, Display}}};
309405" ,
310406 ) ;
311407 }
@@ -319,6 +415,15 @@ use std::{fmt::Debug, fmt$0::Display};
319415" ,
320416 r"
321417use std::{fmt::{Debug, Display}};
418+ " ,
419+ ) ;
420+ check_assist_import_one (
421+ merge_imports,
422+ r"
423+ use {std::{fmt::Debug, fmt$0::Display}};
424+ " ,
425+ r"
426+ use {std::{fmt::{Debug, Display}}};
322427" ,
323428 ) ;
324429 }
@@ -335,6 +440,11 @@ use std::{fmt::{self, Debug}};
335440use std::{fmt::{self, Debug, Display, Write}};
336441" ,
337442 ) ;
443+ check_assist_import_one_variations ! (
444+ "std$0::{fmt::{Write, Display}}" ,
445+ "std::{fmt::{self, Debug}}" ,
446+ "use {std::{fmt::{self, Debug, Display, Write}}};"
447+ ) ;
338448 }
339449
340450 #[ test]
@@ -349,6 +459,11 @@ use std::{fmt::{Write, Display}};
349459use std::{fmt::{self, Debug, Display, Write}};
350460" ,
351461 ) ;
462+ check_assist_import_one_variations ! (
463+ "std$0::{fmt::{self, Debug}}" ,
464+ "std::{fmt::{Write, Display}}" ,
465+ "use {std::{fmt::{self, Debug, Display, Write}}};"
466+ ) ;
352467 }
353468
354469 #[ test]
@@ -360,6 +475,15 @@ use std::{fmt$0::{self, Debug}, fmt::{Write, Display}};
360475" ,
361476 r"
362477use std::{fmt::{self, Debug, Display, Write}};
478+ " ,
479+ ) ;
480+ check_assist_import_one (
481+ merge_imports,
482+ r"
483+ use {std::{fmt$0::{self, Debug}, fmt::{Write, Display}}};
484+ " ,
485+ r"
486+ use {std::{fmt::{self, Debug, Display, Write}}};
363487" ,
364488 ) ;
365489 }
@@ -375,7 +499,12 @@ use foo::{bar};
375499 r"
376500use foo::{bar::{self}};
377501" ,
378- )
502+ ) ;
503+ check_assist_import_one_variations ! (
504+ "foo::$0{bar::{self}}" ,
505+ "foo::{bar}" ,
506+ "use {foo::{bar::{self}}};"
507+ ) ;
379508 }
380509
381510 #[ test]
@@ -389,7 +518,12 @@ use foo::{bar::{self}};
389518 r"
390519use foo::{bar::{self}};
391520" ,
392- )
521+ ) ;
522+ check_assist_import_one_variations ! (
523+ "foo::$0{bar}" ,
524+ "foo::{bar::{self}}" ,
525+ "use {foo::{bar::{self}}};"
526+ ) ;
393527 }
394528
395529 #[ test]
@@ -403,7 +537,12 @@ use std::{fmt::{self, Display}};
403537 r"
404538use std::{fmt::{self, Display, *}};
405539" ,
406- )
540+ ) ;
541+ check_assist_import_one_variations ! (
542+ "std$0::{fmt::*}" ,
543+ "std::{fmt::{self, Display}}" ,
544+ "use {std::{fmt::{self, Display, *}}};"
545+ ) ;
407546 }
408547
409548 #[ test]
@@ -417,7 +556,12 @@ use std::str;
417556 r"
418557use std::{cell::*, str};
419558" ,
420- )
559+ ) ;
560+ check_assist_import_one_variations ! (
561+ "std$0::cell::*" ,
562+ "std::str" ,
563+ "use {std::{cell::*, str}};"
564+ ) ;
421565 }
422566
423567 #[ test]
@@ -431,7 +575,12 @@ use std::str::*;
431575 r"
432576use std::{cell::*, str::*};
433577" ,
434- )
578+ ) ;
579+ check_assist_import_one_variations ! (
580+ "std$0::cell::*" ,
581+ "std::str::*" ,
582+ "use {std::{cell::*, str::*}};"
583+ ) ;
435584 }
436585
437586 #[ test]
@@ -524,6 +673,11 @@ use foo::bar::Baz;
524673use foo::{bar::Baz, *};
525674" ,
526675 ) ;
676+ check_assist_import_one_variations ! (
677+ "foo::$0*" ,
678+ "foo::bar::Baz" ,
679+ "use {foo::{bar::Baz, *}};"
680+ ) ;
527681 }
528682
529683 #[ test]
@@ -541,6 +695,21 @@ $0use std::fmt::Result;
541695use std::fmt::Error;
542696use std::fmt::{Debug, Display, Write};
543697use std::fmt::Result;
698+ " ,
699+ ) ;
700+ check_assist_import_one (
701+ merge_imports,
702+ r"
703+ use std::fmt::Error;
704+ $0use std::fmt::Display;
705+ use std::fmt::Debug;
706+ use std::fmt::Write;
707+ $0use std::fmt::Result;
708+ " ,
709+ r"
710+ use std::fmt::Error;
711+ use {std::fmt::{Debug, Display, Write}};
712+ use std::fmt::Result;
544713" ,
545714 ) ;
546715 }
0 commit comments