@@ -109,8 +109,6 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
109109 let params =
110110 body. extracted_function_params ( ctx, & container_info, locals_used. iter ( ) . copied ( ) ) ;
111111
112- let extracted_from_trait_impl = body. extracted_from_trait_impl ( ) ;
113-
114112 let name = make_function_name ( & semantics_scope) ;
115113
116114 let fun = Function {
@@ -129,8 +127,11 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
129127
130128 builder. replace ( target_range, make_call ( ctx, & fun, old_indent) ) ;
131129
130+ let has_impl_wrapper =
131+ insert_after. ancestors ( ) . any ( |a| a. kind ( ) == SyntaxKind :: IMPL && a != insert_after) ;
132+
132133 let fn_def = match fun. self_param_adt ( ctx) {
133- Some ( adt) if extracted_from_trait_impl => {
134+ Some ( adt) if anchor == Anchor :: Method && !has_impl_wrapper => {
134135 let fn_def = format_function ( ctx, module, & fun, old_indent, new_indent + 1 ) ;
135136 generate_impl_text ( & adt, & fn_def) . replace ( "{\n \n " , "{" )
136137 }
@@ -272,7 +273,7 @@ enum FunType {
272273}
273274
274275/// Where to put extracted function definition
275- #[ derive( Debug ) ]
276+ #[ derive( Debug , Eq , PartialEq , Clone , Copy ) ]
276277enum Anchor {
277278 /// Extract free function and put right after current top-level function
278279 Freestanding ,
@@ -1245,6 +1246,14 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
12451246 while let Some ( next_ancestor) = ancestors. next ( ) {
12461247 match next_ancestor. kind ( ) {
12471248 SyntaxKind :: SOURCE_FILE => break ,
1249+ SyntaxKind :: IMPL => {
1250+ if body. extracted_from_trait_impl ( ) && matches ! ( anchor, Anchor :: Method ) {
1251+ let impl_node = find_non_trait_impl ( & next_ancestor) ;
1252+ if let target_node @ Some ( _) = impl_node. as_ref ( ) . and_then ( last_impl_member) {
1253+ return target_node;
1254+ }
1255+ }
1256+ }
12481257 SyntaxKind :: ITEM_LIST if !matches ! ( anchor, Anchor :: Freestanding ) => continue ,
12491258 SyntaxKind :: ITEM_LIST => {
12501259 if ancestors. peek ( ) . map ( SyntaxNode :: kind) == Some ( SyntaxKind :: MODULE ) {
@@ -1265,6 +1274,29 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
12651274 last_ancestor
12661275}
12671276
1277+ fn find_non_trait_impl ( trait_impl : & SyntaxNode ) -> Option < ast:: Impl > {
1278+ let as_impl = ast:: Impl :: cast ( trait_impl. clone ( ) ) ?;
1279+ let impl_type = Some ( impl_type_name ( & as_impl) ?) ;
1280+
1281+ let sibblings = trait_impl. parent ( ) ?. children ( ) ;
1282+ sibblings
1283+ . filter_map ( ast:: Impl :: cast)
1284+ . find ( |s| impl_type_name ( s) == impl_type && !is_trait_impl ( s) )
1285+ }
1286+
1287+ fn last_impl_member ( impl_node : & ast:: Impl ) -> Option < SyntaxNode > {
1288+ let last_child = impl_node. assoc_item_list ( ) ?. assoc_items ( ) . last ( ) ?;
1289+ Some ( last_child. syntax ( ) . clone ( ) )
1290+ }
1291+
1292+ fn is_trait_impl ( node : & ast:: Impl ) -> bool {
1293+ node. trait_ ( ) . is_some ( )
1294+ }
1295+
1296+ fn impl_type_name ( impl_node : & ast:: Impl ) -> Option < String > {
1297+ Some ( impl_node. self_ty ( ) ?. to_string ( ) )
1298+ }
1299+
12681300fn make_call ( ctx : & AssistContext < ' _ > , fun : & Function , indent : IndentLevel ) -> String {
12691301 let ret_ty = fun. return_type ( ctx) ;
12701302
@@ -5051,6 +5083,236 @@ impl Struct {
50515083 ) ;
50525084 }
50535085
5086+ #[ test]
5087+ fn extract_method_from_trait_with_existing_non_empty_impl_block ( ) {
5088+ check_assist (
5089+ extract_function,
5090+ r#"
5091+ struct Struct(i32);
5092+ trait Trait {
5093+ fn bar(&self) -> i32;
5094+ }
5095+
5096+ impl Struct {
5097+ fn foo() {}
5098+ }
5099+
5100+ impl Trait for Struct {
5101+ fn bar(&self) -> i32 {
5102+ $0self.0 + 2$0
5103+ }
5104+ }
5105+ "# ,
5106+ r#"
5107+ struct Struct(i32);
5108+ trait Trait {
5109+ fn bar(&self) -> i32;
5110+ }
5111+
5112+ impl Struct {
5113+ fn foo() {}
5114+
5115+ fn $0fun_name(&self) -> i32 {
5116+ self.0 + 2
5117+ }
5118+ }
5119+
5120+ impl Trait for Struct {
5121+ fn bar(&self) -> i32 {
5122+ self.fun_name()
5123+ }
5124+ }
5125+ "# ,
5126+ )
5127+ }
5128+
5129+ #[ test]
5130+ fn extract_function_from_trait_with_existing_non_empty_impl_block ( ) {
5131+ check_assist (
5132+ extract_function,
5133+ r#"
5134+ struct Struct(i32);
5135+ trait Trait {
5136+ fn bar(&self) -> i32;
5137+ }
5138+
5139+ impl Struct {
5140+ fn foo() {}
5141+ }
5142+
5143+ impl Trait for Struct {
5144+ fn bar(&self) -> i32 {
5145+ let three_squared = $03 * 3$0;
5146+ self.0 + three_squared
5147+ }
5148+ }
5149+ "# ,
5150+ r#"
5151+ struct Struct(i32);
5152+ trait Trait {
5153+ fn bar(&self) -> i32;
5154+ }
5155+
5156+ impl Struct {
5157+ fn foo() {}
5158+ }
5159+
5160+ impl Trait for Struct {
5161+ fn bar(&self) -> i32 {
5162+ let three_squared = fun_name();
5163+ self.0 + three_squared
5164+ }
5165+ }
5166+
5167+ fn $0fun_name() -> i32 {
5168+ 3 * 3
5169+ }
5170+ "# ,
5171+ )
5172+ }
5173+
5174+ #[ test]
5175+ fn extract_method_from_trait_with_multiple_existing_impl_blocks ( ) {
5176+ check_assist (
5177+ extract_function,
5178+ r#"
5179+ struct Struct(i32);
5180+ struct StructBefore(i32);
5181+ struct StructAfter(i32);
5182+ trait Trait {
5183+ fn bar(&self) -> i32;
5184+ }
5185+
5186+ impl StructBefore {
5187+ fn foo(){}
5188+ }
5189+
5190+ impl Struct {
5191+ fn foo(){}
5192+ }
5193+
5194+ impl StructAfter {
5195+ fn foo(){}
5196+ }
5197+
5198+ impl Trait for Struct {
5199+ fn bar(&self) -> i32 {
5200+ $0self.0 + 2$0
5201+ }
5202+ }
5203+ "# ,
5204+ r#"
5205+ struct Struct(i32);
5206+ struct StructBefore(i32);
5207+ struct StructAfter(i32);
5208+ trait Trait {
5209+ fn bar(&self) -> i32;
5210+ }
5211+
5212+ impl StructBefore {
5213+ fn foo(){}
5214+ }
5215+
5216+ impl Struct {
5217+ fn foo(){}
5218+
5219+ fn $0fun_name(&self) -> i32 {
5220+ self.0 + 2
5221+ }
5222+ }
5223+
5224+ impl StructAfter {
5225+ fn foo(){}
5226+ }
5227+
5228+ impl Trait for Struct {
5229+ fn bar(&self) -> i32 {
5230+ self.fun_name()
5231+ }
5232+ }
5233+ "# ,
5234+ )
5235+ }
5236+
5237+ #[ test]
5238+ fn extract_method_from_trait_with_multiple_existing_trait_impl_blocks ( ) {
5239+ check_assist (
5240+ extract_function,
5241+ r#"
5242+ struct Struct(i32);
5243+ trait Trait {
5244+ fn bar(&self) -> i32;
5245+ }
5246+ trait TraitBefore {
5247+ fn before(&self) -> i32;
5248+ }
5249+ trait TraitAfter {
5250+ fn after(&self) -> i32;
5251+ }
5252+
5253+ impl TraitBefore for Struct {
5254+ fn before(&self) -> i32 {
5255+ 42
5256+ }
5257+ }
5258+
5259+ impl Struct {
5260+ fn foo(){}
5261+ }
5262+
5263+ impl TraitAfter for Struct {
5264+ fn after(&self) -> i32 {
5265+ 42
5266+ }
5267+ }
5268+
5269+ impl Trait for Struct {
5270+ fn bar(&self) -> i32 {
5271+ $0self.0 + 2$0
5272+ }
5273+ }
5274+ "# ,
5275+ r#"
5276+ struct Struct(i32);
5277+ trait Trait {
5278+ fn bar(&self) -> i32;
5279+ }
5280+ trait TraitBefore {
5281+ fn before(&self) -> i32;
5282+ }
5283+ trait TraitAfter {
5284+ fn after(&self) -> i32;
5285+ }
5286+
5287+ impl TraitBefore for Struct {
5288+ fn before(&self) -> i32 {
5289+ 42
5290+ }
5291+ }
5292+
5293+ impl Struct {
5294+ fn foo(){}
5295+
5296+ fn $0fun_name(&self) -> i32 {
5297+ self.0 + 2
5298+ }
5299+ }
5300+
5301+ impl TraitAfter for Struct {
5302+ fn after(&self) -> i32 {
5303+ 42
5304+ }
5305+ }
5306+
5307+ impl Trait for Struct {
5308+ fn bar(&self) -> i32 {
5309+ self.fun_name()
5310+ }
5311+ }
5312+ "# ,
5313+ )
5314+ }
5315+
50545316 #[ test]
50555317 fn closure_arguments ( ) {
50565318 check_assist (
0 commit comments