@@ -4,10 +4,10 @@ use ide_db::{
44 defs:: { Definition , NameRefClass } ,
55 search:: SearchScope ,
66} ;
7+ use stdx:: never;
78use syntax:: {
8- algo:: SyntaxRewriter ,
99 ast:: { self , make} ,
10- AstNode , Direction , SyntaxNode , SyntaxToken , T ,
10+ ted , AstNode , Direction , SyntaxNode , SyntaxToken , T ,
1111} ;
1212
1313use crate :: {
@@ -42,6 +42,7 @@ use crate::{
4242// ```
4343pub ( crate ) fn expand_glob_import ( acc : & mut Assists , ctx : & AssistContext ) -> Option < ( ) > {
4444 let star = ctx. find_token_syntax_at_offset ( T ! [ * ] ) ?;
45+ let use_tree = star. parent ( ) . and_then ( ast:: UseTree :: cast) ?;
4546 let ( parent, mod_path) = find_parent_and_path ( & star) ?;
4647 let target_module = match ctx. sema . resolve_path ( & mod_path) ? {
4748 PathResolution :: Def ( ModuleDef :: Module ( it) ) => it,
@@ -53,17 +54,39 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
5354
5455 let refs_in_target = find_refs_in_mod ( ctx, target_module, Some ( current_module) ) ?;
5556 let imported_defs = find_imported_defs ( ctx, star) ?;
56- let names_to_import = find_names_to_import ( ctx, refs_in_target, imported_defs) ;
5757
5858 let target = parent. clone ( ) . either ( |n| n. syntax ( ) . clone ( ) , |n| n. syntax ( ) . clone ( ) ) ;
5959 acc. add (
6060 AssistId ( "expand_glob_import" , AssistKind :: RefactorRewrite ) ,
6161 "Expand glob import" ,
6262 target. text_range ( ) ,
6363 |builder| {
64- let mut rewriter = SyntaxRewriter :: default ( ) ;
65- replace_ast ( & mut rewriter, parent, mod_path, names_to_import) ;
66- builder. rewrite ( rewriter) ;
64+ let use_tree = builder. make_ast_mut ( use_tree) ;
65+
66+ let names_to_import = find_names_to_import ( ctx, refs_in_target, imported_defs) ;
67+ let expanded = make:: use_tree_list ( names_to_import. iter ( ) . map ( |n| {
68+ let path =
69+ make:: path_unqualified ( make:: path_segment ( make:: name_ref ( & n. to_string ( ) ) ) ) ;
70+ make:: use_tree ( path, None , None , false )
71+ } ) )
72+ . clone_for_update ( ) ;
73+
74+ match use_tree. star_token ( ) {
75+ Some ( star) => {
76+ let needs_braces = use_tree. path ( ) . is_some ( ) && names_to_import. len ( ) > 1 ;
77+ if needs_braces {
78+ ted:: replace ( star, expanded. syntax ( ) )
79+ } else {
80+ let without_braces = expanded
81+ . syntax ( )
82+ . children_with_tokens ( )
83+ . filter ( |child| !matches ! ( child. kind( ) , T ![ '{' ] | T ![ '}' ] ) )
84+ . collect ( ) ;
85+ ted:: replace_with_many ( star, without_braces)
86+ }
87+ }
88+ None => never ! ( ) ,
89+ }
6790 } ,
6891 )
6992}
@@ -232,53 +255,6 @@ fn find_names_to_import(
232255 used_refs. 0 . iter ( ) . map ( |r| r. visible_name . clone ( ) ) . collect ( )
233256}
234257
235- fn replace_ast (
236- rewriter : & mut SyntaxRewriter ,
237- parent : Either < ast:: UseTree , ast:: UseTreeList > ,
238- path : ast:: Path ,
239- names_to_import : Vec < Name > ,
240- ) {
241- let existing_use_trees = match parent. clone ( ) {
242- Either :: Left ( _) => vec ! [ ] ,
243- Either :: Right ( u) => u
244- . use_trees ( )
245- . filter ( |n|
246- // filter out star
247- n. star_token ( ) . is_none ( ) )
248- . collect ( ) ,
249- } ;
250-
251- let new_use_trees: Vec < ast:: UseTree > = names_to_import
252- . iter ( )
253- . map ( |n| {
254- let path = make:: path_unqualified ( make:: path_segment ( make:: name_ref ( & n. to_string ( ) ) ) ) ;
255- make:: use_tree ( path, None , None , false )
256- } )
257- . collect ( ) ;
258-
259- let use_trees = [ & existing_use_trees[ ..] , & new_use_trees[ ..] ] . concat ( ) ;
260-
261- match use_trees. as_slice ( ) {
262- [ name] => {
263- if let Some ( end_path) = name. path ( ) {
264- rewriter. replace_ast (
265- & parent. left_or_else ( |tl| tl. parent_use_tree ( ) ) ,
266- & make:: use_tree ( make:: path_concat ( path, end_path) , None , None , false ) ,
267- ) ;
268- }
269- }
270- names => match & parent {
271- Either :: Left ( parent) => rewriter. replace_ast (
272- parent,
273- & make:: use_tree ( path, Some ( make:: use_tree_list ( names. to_owned ( ) ) ) , None , false ) ,
274- ) ,
275- Either :: Right ( parent) => {
276- rewriter. replace_ast ( parent, & make:: use_tree_list ( names. to_owned ( ) ) )
277- }
278- } ,
279- } ;
280- }
281-
282258#[ cfg( test) ]
283259mod tests {
284260 use crate :: tests:: { check_assist, check_assist_not_applicable} ;
@@ -350,7 +326,7 @@ mod foo {
350326 pub fn f() {}
351327}
352328
353- use foo::{f, Baz, Bar};
329+ use foo::{Baz, Bar, f };
354330
355331fn qux(bar: Bar, baz: Baz) {
356332 f();
@@ -389,7 +365,7 @@ mod foo {
389365}
390366
391367use foo::Bar;
392- use foo::{f, Baz };
368+ use foo::{Baz, f };
393369
394370fn qux(bar: Bar, baz: Baz) {
395371 f();
@@ -439,7 +415,7 @@ mod foo {
439415 }
440416}
441417
442- use foo::{bar::{f, Baz, Bar}, baz::*};
418+ use foo::{bar::{Baz, Bar, f }, baz::*};
443419
444420fn qux(bar: Bar, baz: Baz) {
445421 f();
@@ -891,7 +867,7 @@ mod foo {
891867 pub struct Bar;
892868}
893869
894- use foo::Bar;
870+ use foo::{ Bar} ;
895871
896872struct Baz {
897873 bar: Bar
0 commit comments