@@ -122,15 +122,18 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_, '_>) ->
122122 let ( usages_to_be_processed, record_fields, use_stmts_to_be_inserted) =
123123 module. get_usages_and_record_fields ( ctx, module_text_range) ;
124124
125+ let make = SyntaxFactory :: without_mappings ( ) ;
126+
125127 builder. edit_file ( ctx. vfs_file_id ( ) ) ;
126128 use_stmts_to_be_inserted. into_iter ( ) . for_each ( |( _, use_stmt) | {
127129 builder. insert ( ctx. selection_trimmed ( ) . end ( ) , format ! ( "\n {use_stmt}" ) ) ;
128130 } ) ;
129131
130- let import_items = module. resolve_imports ( curr_parent_module, ctx) ;
131- module. change_visibility ( record_fields) ;
132+ let import_items = module. resolve_imports ( curr_parent_module, ctx, & make ) ;
133+ module. change_visibility ( record_fields, & make ) ;
132134
133- let module_def = generate_module_def ( & impl_parent, & module) . indent ( old_item_indent) ;
135+ let module_def =
136+ generate_module_def ( & impl_parent, & module, & make) . indent ( old_item_indent) ;
134137
135138 let mut usages_to_be_processed_for_cur_file = vec ! [ ] ;
136139 for ( file_id, usages) in usages_to_be_processed {
@@ -186,6 +189,7 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_, '_>) ->
186189fn generate_module_def (
187190 parent_impl : & Option < ast:: Impl > ,
188191 Module { name, body_items, use_items } : & Module ,
192+ make : & SyntaxFactory ,
189193) -> ast:: Module {
190194 let items: Vec < _ > = if let Some ( impl_) = parent_impl. as_ref ( )
191195 && let Some ( self_ty) = impl_. self_ty ( )
@@ -196,11 +200,15 @@ fn generate_module_def(
196200 . filter_map ( ast:: AssocItem :: cast)
197201 . map ( |it| it. indent ( IndentLevel ( 1 ) ) )
198202 . collect_vec ( ) ;
199- let assoc_item_list = make:: assoc_item_list ( Some ( assoc_items) ) . clone_for_update ( ) ;
200- let impl_ = impl_. reset_indent ( ) ;
201- ted:: replace ( impl_. get_or_create_assoc_item_list ( ) . syntax ( ) , assoc_item_list. syntax ( ) ) ;
203+ let impl_reset = impl_. reset_indent ( ) ;
204+ let ( editor, impl_root) = SyntaxEditor :: with_ast_node ( & impl_reset) ;
205+ let assoc_item_list = editor. make ( ) . assoc_item_list ( assoc_items) ;
206+ if let Some ( existing_list) = impl_root. assoc_item_list ( ) {
207+ editor. replace ( existing_list. syntax ( ) , assoc_item_list. syntax ( ) ) ;
208+ }
209+ let impl_ = ast:: Impl :: cast ( editor. finish ( ) . new_root ( ) . clone ( ) ) . unwrap ( ) ;
202210 // Add the import for enum/struct corresponding to given impl block
203- let use_impl = make_use_stmt_of_node_with_super ( self_ty. syntax ( ) ) ;
211+ let use_impl = make_use_stmt_of_node_with_super ( self_ty. syntax ( ) , make ) ;
204212 once ( use_impl)
205213 . chain ( use_items. iter ( ) . cloned ( ) )
206214 . chain ( once ( ast:: Item :: Impl ( impl_) ) )
@@ -210,19 +218,18 @@ fn generate_module_def(
210218 } ;
211219
212220 let items = items. into_iter ( ) . map ( |it| it. reset_indent ( ) . indent ( IndentLevel ( 1 ) ) ) . collect_vec ( ) ;
213- let module_body = make:: item_list ( Some ( items) ) ;
214-
215- let module_name = make:: name ( name) ;
216- make:: mod_ ( module_name, Some ( module_body) )
221+ let module_body = make. item_list ( items) ;
222+ let module_name = make. name ( name) ;
223+ make. mod_ ( module_name, Some ( module_body) )
217224}
218225
219- fn make_use_stmt_of_node_with_super ( node_syntax : & SyntaxNode ) -> ast:: Item {
220- let super_path = make:: ext:: ident_path ( "super" ) ;
221- let node_path = make:: ext:: ident_path ( & node_syntax. to_string ( ) ) ;
222- let use_ = make:: use_ (
226+ fn make_use_stmt_of_node_with_super ( node_syntax : & SyntaxNode , make : & SyntaxFactory ) -> ast:: Item {
227+ let super_path = make. ident_path ( "super" ) ;
228+ let node_path = make. path_from_text ( & node_syntax. to_string ( ) ) ;
229+ let use_ = make. use_ (
230+ [ ] ,
223231 None ,
224- None ,
225- make:: use_tree ( make:: join_paths ( vec ! [ super_path, node_path] ) , None , None , false ) ,
232+ make. use_tree ( make. path_concat ( super_path, node_path) , None , None , false ) ,
226233 ) ;
227234
228235 ast:: Item :: from ( use_)
@@ -386,18 +393,30 @@ impl Module {
386393 if use_. syntax ( ) . parent ( ) . is_some_and ( |parent| parent == covering_node)
387394 && use_stmts_set. insert ( use_. syntax ( ) . text_range ( ) . start ( ) )
388395 {
389- let use_ = use_stmts_to_be_inserted
390- . entry ( use_. syntax ( ) . text_range ( ) . start ( ) )
391- . or_insert_with ( || use_. clone_subtree ( ) . clone_for_update ( ) ) ;
392- for seg in use_
393- . syntax ( )
394- . descendants ( )
395- . filter_map ( ast:: NameRef :: cast)
396- . filter ( |seg| seg. syntax ( ) . to_string ( ) == name_ref. to_string ( ) )
397- {
398- let new_ref = make:: path_from_text ( & format ! ( "{mod_name}::{seg}" ) )
399- . clone_for_update ( ) ;
400- ted:: replace ( seg. syntax ( ) . parent ( ) ?, new_ref. syntax ( ) ) ;
396+ let key = use_. syntax ( ) . text_range ( ) . start ( ) ;
397+ let entry =
398+ use_stmts_to_be_inserted. entry ( key) . or_insert_with ( || use_. clone ( ) ) ;
399+ let ( editor, edit_root) = SyntaxEditor :: with_ast_node ( & * entry) ;
400+ let replacements: Vec < _ > = {
401+ let make = editor. make ( ) ;
402+ edit_root
403+ . syntax ( )
404+ . descendants ( )
405+ . filter_map ( ast:: NameRef :: cast)
406+ . filter ( |seg| seg. syntax ( ) . to_string ( ) == name_ref. to_string ( ) )
407+ . filter_map ( |seg| {
408+ Some ( (
409+ seg. syntax ( ) . parent ( ) ?,
410+ make. path_from_text ( & format ! ( "{mod_name}::{seg}" ) ) ,
411+ ) )
412+ } )
413+ . collect ( )
414+ } ;
415+ if !replacements. is_empty ( ) {
416+ for ( parent, new_ref) in & replacements {
417+ editor. replace ( parent, new_ref. syntax ( ) ) ;
418+ }
419+ * entry = ast:: Use :: cast ( editor. finish ( ) . new_root ( ) . clone ( ) ) . unwrap ( ) ;
401420 }
402421 }
403422 }
@@ -408,18 +427,23 @@ impl Module {
408427 }
409428 }
410429
411- fn change_visibility ( & mut self , record_fields : Vec < SyntaxNode > ) {
430+ fn change_visibility ( & mut self , record_fields : Vec < SyntaxNode > , make : & SyntaxFactory ) {
431+ for item in & mut self . body_items {
432+ let ( _, root) = SyntaxEditor :: with_ast_node ( & item. reset_indent ( ) ) ;
433+ * item = root;
434+ }
435+
412436 let ( mut replacements, record_field_parents, impls) =
413- get_replacements_for_visibility_change ( & mut self . body_items , false ) ;
437+ get_replacements_for_visibility_change ( & self . body_items ) ;
414438
415- let mut impl_items = impls
439+ let impl_items = impls
416440 . into_iter ( )
417441 . flat_map ( |impl_| impl_. syntax ( ) . descendants ( ) )
418442 . filter_map ( ast:: Item :: cast)
419443 . collect_vec ( ) ;
420444
421445 let ( mut impl_item_replacements, _, _) =
422- get_replacements_for_visibility_change ( & mut impl_items, true ) ;
446+ get_replacements_for_visibility_change ( & impl_items) ;
423447
424448 replacements. append ( & mut impl_item_replacements) ;
425449
@@ -433,24 +457,47 @@ impl Module {
433457 }
434458 }
435459
436- for ( vis, syntax) in replacements {
437- let item = syntax. children_with_tokens ( ) . find ( |node_or_token| {
438- match node_or_token. kind ( ) {
439- // We're skipping comments, doc comments, and attribute macros that may precede the keyword
440- // that the visibility should be placed before.
441- SyntaxKind :: COMMENT | SyntaxKind :: ATTR | SyntaxKind :: WHITESPACE => false ,
442- _ => true ,
443- }
444- } ) ;
460+ for body_item in & mut self . body_items {
461+ let insert_targets: Vec < _ > = replacements
462+ . iter ( )
463+ . filter ( |( vis, syntax) | {
464+ vis. is_none ( )
465+ && ( syntax == body_item. syntax ( )
466+ || syntax. ancestors ( ) . any ( |a| & a == body_item. syntax ( ) ) )
467+ } )
468+ . filter_map ( |( _, syntax) | {
469+ syntax. children_with_tokens ( ) . find ( |nt| {
470+ !matches ! (
471+ nt. kind( ) ,
472+ SyntaxKind :: COMMENT | SyntaxKind :: ATTR | SyntaxKind :: WHITESPACE
473+ )
474+ } )
475+ } )
476+ . collect ( ) ;
445477
446- add_change_vis ( vis, item) ;
478+ if insert_targets. is_empty ( ) {
479+ continue ;
480+ }
481+
482+ let ( editor, _) = SyntaxEditor :: new ( body_item. syntax ( ) . clone ( ) ) ;
483+ for target in insert_targets {
484+ editor. insert_all (
485+ Position :: before ( target) ,
486+ vec ! [
487+ make. visibility_pub_crate( ) . syntax( ) . clone( ) . into( ) ,
488+ make. whitespace( " " ) . into( ) ,
489+ ] ,
490+ ) ;
491+ }
492+ * body_item = ast:: Item :: cast ( editor. finish ( ) . new_root ( ) . clone ( ) ) . unwrap ( ) ;
447493 }
448494 }
449495
450496 fn resolve_imports (
451497 & mut self ,
452498 module : Option < ast:: Module > ,
453499 ctx : & AssistContext < ' _ , ' _ > ,
500+ make : & SyntaxFactory ,
454501 ) -> Vec < TextRange > {
455502 let mut imports_to_remove = vec ! [ ] ;
456503 let mut node_set = FxHashSet :: default ( ) ;
@@ -477,7 +524,8 @@ impl Module {
477524 } )
478525 . for_each ( |( node, def) | {
479526 if node_set. insert ( node. to_string ( ) )
480- && let Some ( import) = self . process_def_in_sel ( def, & node, & module, ctx)
527+ && let Some ( import) =
528+ self . process_def_in_sel ( def, & node, & module, ctx, make)
481529 {
482530 check_intersection_and_push ( & mut imports_to_remove, import) ;
483531 }
@@ -493,6 +541,7 @@ impl Module {
493541 use_node : & SyntaxNode ,
494542 curr_parent_module : & Option < ast:: Module > ,
495543 ctx : & AssistContext < ' _ , ' _ > ,
544+ make : & SyntaxFactory ,
496545 ) -> Option < TextRange > {
497546 //We only need to find in the current file
498547 let selection_range = ctx. selection_trimmed ( ) ;
@@ -568,7 +617,7 @@ impl Module {
568617 // mod -> ust_stmt transversal
569618 // true | false -> super import insertion
570619 // true | true -> super import insertion
571- let super_use_node = make_use_stmt_of_node_with_super ( use_node) ;
620+ let super_use_node = make_use_stmt_of_node_with_super ( use_node, make ) ;
572621 self . use_items . insert ( 0 , super_use_node) ;
573622 }
574623 None => { }
@@ -591,14 +640,14 @@ impl Module {
591640 if !first_path_in_use_tree_str. contains ( "super" )
592641 && !first_path_in_use_tree_str. contains ( "crate" )
593642 {
594- let super_path = make:: ext :: ident_path ( "super" ) ;
643+ let super_path = make. ident_path ( "super" ) ;
595644 use_tree_str. push ( super_path) ;
596645 }
597646 }
598647
599648 use_tree_paths = Some ( use_tree_str) ;
600649 } else if def_in_mod && def_out_sel {
601- let super_use_node = make_use_stmt_of_node_with_super ( use_node) ;
650+ let super_use_node = make_use_stmt_of_node_with_super ( use_node, make ) ;
602651 self . use_items . insert ( 0 , super_use_node) ;
603652 }
604653 }
@@ -610,7 +659,7 @@ impl Module {
610659 && let Some ( first_path_in_use_tree) = use_tree_paths. first ( )
611660 && first_path_in_use_tree. to_string ( ) . contains ( "super" )
612661 {
613- use_tree_paths. insert ( 0 , make:: ext :: ident_path ( "super" ) ) ;
662+ use_tree_paths. insert ( 0 , make. ident_path ( "super" ) ) ;
614663 }
615664
616665 let is_item = matches ! (
@@ -625,12 +674,12 @@ impl Module {
625674 | Definition :: TypeAlias ( _)
626675 ) ;
627676
628- if ( def_out_sel || !is_item) && use_stmt_not_in_sel {
629- let use_ = make :: use_ (
630- None ,
631- None ,
632- make :: use_tree ( make :: join_paths ( use_tree_paths ) , None , None , false ) ,
633- ) ;
677+ if ( def_out_sel || !is_item)
678+ && use_stmt_not_in_sel
679+ && let Some ( joined ) =
680+ use_tree_paths . into_iter ( ) . reduce ( |acc , p| make . path_concat ( acc , p ) )
681+ {
682+ let use_ = make . use_ ( [ ] , None , make . use_tree ( joined , None , None , false ) ) ;
634683 self . use_items . insert ( 0 , ast:: Item :: from ( use_) ) ;
635684 }
636685 }
@@ -741,8 +790,7 @@ fn check_def_in_mod_and_out_sel(
741790}
742791
743792fn get_replacements_for_visibility_change (
744- items : & mut [ ast:: Item ] ,
745- is_clone_for_updated : bool ,
793+ items : & [ ast:: Item ] ,
746794) -> (
747795 Vec < ( Option < ast:: Visibility > , SyntaxNode ) > ,
748796 Vec < ( Option < ast:: Visibility > , SyntaxNode ) > ,
@@ -753,9 +801,6 @@ fn get_replacements_for_visibility_change(
753801 let mut impls = Vec :: new ( ) ;
754802
755803 for item in items {
756- if !is_clone_for_updated {
757- * item = item. clone_for_update ( ) ;
758- }
759804 //Use stmts are ignored
760805 macro_rules! push_to_replacement {
761806 ( $it: ident) => {
@@ -812,15 +857,6 @@ fn get_use_tree_paths_from_path(
812857 Some ( use_tree_str)
813858}
814859
815- fn add_change_vis ( vis : Option < ast:: Visibility > , node_or_token_opt : Option < syntax:: SyntaxElement > ) {
816- if vis. is_none ( )
817- && let Some ( node_or_token) = node_or_token_opt
818- {
819- let pub_crate_vis = make:: visibility_pub_crate ( ) . clone_for_update ( ) ;
820- ted:: insert ( ted:: Position :: before ( node_or_token) , pub_crate_vis. syntax ( ) ) ;
821- }
822- }
823-
824860fn indent_range_before_given_node ( node : & SyntaxNode ) -> Option < TextRange > {
825861 node. siblings_with_tokens ( syntax:: Direction :: Prev )
826862 . find ( |x| x. kind ( ) == WHITESPACE )
0 commit comments