@@ -2,12 +2,8 @@ use crate::assist_context::{AssistContext, Assists};
2
2
use ide_db:: assists:: AssistId ;
3
3
use syntax:: {
4
4
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 } ,
11
7
} ;
12
8
13
9
// NOTES :
@@ -88,8 +84,8 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
88
84
return None ;
89
85
}
90
86
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 ( ) ;
93
89
first_element. as_ref ( ) ?;
94
90
95
91
let impl_name = impl_ast. self_ty ( ) ?;
@@ -99,20 +95,16 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
99
95
"Generate trait from impl" ,
100
96
impl_ast. syntax ( ) . text_range ( ) ,
101
97
|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
+ } ;
116
108
let trait_ast = make:: trait_ (
117
109
false ,
118
110
"NewTrait" ,
@@ -130,17 +122,23 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
130
122
trait_name_ref. syntax( ) . clone( ) . into( ) ,
131
123
make:: tokens:: single_space( ) . into( ) ,
132
124
make:: token( T ![ for ] ) . into( ) ,
125
+ make:: tokens:: single_space( ) . into( ) ,
133
126
] ;
134
127
135
128
if let Some ( params) = impl_ast. generic_param_list ( ) {
136
129
let gen_args = & params. to_generic_args ( ) . clone_for_update ( ) ;
137
130
elements. insert ( 1 , gen_args. syntax ( ) . clone ( ) . into ( ) ) ;
138
131
}
139
132
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) ;
141
139
142
140
// Insert trait before TraitImpl
143
- ted :: insert_all_raw (
141
+ editor . insert_all (
144
142
Position :: before ( impl_ast. syntax ( ) ) ,
145
143
vec ! [
146
144
trait_ast. syntax( ) . clone( ) . into( ) ,
@@ -150,31 +148,34 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
150
148
151
149
// Link the trait name & trait ref names together as a placeholder snippet group
152
150
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) ;
157
154
}
155
+
156
+ builder. add_file_edits ( ctx. vfs_file_id ( ) , editor) ;
158
157
} ,
159
158
) ;
160
159
161
160
Some ( ( ) )
162
161
}
163
162
164
163
/// `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 ) {
166
165
if let Some ( has_vis) = ast:: AnyHasVisibility :: cast ( item. syntax ( ) . clone ( ) ) {
167
166
if let Some ( vis) = has_vis. visibility ( )
168
167
&& let Some ( token) = vis. syntax ( ) . next_sibling_or_token ( )
169
168
&& token. kind ( ) == SyntaxKind :: WHITESPACE
170
169
{
171
- ted:: remove ( token) ;
170
+ editor. delete ( token) ;
171
+ }
172
+ if let Some ( vis) = has_vis. visibility ( ) {
173
+ editor. delete ( vis. syntax ( ) ) ;
172
174
}
173
- has_vis. set_visibility ( None ) ;
174
175
}
175
176
}
176
177
177
- fn strip_body ( item : & ast:: AssocItem ) {
178
+ fn strip_body ( editor : & mut SyntaxEditor , item : & ast:: AssocItem ) {
178
179
if let ast:: AssocItem :: Fn ( f) = item
179
180
&& let Some ( body) = f. body ( )
180
181
{
@@ -183,10 +184,10 @@ fn strip_body(item: &ast::AssocItem) {
183
184
if let Some ( prev) = body. syntax ( ) . prev_sibling_or_token ( )
184
185
&& prev. kind ( ) == SyntaxKind :: WHITESPACE
185
186
{
186
- ted :: remove ( prev) ;
187
+ editor . delete ( prev) ;
187
188
}
188
189
189
- ted :: replace ( body. syntax ( ) , make:: tokens:: semicolon ( ) ) ;
190
+ editor . replace ( body. syntax ( ) , make:: tokens:: semicolon ( ) ) ;
190
191
} ;
191
192
}
192
193
0 commit comments