@@ -2,12 +2,8 @@ use crate::assist_context::{AssistContext, Assists};
22use ide_db:: assists:: AssistId ;
33use syntax:: {
44 AstNode , SyntaxKind , T ,
5- ast:: {
6- self , HasGenericParams , HasName , HasVisibility ,
7- edit_in_place:: { HasVisibilityEdit , Indent } ,
8- make,
9- } ,
10- ted:: { self , Position } ,
5+ ast:: { self , HasGenericParams , HasName , HasVisibility , edit_in_place:: Indent , make} ,
6+ syntax_editor:: { Position , SyntaxEditor } ,
117} ;
128
139// NOTES :
@@ -88,8 +84,8 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
8884 return None ;
8985 }
9086
91- let assoc_items = impl_ast. assoc_item_list ( ) ?;
92- let first_element = assoc_items . assoc_items ( ) . next ( ) ;
87+ let impl_assoc_items = impl_ast. assoc_item_list ( ) ?;
88+ let first_element = impl_assoc_items . assoc_items ( ) . next ( ) ;
9389 first_element. as_ref ( ) ?;
9490
9591 let impl_name = impl_ast. self_ty ( ) ?;
@@ -99,20 +95,16 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
9995 "Generate trait from impl" ,
10096 impl_ast. syntax ( ) . text_range ( ) ,
10197 |builder| {
102- let impl_ast = builder. make_mut ( impl_ast) ;
103- let trait_items = assoc_items. clone_for_update ( ) ;
104- let impl_items = builder. make_mut ( assoc_items) ;
105- let impl_name = builder. make_mut ( impl_name) ;
106-
107- trait_items. assoc_items ( ) . for_each ( |item| {
108- strip_body ( & item) ;
109- remove_items_visibility ( & item) ;
110- } ) ;
111-
112- impl_items. assoc_items ( ) . for_each ( |item| {
113- remove_items_visibility ( & item) ;
114- } ) ;
115-
98+ let trait_items: ast:: AssocItemList = {
99+ let trait_items = impl_assoc_items. clone_subtree ( ) ;
100+ let mut trait_items_editor = SyntaxEditor :: new ( trait_items. syntax ( ) . clone ( ) ) ;
101+
102+ trait_items. assoc_items ( ) . for_each ( |item| {
103+ strip_body ( & mut trait_items_editor, & item) ;
104+ remove_items_visibility ( & mut trait_items_editor, & item) ;
105+ } ) ;
106+ ast:: AssocItemList :: cast ( trait_items_editor. finish ( ) . new_root ( ) . clone ( ) ) . unwrap ( )
107+ } ;
116108 let trait_ast = make:: trait_ (
117109 false ,
118110 "NewTrait" ,
@@ -130,17 +122,23 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
130122 trait_name_ref. syntax( ) . clone( ) . into( ) ,
131123 make:: tokens:: single_space( ) . into( ) ,
132124 make:: token( T ![ for ] ) . into( ) ,
125+ make:: tokens:: single_space( ) . into( ) ,
133126 ] ;
134127
135128 if let Some ( params) = impl_ast. generic_param_list ( ) {
136129 let gen_args = & params. to_generic_args ( ) . clone_for_update ( ) ;
137130 elements. insert ( 1 , gen_args. syntax ( ) . clone ( ) . into ( ) ) ;
138131 }
139132
140- ted:: insert_all ( Position :: before ( impl_name. syntax ( ) ) , elements) ;
133+ let mut editor = builder. make_editor ( impl_ast. syntax ( ) ) ;
134+ impl_assoc_items. assoc_items ( ) . for_each ( |item| {
135+ remove_items_visibility ( & mut editor, & item) ;
136+ } ) ;
137+
138+ editor. insert_all ( Position :: before ( impl_name. syntax ( ) ) , elements) ;
141139
142140 // Insert trait before TraitImpl
143- ted :: insert_all_raw (
141+ editor . insert_all (
144142 Position :: before ( impl_ast. syntax ( ) ) ,
145143 vec ! [
146144 trait_ast. syntax( ) . clone( ) . into( ) ,
@@ -150,31 +148,34 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
150148
151149 // Link the trait name & trait ref names together as a placeholder snippet group
152150 if let Some ( cap) = ctx. config . snippet_cap {
153- builder. add_placeholder_snippet_group (
154- cap,
155- vec ! [ trait_name. syntax( ) . clone( ) , trait_name_ref. syntax( ) . clone( ) ] ,
156- ) ;
151+ let placeholder = builder. make_placeholder_snippet ( cap) ;
152+ editor. add_annotation ( trait_name. syntax ( ) , placeholder) ;
153+ editor. add_annotation ( trait_name_ref. syntax ( ) , placeholder) ;
157154 }
155+
156+ builder. add_file_edits ( ctx. vfs_file_id ( ) , editor) ;
158157 } ,
159158 ) ;
160159
161160 Some ( ( ) )
162161}
163162
164163/// `E0449` Trait items always share the visibility of their trait
165- fn remove_items_visibility ( item : & ast:: AssocItem ) {
164+ fn remove_items_visibility ( editor : & mut SyntaxEditor , item : & ast:: AssocItem ) {
166165 if let Some ( has_vis) = ast:: AnyHasVisibility :: cast ( item. syntax ( ) . clone ( ) ) {
167166 if let Some ( vis) = has_vis. visibility ( )
168167 && let Some ( token) = vis. syntax ( ) . next_sibling_or_token ( )
169168 && token. kind ( ) == SyntaxKind :: WHITESPACE
170169 {
171- ted:: remove ( token) ;
170+ editor. delete ( token) ;
171+ }
172+ if let Some ( vis) = has_vis. visibility ( ) {
173+ editor. delete ( vis. syntax ( ) ) ;
172174 }
173- has_vis. set_visibility ( None ) ;
174175 }
175176}
176177
177- fn strip_body ( item : & ast:: AssocItem ) {
178+ fn strip_body ( editor : & mut SyntaxEditor , item : & ast:: AssocItem ) {
178179 if let ast:: AssocItem :: Fn ( f) = item
179180 && let Some ( body) = f. body ( )
180181 {
@@ -183,10 +184,10 @@ fn strip_body(item: &ast::AssocItem) {
183184 if let Some ( prev) = body. syntax ( ) . prev_sibling_or_token ( )
184185 && prev. kind ( ) == SyntaxKind :: WHITESPACE
185186 {
186- ted :: remove ( prev) ;
187+ editor . delete ( prev) ;
187188 }
188189
189- ted :: replace ( body. syntax ( ) , make:: tokens:: semicolon ( ) ) ;
190+ editor . replace ( body. syntax ( ) , make:: tokens:: semicolon ( ) ) ;
190191 } ;
191192}
192193
0 commit comments