@@ -2,6 +2,7 @@ use hir::HasSource;
22use syntax:: {
33 Edition ,
44 ast:: { self , AstNode , make} ,
5+ syntax_editor:: { Position , SyntaxEditor } ,
56} ;
67
78use crate :: {
@@ -147,45 +148,78 @@ fn add_missing_impl_members_inner(
147148
148149 let target = impl_def. syntax ( ) . text_range ( ) ;
149150 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 (
152152 & ctx. sema ,
153153 ctx. config ,
154154 & missing_items,
155155 trait_,
156- & new_impl_def ,
156+ & impl_def ,
157157 & target_scope,
158158 ) ;
159159
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+
160202 if let Some ( cap) = ctx. config . snippet_cap {
161203 let mut placeholder = None ;
162204 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!()"
172208 {
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) ;
179210 }
180211 }
181212 }
182213
183214 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) ;
187220 } ;
188221 } ;
222+ edit. add_file_edits ( ctx. vfs_file_id ( ) , editor) ;
189223 } )
190224}
191225
@@ -195,7 +229,7 @@ fn try_gen_trait_body(
195229 trait_ref : hir:: TraitRef < ' _ > ,
196230 impl_def : & ast:: Impl ,
197231 edition : Edition ,
198- ) -> Option < ( ) > {
232+ ) -> Option < ast :: BlockExpr > {
199233 let trait_path = make:: ext:: ident_path (
200234 & trait_ref. trait_ ( ) . name ( ctx. db ( ) ) . display ( ctx. db ( ) , edition) . to_string ( ) ,
201235 ) ;
@@ -322,7 +356,7 @@ impl Foo for S {
322356 }
323357
324358 #[ test]
325- fn test_impl_def_without_braces ( ) {
359+ fn test_impl_def_without_braces_macro ( ) {
326360 check_assist (
327361 add_missing_impl_members,
328362 r#"
@@ -340,6 +374,33 @@ impl Foo for S {
340374 ) ;
341375 }
342376
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+
343404 #[ test]
344405 fn fill_in_type_params_1 ( ) {
345406 check_assist (
0 commit comments