@@ -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,11 @@ 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 =
131
+ insert_after. ancestors ( ) . any ( |a| a. kind ( ) == SyntaxKind :: IMPL && a != insert_after) ;
132
+
132
133
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 => {
134
135
let fn_def = format_function ( ctx, module, & fun, old_indent, new_indent + 1 ) ;
135
136
generate_impl_text ( & adt, & fn_def) . replace ( "{\n \n " , "{" )
136
137
}
@@ -272,7 +273,7 @@ enum FunType {
272
273
}
273
274
274
275
/// Where to put extracted function definition
275
- #[ derive( Debug ) ]
276
+ #[ derive( Debug , Eq , PartialEq , Clone , Copy ) ]
276
277
enum Anchor {
277
278
/// Extract free function and put right after current top-level function
278
279
Freestanding ,
@@ -1245,6 +1246,14 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
1245
1246
while let Some ( next_ancestor) = ancestors. next ( ) {
1246
1247
match next_ancestor. kind ( ) {
1247
1248
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
+ }
1248
1257
SyntaxKind :: ITEM_LIST if !matches ! ( anchor, Anchor :: Freestanding ) => continue ,
1249
1258
SyntaxKind :: ITEM_LIST => {
1250
1259
if ancestors. peek ( ) . map ( SyntaxNode :: kind) == Some ( SyntaxKind :: MODULE ) {
@@ -1265,6 +1274,29 @@ fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNod
1265
1274
last_ancestor
1266
1275
}
1267
1276
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
+
1268
1300
fn make_call ( ctx : & AssistContext < ' _ > , fun : & Function , indent : IndentLevel ) -> String {
1269
1301
let ret_ty = fun. return_type ( ctx) ;
1270
1302
@@ -5051,6 +5083,236 @@ impl Struct {
5051
5083
) ;
5052
5084
}
5053
5085
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
+
5054
5316
#[ test]
5055
5317
fn closure_arguments ( ) {
5056
5318
check_assist (
0 commit comments