@@ -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,13 @@ 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 = insert_after
131+ . ancestors ( )
132+ . find ( |a| a. kind ( ) == SyntaxKind :: IMPL && a != & insert_after)
133+ . is_some ( ) ;
134+
132135 let fn_def = match fun. self_param_adt ( ctx) {
133- Some ( adt) if extracted_from_trait_impl => {
136+ Some ( adt) if anchor == Anchor :: Method && !has_impl_wrapper => {
134137 let fn_def = format_function ( ctx, module, & fun, old_indent, new_indent + 1 ) ;
135138 generate_impl_text ( & adt, & fn_def) . replace ( "{\n \n " , "{" )
136139 }
@@ -271,7 +274,7 @@ enum FunType {
271274}
272275
273276/// Where to put extracted function definition
274- #[ derive( Debug ) ]
277+ #[ derive( Debug , Eq , PartialEq , Clone , Copy ) ]
275278enum Anchor {
276279 /// Extract free function and put right after current top-level function
277280 Freestanding ,
@@ -1244,6 +1247,15 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
12441247 while let Some ( next_ancestor) = ancestors. next ( ) {
12451248 match next_ancestor. kind ( ) {
12461249 SyntaxKind :: SOURCE_FILE => break ,
1250+ SyntaxKind :: IMPL => {
1251+ if body. extracted_from_trait_impl ( ) && matches ! ( anchor, Anchor :: Method ) {
1252+ let impl_node = find_non_trait_impl ( & next_ancestor) ;
1253+ let target_node = impl_node. as_ref ( ) . and_then ( last_impl_member) ;
1254+ if target_node. is_some ( ) {
1255+ return target_node;
1256+ }
1257+ }
1258+ }
12471259 SyntaxKind :: ITEM_LIST if !matches ! ( anchor, Anchor :: Freestanding ) => continue ,
12481260 SyntaxKind :: ITEM_LIST => {
12491261 if ancestors. peek ( ) . map ( SyntaxNode :: kind) == Some ( SyntaxKind :: MODULE ) {
@@ -1264,6 +1276,28 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
12641276 last_ancestor
12651277}
12661278
1279+ fn find_non_trait_impl ( trait_impl : & SyntaxNode ) -> Option < SyntaxNode > {
1280+ let impl_type = Some ( impl_type_name ( trait_impl) ?) ;
1281+
1282+ let mut sibblings = trait_impl. parent ( ) ?. children ( ) ;
1283+ sibblings. find ( |s| impl_type_name ( s) == impl_type && !is_trait_impl ( s) )
1284+ }
1285+
1286+ fn last_impl_member ( impl_node : & SyntaxNode ) -> Option < SyntaxNode > {
1287+ impl_node. children ( ) . find ( |c| c. kind ( ) == SyntaxKind :: ASSOC_ITEM_LIST ) ?. last_child ( )
1288+ }
1289+
1290+ fn is_trait_impl ( node : & SyntaxNode ) -> bool {
1291+ match ast:: Impl :: cast ( node. clone ( ) ) {
1292+ Some ( c) => c. trait_ ( ) . is_some ( ) ,
1293+ None => false ,
1294+ }
1295+ }
1296+
1297+ fn impl_type_name ( impl_node : & SyntaxNode ) -> Option < String > {
1298+ Some ( ast:: Impl :: cast ( impl_node. clone ( ) ) ?. self_ty ( ) ?. to_string ( ) )
1299+ }
1300+
12671301fn make_call ( ctx : & AssistContext < ' _ > , fun : & Function , indent : IndentLevel ) -> String {
12681302 let ret_ty = fun. return_type ( ctx) ;
12691303
@@ -5058,6 +5092,236 @@ impl Struct {
50585092 ) ;
50595093 }
50605094
5095+ #[ test]
5096+ fn extract_method_from_trait_with_existing_non_empty_impl_block ( ) {
5097+ check_assist (
5098+ extract_function,
5099+ r#"
5100+ struct Struct(i32);
5101+ trait Trait {
5102+ fn bar(&self) -> i32;
5103+ }
5104+
5105+ impl Struct {
5106+ fn foo() {}
5107+ }
5108+
5109+ impl Trait for Struct {
5110+ fn bar(&self) -> i32 {
5111+ $0self.0 + 2$0
5112+ }
5113+ }
5114+ "# ,
5115+ r#"
5116+ struct Struct(i32);
5117+ trait Trait {
5118+ fn bar(&self) -> i32;
5119+ }
5120+
5121+ impl Struct {
5122+ fn foo() {}
5123+
5124+ fn $0fun_name(&self) -> i32 {
5125+ self.0 + 2
5126+ }
5127+ }
5128+
5129+ impl Trait for Struct {
5130+ fn bar(&self) -> i32 {
5131+ self.fun_name()
5132+ }
5133+ }
5134+ "# ,
5135+ )
5136+ }
5137+
5138+ #[ test]
5139+ fn extract_function_from_trait_with_existing_non_empty_impl_block ( ) {
5140+ check_assist (
5141+ extract_function,
5142+ r#"
5143+ struct Struct(i32);
5144+ trait Trait {
5145+ fn bar(&self) -> i32;
5146+ }
5147+
5148+ impl Struct {
5149+ fn foo() {}
5150+ }
5151+
5152+ impl Trait for Struct {
5153+ fn bar(&self) -> i32 {
5154+ let three_squared = $03 * 3$0;
5155+ self.0 + three_squared
5156+ }
5157+ }
5158+ "# ,
5159+ r#"
5160+ struct Struct(i32);
5161+ trait Trait {
5162+ fn bar(&self) -> i32;
5163+ }
5164+
5165+ impl Struct {
5166+ fn foo() {}
5167+ }
5168+
5169+ impl Trait for Struct {
5170+ fn bar(&self) -> i32 {
5171+ let three_squared = fun_name();
5172+ self.0 + three_squared
5173+ }
5174+ }
5175+
5176+ fn $0fun_name() -> i32 {
5177+ 3 * 3
5178+ }
5179+ "# ,
5180+ )
5181+ }
5182+
5183+ #[ test]
5184+ fn extract_method_from_trait_with_multiple_existing_impl_blocks ( ) {
5185+ check_assist (
5186+ extract_function,
5187+ r#"
5188+ struct Struct(i32);
5189+ struct StructBefore(i32);
5190+ struct StructAfter(i32);
5191+ trait Trait {
5192+ fn bar(&self) -> i32;
5193+ }
5194+
5195+ impl StructBefore {
5196+ fn foo(){}
5197+ }
5198+
5199+ impl Struct {
5200+ fn foo(){}
5201+ }
5202+
5203+ impl StructAfter {
5204+ fn foo(){}
5205+ }
5206+
5207+ impl Trait for Struct {
5208+ fn bar(&self) -> i32 {
5209+ $0self.0 + 2$0
5210+ }
5211+ }
5212+ "# ,
5213+ r#"
5214+ struct Struct(i32);
5215+ struct StructBefore(i32);
5216+ struct StructAfter(i32);
5217+ trait Trait {
5218+ fn bar(&self) -> i32;
5219+ }
5220+
5221+ impl StructBefore {
5222+ fn foo(){}
5223+ }
5224+
5225+ impl Struct {
5226+ fn foo(){}
5227+
5228+ fn $0fun_name(&self) -> i32 {
5229+ self.0 + 2
5230+ }
5231+ }
5232+
5233+ impl StructAfter {
5234+ fn foo(){}
5235+ }
5236+
5237+ impl Trait for Struct {
5238+ fn bar(&self) -> i32 {
5239+ self.fun_name()
5240+ }
5241+ }
5242+ "# ,
5243+ )
5244+ }
5245+
5246+ #[ test]
5247+ fn extract_method_from_trait_with_multiple_existing_trait_impl_blocks ( ) {
5248+ check_assist (
5249+ extract_function,
5250+ r#"
5251+ struct Struct(i32);
5252+ trait Trait {
5253+ fn bar(&self) -> i32;
5254+ }
5255+ trait TraitBefore {
5256+ fn before(&self) -> i32;
5257+ }
5258+ trait TraitAfter {
5259+ fn after(&self) -> i32;
5260+ }
5261+
5262+ impl TraitBefore for Struct {
5263+ fn before(&self) -> i32 {
5264+ 42
5265+ }
5266+ }
5267+
5268+ impl Struct {
5269+ fn foo(){}
5270+ }
5271+
5272+ impl TraitAfter for Struct {
5273+ fn after(&self) -> i32 {
5274+ 42
5275+ }
5276+ }
5277+
5278+ impl Trait for Struct {
5279+ fn bar(&self) -> i32 {
5280+ $0self.0 + 2$0
5281+ }
5282+ }
5283+ "# ,
5284+ r#"
5285+ struct Struct(i32);
5286+ trait Trait {
5287+ fn bar(&self) -> i32;
5288+ }
5289+ trait TraitBefore {
5290+ fn before(&self) -> i32;
5291+ }
5292+ trait TraitAfter {
5293+ fn after(&self) -> i32;
5294+ }
5295+
5296+ impl TraitBefore for Struct {
5297+ fn before(&self) -> i32 {
5298+ 42
5299+ }
5300+ }
5301+
5302+ impl Struct {
5303+ fn foo(){}
5304+
5305+ fn $0fun_name(&self) -> i32 {
5306+ self.0 + 2
5307+ }
5308+ }
5309+
5310+ impl TraitAfter for Struct {
5311+ fn after(&self) -> i32 {
5312+ 42
5313+ }
5314+ }
5315+
5316+ impl Trait for Struct {
5317+ fn bar(&self) -> i32 {
5318+ self.fun_name()
5319+ }
5320+ }
5321+ "# ,
5322+ )
5323+ }
5324+
50615325 #[ test]
50625326 fn closure_arguments ( ) {
50635327 check_assist (
0 commit comments