@@ -4,12 +4,12 @@ use ide_db::{
4
4
} ;
5
5
use syntax:: {
6
6
ast:: { self , AstNode , HasName , HasVisibility , StructKind , edit_in_place:: Indent , make} ,
7
- ted ,
7
+ syntax_editor :: Position ,
8
8
} ;
9
9
10
10
use crate :: {
11
11
AssistContext , AssistId , Assists ,
12
- utils:: { find_struct_impl, generate_impl } ,
12
+ utils:: { find_struct_impl, generate_impl_with_item } ,
13
13
} ;
14
14
15
15
// Assist: generate_new
@@ -149,7 +149,53 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
149
149
. clone_for_update ( ) ;
150
150
fn_. indent ( 1 . into ( ) ) ;
151
151
152
- if let Some ( cap) = ctx. config . snippet_cap {
152
+ let mut editor = builder. make_editor ( strukt. syntax ( ) ) ;
153
+
154
+ // Get the node for set annotation
155
+ let contain_fn = if let Some ( impl_def) = impl_def {
156
+ fn_. indent ( impl_def. indent_level ( ) ) ;
157
+
158
+ if let Some ( l_curly) = impl_def. assoc_item_list ( ) . and_then ( |list| list. l_curly_token ( ) )
159
+ {
160
+ editor. insert_all (
161
+ Position :: after ( l_curly) ,
162
+ vec ! [
163
+ make:: tokens:: whitespace( & format!( "\n {}" , impl_def. indent_level( ) + 1 ) )
164
+ . into( ) ,
165
+ fn_. syntax( ) . clone( ) . into( ) ,
166
+ make:: tokens:: whitespace( "\n " ) . into( ) ,
167
+ ] ,
168
+ ) ;
169
+ fn_. syntax ( ) . clone ( )
170
+ } else {
171
+ let items = vec ! [ either:: Either :: Right ( ast:: AssocItem :: Fn ( fn_) ) ] ;
172
+ let list = make:: assoc_item_list ( Some ( items) ) ;
173
+ editor. insert ( Position :: after ( impl_def. syntax ( ) ) , list. syntax ( ) ) ;
174
+ list. syntax ( ) . clone ( )
175
+ }
176
+ } else {
177
+ // Generate a new impl to add the method to
178
+ let indent_level = strukt. indent_level ( ) ;
179
+ let body = vec ! [ either:: Either :: Right ( ast:: AssocItem :: Fn ( fn_) ) ] ;
180
+ let list = make:: assoc_item_list ( Some ( body) ) ;
181
+ let impl_def = generate_impl_with_item ( & ast:: Adt :: Struct ( strukt. clone ( ) ) , Some ( list) ) ;
182
+
183
+ impl_def. indent ( strukt. indent_level ( ) ) ;
184
+
185
+ // Insert it after the adt
186
+ editor. insert_all (
187
+ Position :: after ( strukt. syntax ( ) ) ,
188
+ vec ! [
189
+ make:: tokens:: whitespace( & format!( "\n \n {indent_level}" ) ) . into( ) ,
190
+ impl_def. syntax( ) . clone( ) . into( ) ,
191
+ ] ,
192
+ ) ;
193
+ impl_def. syntax ( ) . clone ( )
194
+ } ;
195
+
196
+ if let Some ( fn_) = contain_fn. descendants ( ) . find_map ( ast:: Fn :: cast)
197
+ && let Some ( cap) = ctx. config . snippet_cap
198
+ {
153
199
match strukt. kind ( ) {
154
200
StructKind :: Tuple ( _) => {
155
201
let struct_args = fn_
@@ -168,8 +214,8 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
168
214
for ( struct_arg, fn_param) in struct_args. zip ( fn_params. params ( ) ) {
169
215
if let Some ( fn_pat) = fn_param. pat ( ) {
170
216
let fn_pat = fn_pat. syntax ( ) . clone ( ) ;
171
- builder
172
- . add_placeholder_snippet_group ( cap , vec ! [ struct_arg, fn_pat] ) ;
217
+ let placeholder = builder. make_placeholder_snippet ( cap ) ;
218
+ editor . add_annotation_all ( vec ! [ struct_arg, fn_pat] , placeholder )
173
219
}
174
220
}
175
221
}
@@ -179,36 +225,12 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
179
225
180
226
// Add a tabstop before the name
181
227
if let Some ( name) = fn_. name ( ) {
182
- builder. add_tabstop_before ( cap, name) ;
228
+ let tabstop_before = builder. make_tabstop_before ( cap) ;
229
+ editor. add_annotation ( name. syntax ( ) , tabstop_before) ;
183
230
}
184
231
}
185
232
186
- // Get the mutable version of the impl to modify
187
- let impl_def = if let Some ( impl_def) = impl_def {
188
- fn_. indent ( impl_def. indent_level ( ) ) ;
189
- builder. make_mut ( impl_def)
190
- } else {
191
- // Generate a new impl to add the method to
192
- let impl_def = generate_impl ( & ast:: Adt :: Struct ( strukt. clone ( ) ) ) ;
193
- let indent_level = strukt. indent_level ( ) ;
194
- fn_. indent ( indent_level) ;
195
-
196
- // Insert it after the adt
197
- let strukt = builder. make_mut ( strukt. clone ( ) ) ;
198
-
199
- ted:: insert_all_raw (
200
- ted:: Position :: after ( strukt. syntax ( ) ) ,
201
- vec ! [
202
- make:: tokens:: whitespace( & format!( "\n \n {indent_level}" ) ) . into( ) ,
203
- impl_def. syntax( ) . clone( ) . into( ) ,
204
- ] ,
205
- ) ;
206
-
207
- impl_def
208
- } ;
209
-
210
- // Add the `new` method at the start of the impl
211
- impl_def. get_or_create_assoc_item_list ( ) . add_item_at_start ( fn_. into ( ) ) ;
233
+ builder. add_file_edits ( ctx. vfs_file_id ( ) , editor) ;
212
234
} )
213
235
}
214
236
0 commit comments