@@ -109,8 +109,6 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
109
109
let params =
110
110
body. extracted_function_params ( ctx, & container_info, locals_used. iter ( ) . copied ( ) ) ;
111
111
112
- let extracted_from_trait_impl = body. extracted_from_trait_impl ( ) ;
113
-
114
112
let name = make_function_name ( & semantics_scope) ;
115
113
116
114
let fun = Function {
@@ -129,8 +127,13 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
129
127
130
128
builder. replace ( target_range, make_call ( ctx, & fun, old_indent) ) ;
131
129
130
+ let has_impl_wrapper = insert_after
131
+ . ancestors ( )
132
+ . find ( |a| a. kind ( ) == SyntaxKind :: IMPL && a != & insert_after)
133
+ . is_some ( ) ;
134
+
132
135
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 => {
134
137
let fn_def = format_function ( ctx, module, & fun, old_indent, new_indent + 1 ) ;
135
138
generate_impl_text ( & adt, & fn_def) . replace ( "{\n \n " , "{" )
136
139
}
@@ -271,7 +274,7 @@ enum FunType {
271
274
}
272
275
273
276
/// Where to put extracted function definition
274
- #[ derive( Debug ) ]
277
+ #[ derive( Debug , Eq , PartialEq , Clone , Copy ) ]
275
278
enum Anchor {
276
279
/// Extract free function and put right after current top-level function
277
280
Freestanding ,
@@ -1244,6 +1247,15 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
1244
1247
while let Some ( next_ancestor) = ancestors. next ( ) {
1245
1248
match next_ancestor. kind ( ) {
1246
1249
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
+ }
1247
1259
SyntaxKind :: ITEM_LIST if !matches ! ( anchor, Anchor :: Freestanding ) => continue ,
1248
1260
SyntaxKind :: ITEM_LIST => {
1249
1261
if ancestors. peek ( ) . map ( SyntaxNode :: kind) == Some ( SyntaxKind :: MODULE ) {
@@ -1264,6 +1276,28 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
1264
1276
last_ancestor
1265
1277
}
1266
1278
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
+
1267
1301
fn make_call ( ctx : & AssistContext < ' _ > , fun : & Function , indent : IndentLevel ) -> String {
1268
1302
let ret_ty = fun. return_type ( ctx) ;
1269
1303
@@ -5058,6 +5092,236 @@ impl Struct {
5058
5092
) ;
5059
5093
}
5060
5094
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
+
5061
5325
#[ test]
5062
5326
fn closure_arguments ( ) {
5063
5327
check_assist (
0 commit comments