@@ -2,6 +2,7 @@ use hir::HasSource;
2
2
use syntax:: {
3
3
Edition ,
4
4
ast:: { self , AstNode , make} ,
5
+ syntax_editor:: { Position , SyntaxEditor } ,
5
6
} ;
6
7
7
8
use crate :: {
@@ -147,45 +148,78 @@ fn add_missing_impl_members_inner(
147
148
148
149
let target = impl_def. syntax ( ) . text_range ( ) ;
149
150
acc. add ( AssistId :: quick_fix ( assist_id) , label, target, |edit| {
150
- let new_impl_def = edit. make_mut ( impl_def. clone ( ) ) ;
151
- let first_new_item = add_trait_assoc_items_to_impl (
151
+ let new_item = add_trait_assoc_items_to_impl (
152
152
& ctx. sema ,
153
153
ctx. config ,
154
154
& missing_items,
155
155
trait_,
156
- & new_impl_def ,
156
+ & impl_def ,
157
157
& target_scope,
158
158
) ;
159
159
160
+ let Some ( ( first_new_item, other_items) ) = new_item. split_first ( ) else {
161
+ return ;
162
+ } ;
163
+
164
+ let mut first_new_item = if let DefaultMethods :: No = mode
165
+ && let ast:: AssocItem :: Fn ( func) = & first_new_item
166
+ && let Some ( body) = try_gen_trait_body (
167
+ ctx,
168
+ func,
169
+ trait_ref,
170
+ & impl_def,
171
+ target_scope. krate ( ) . edition ( ctx. sema . db ) ,
172
+ )
173
+ && let Some ( func_body) = func. body ( )
174
+ {
175
+ let mut func_editor = SyntaxEditor :: new ( first_new_item. syntax ( ) . clone_subtree ( ) ) ;
176
+ func_editor. replace ( func_body. syntax ( ) , body. syntax ( ) ) ;
177
+ ast:: AssocItem :: cast ( func_editor. finish ( ) . new_root ( ) . clone ( ) )
178
+ } else {
179
+ Some ( first_new_item. clone ( ) )
180
+ } ;
181
+
182
+ let new_assoc_items = first_new_item
183
+ . clone ( )
184
+ . into_iter ( )
185
+ . chain ( other_items. iter ( ) . cloned ( ) )
186
+ . map ( either:: Either :: Right )
187
+ . collect :: < Vec < _ > > ( ) ;
188
+
189
+ let mut editor = edit. make_editor ( impl_def. syntax ( ) ) ;
190
+ if let Some ( assoc_item_list) = impl_def. assoc_item_list ( ) {
191
+ let items = new_assoc_items. into_iter ( ) . filter_map ( either:: Either :: right) . collect ( ) ;
192
+ assoc_item_list. add_items ( & mut editor, items) ;
193
+ } else {
194
+ let assoc_item_list = make:: assoc_item_list ( Some ( new_assoc_items) ) . clone_for_update ( ) ;
195
+ editor. insert_all (
196
+ Position :: after ( impl_def. syntax ( ) ) ,
197
+ vec ! [ make:: tokens:: whitespace( " " ) . into( ) , assoc_item_list. syntax( ) . clone( ) . into( ) ] ,
198
+ ) ;
199
+ first_new_item = assoc_item_list. assoc_items ( ) . next ( ) ;
200
+ }
201
+
160
202
if let Some ( cap) = ctx. config . snippet_cap {
161
203
let mut placeholder = None ;
162
204
if let DefaultMethods :: No = mode {
163
- if let ast:: AssocItem :: Fn ( func) = & first_new_item {
164
- if try_gen_trait_body (
165
- ctx,
166
- func,
167
- trait_ref,
168
- & impl_def,
169
- target_scope. krate ( ) . edition ( ctx. sema . db ) ,
170
- )
171
- . is_none ( )
205
+ if let Some ( ast:: AssocItem :: Fn ( func) ) = & first_new_item {
206
+ if let Some ( m) = func. syntax ( ) . descendants ( ) . find_map ( ast:: MacroCall :: cast)
207
+ && m. syntax ( ) . text ( ) == "todo!()"
172
208
{
173
- if let Some ( m) = func. syntax ( ) . descendants ( ) . find_map ( ast:: MacroCall :: cast)
174
- {
175
- if m. syntax ( ) . text ( ) == "todo!()" {
176
- placeholder = Some ( m) ;
177
- }
178
- }
209
+ placeholder = Some ( m) ;
179
210
}
180
211
}
181
212
}
182
213
183
214
if let Some ( macro_call) = placeholder {
184
- edit. add_placeholder_snippet ( cap, macro_call) ;
185
- } else {
186
- edit. add_tabstop_before ( cap, first_new_item) ;
215
+ let placeholder = edit. make_placeholder_snippet ( cap) ;
216
+ editor. add_annotation ( macro_call. syntax ( ) , placeholder) ;
217
+ } else if let Some ( first_new_item) = first_new_item {
218
+ let tabstop = edit. make_tabstop_before ( cap) ;
219
+ editor. add_annotation ( first_new_item. syntax ( ) , tabstop) ;
187
220
} ;
188
221
} ;
222
+ edit. add_file_edits ( ctx. vfs_file_id ( ) , editor) ;
189
223
} )
190
224
}
191
225
@@ -195,7 +229,7 @@ fn try_gen_trait_body(
195
229
trait_ref : hir:: TraitRef < ' _ > ,
196
230
impl_def : & ast:: Impl ,
197
231
edition : Edition ,
198
- ) -> Option < ( ) > {
232
+ ) -> Option < ast :: BlockExpr > {
199
233
let trait_path = make:: ext:: ident_path (
200
234
& trait_ref. trait_ ( ) . name ( ctx. db ( ) ) . display ( ctx. db ( ) , edition) . to_string ( ) ,
201
235
) ;
@@ -322,7 +356,7 @@ impl Foo for S {
322
356
}
323
357
324
358
#[ test]
325
- fn test_impl_def_without_braces ( ) {
359
+ fn test_impl_def_without_braces_macro ( ) {
326
360
check_assist (
327
361
add_missing_impl_members,
328
362
r#"
@@ -340,6 +374,33 @@ impl Foo for S {
340
374
) ;
341
375
}
342
376
377
+ #[ test]
378
+ fn test_impl_def_without_braces_tabstop_first_item ( ) {
379
+ check_assist (
380
+ add_missing_impl_members,
381
+ r#"
382
+ trait Foo {
383
+ type Output;
384
+ fn foo(&self);
385
+ }
386
+ struct S;
387
+ impl Foo for S { $0 }"# ,
388
+ r#"
389
+ trait Foo {
390
+ type Output;
391
+ fn foo(&self);
392
+ }
393
+ struct S;
394
+ impl Foo for S {
395
+ $0type Output;
396
+
397
+ fn foo(&self) {
398
+ todo!()
399
+ }
400
+ }"# ,
401
+ ) ;
402
+ }
403
+
343
404
#[ test]
344
405
fn fill_in_type_params_1 ( ) {
345
406
check_assist (
0 commit comments