@@ -3,8 +3,10 @@ use crate::{
3
3
AssistId ,
4
4
} ;
5
5
use ide_db:: helpers:: FamousDefs ;
6
+ use itertools:: Itertools ;
7
+ use stdx:: format_to;
6
8
use syntax:: {
7
- ast:: { self , Impl , NameOwner } ,
9
+ ast:: { self , GenericParamsOwner , Impl , NameOwner , TypeBoundsOwner } ,
8
10
AstNode ,
9
11
} ;
10
12
@@ -65,23 +67,56 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext)
65
67
"Generate a Default impl from a new fn" ,
66
68
insert_location,
67
69
move |builder| {
68
- let code = default_fn_node_for_new ( impl_) ;
70
+ let default_code = " fn default() -> Self {
71
+ Self::new()
72
+ }" ;
73
+ let code = generate_trait_impl_text_from_impl ( & impl_, "Default" , default_code) ;
69
74
builder. insert ( insert_location. end ( ) , code) ;
70
75
} ,
71
76
)
72
77
}
73
78
74
- fn default_fn_node_for_new ( impl_ : Impl ) -> String {
75
- format ! (
76
- "
79
+ fn generate_trait_impl_text_from_impl ( impl_ : & ast:: Impl , trait_text : & str , code : & str ) -> String {
80
+ let generic_params = impl_. generic_param_list ( ) ;
81
+ let mut buf = String :: with_capacity ( code. len ( ) ) ;
82
+ buf. push_str ( "\n \n " ) ;
83
+ buf. push_str ( "impl" ) ;
84
+
85
+ if let Some ( generic_params) = & generic_params {
86
+ let lifetimes = generic_params. lifetime_params ( ) . map ( |lt| format ! ( "{}" , lt. syntax( ) ) ) ;
87
+ let type_params = generic_params. type_params ( ) . map ( |type_param| {
88
+ let mut buf = String :: new ( ) ;
89
+ if let Some ( it) = type_param. name ( ) {
90
+ format_to ! ( buf, "{}" , it. syntax( ) ) ;
91
+ }
92
+ if let Some ( it) = type_param. colon_token ( ) {
93
+ format_to ! ( buf, "{} " , it) ;
94
+ }
95
+ if let Some ( it) = type_param. type_bound_list ( ) {
96
+ format_to ! ( buf, "{}" , it. syntax( ) ) ;
97
+ }
98
+ buf
99
+ } ) ;
100
+ let const_params = generic_params. const_params ( ) . map ( |t| t. syntax ( ) . to_string ( ) ) ;
101
+ let generics = lifetimes. chain ( type_params) . chain ( const_params) . format ( ", " ) ;
102
+ format_to ! ( buf, "<{}>" , generics) ;
103
+ }
104
+
105
+ buf. push ( ' ' ) ;
106
+ buf. push_str ( trait_text) ;
107
+ buf. push_str ( " for " ) ;
108
+ buf. push_str ( & impl_. self_ty ( ) . unwrap ( ) . syntax ( ) . text ( ) . to_string ( ) ) ;
109
+
110
+ match impl_. where_clause ( ) {
111
+ Some ( where_clause) => {
112
+ format_to ! ( buf, "\n {}\n {{\n {}\n }}" , where_clause, code) ;
113
+ }
114
+ None => {
115
+ format_to ! ( buf, " {{\n {}\n }}" , code) ;
116
+ }
117
+ }
77
118
78
- impl Default for {} {{
79
- fn default() -> Self {{
80
- Self::new()
81
- }}
82
- }}" ,
83
- impl_. self_ty( ) . unwrap( ) . syntax( ) . text( )
84
- )
119
+ buf
85
120
}
86
121
87
122
fn is_default_implemented ( ctx : & AssistContext , impl_ : & Impl ) -> bool {
@@ -175,6 +210,234 @@ impl Default for Test {
175
210
) ;
176
211
}
177
212
213
+ #[ test]
214
+ fn new_function_with_generic ( ) {
215
+ check_pass (
216
+ r#"
217
+ pub struct Foo<T> {
218
+ _bar: *mut T,
219
+ }
220
+
221
+ impl<T> Foo<T> {
222
+ pub fn ne$0w() -> Self {
223
+ unimplemented!()
224
+ }
225
+ }
226
+ "# ,
227
+ r#"
228
+ pub struct Foo<T> {
229
+ _bar: *mut T,
230
+ }
231
+
232
+ impl<T> Foo<T> {
233
+ pub fn new() -> Self {
234
+ unimplemented!()
235
+ }
236
+ }
237
+
238
+ impl<T> Default for Foo<T> {
239
+ fn default() -> Self {
240
+ Self::new()
241
+ }
242
+ }
243
+ "# ,
244
+ ) ;
245
+ }
246
+
247
+ #[ test]
248
+ fn new_function_with_generics ( ) {
249
+ check_pass (
250
+ r#"
251
+ pub struct Foo<T, B> {
252
+ _tars: *mut T,
253
+ _bar: *mut B,
254
+ }
255
+
256
+ impl<T, B> Foo<T, B> {
257
+ pub fn ne$0w() -> Self {
258
+ unimplemented!()
259
+ }
260
+ }
261
+ "# ,
262
+ r#"
263
+ pub struct Foo<T, B> {
264
+ _tars: *mut T,
265
+ _bar: *mut B,
266
+ }
267
+
268
+ impl<T, B> Foo<T, B> {
269
+ pub fn new() -> Self {
270
+ unimplemented!()
271
+ }
272
+ }
273
+
274
+ impl<T, B> Default for Foo<T, B> {
275
+ fn default() -> Self {
276
+ Self::new()
277
+ }
278
+ }
279
+ "# ,
280
+ ) ;
281
+ }
282
+
283
+ #[ test]
284
+ fn new_function_with_generic_and_bound ( ) {
285
+ check_pass (
286
+ r#"
287
+ pub struct Foo<T> {
288
+ t: T,
289
+ }
290
+
291
+ impl<T: From<i32>> Foo<T> {
292
+ pub fn ne$0w() -> Self {
293
+ Foo { t: 0.into() }
294
+ }
295
+ }
296
+ "# ,
297
+ r#"
298
+ pub struct Foo<T> {
299
+ t: T,
300
+ }
301
+
302
+ impl<T: From<i32>> Foo<T> {
303
+ pub fn new() -> Self {
304
+ Foo { t: 0.into() }
305
+ }
306
+ }
307
+
308
+ impl<T: From<i32>> Default for Foo<T> {
309
+ fn default() -> Self {
310
+ Self::new()
311
+ }
312
+ }
313
+ "# ,
314
+ ) ;
315
+ }
316
+
317
+ #[ test]
318
+ fn new_function_with_generics_and_bounds ( ) {
319
+ check_pass (
320
+ r#"
321
+ pub struct Foo<T, B> {
322
+ _tars: T,
323
+ _bar: B,
324
+ }
325
+
326
+ impl<T: From<i32>, B: From<i64>> Foo<T, B> {
327
+ pub fn ne$0w() -> Self {
328
+ unimplemented!()
329
+ }
330
+ }
331
+ "# ,
332
+ r#"
333
+ pub struct Foo<T, B> {
334
+ _tars: T,
335
+ _bar: B,
336
+ }
337
+
338
+ impl<T: From<i32>, B: From<i64>> Foo<T, B> {
339
+ pub fn new() -> Self {
340
+ unimplemented!()
341
+ }
342
+ }
343
+
344
+ impl<T: From<i32>, B: From<i64>> Default for Foo<T, B> {
345
+ fn default() -> Self {
346
+ Self::new()
347
+ }
348
+ }
349
+ "# ,
350
+ ) ;
351
+ }
352
+
353
+ #[ test]
354
+ fn new_function_with_generic_and_where ( ) {
355
+ check_pass (
356
+ r#"
357
+ pub struct Foo<T> {
358
+ t: T,
359
+ }
360
+
361
+ impl<T: From<i32>> Foo<T>
362
+ where
363
+ Option<T>: Debug
364
+ {
365
+ pub fn ne$0w() -> Self {
366
+ Foo { t: 0.into() }
367
+ }
368
+ }
369
+ "# ,
370
+ r#"
371
+ pub struct Foo<T> {
372
+ t: T,
373
+ }
374
+
375
+ impl<T: From<i32>> Foo<T>
376
+ where
377
+ Option<T>: Debug
378
+ {
379
+ pub fn new() -> Self {
380
+ Foo { t: 0.into() }
381
+ }
382
+ }
383
+
384
+ impl<T: From<i32>> Default for Foo<T>
385
+ where
386
+ Option<T>: Debug
387
+ {
388
+ fn default() -> Self {
389
+ Self::new()
390
+ }
391
+ }
392
+ "# ,
393
+ ) ;
394
+ }
395
+
396
+ #[ test]
397
+ fn new_function_with_generics_and_wheres ( ) {
398
+ check_pass (
399
+ r#"
400
+ pub struct Foo<T, B> {
401
+ _tars: T,
402
+ _bar: B,
403
+ }
404
+
405
+ impl<T: From<i32>, B: From<i64>> Foo<T, B>
406
+ where
407
+ Option<T>: Debug, Option<B>: Debug,
408
+ {
409
+ pub fn ne$0w() -> Self {
410
+ unimplemented!()
411
+ }
412
+ }
413
+ "# ,
414
+ r#"
415
+ pub struct Foo<T, B> {
416
+ _tars: T,
417
+ _bar: B,
418
+ }
419
+
420
+ impl<T: From<i32>, B: From<i64>> Foo<T, B>
421
+ where
422
+ Option<T>: Debug, Option<B>: Debug,
423
+ {
424
+ pub fn new() -> Self {
425
+ unimplemented!()
426
+ }
427
+ }
428
+
429
+ impl<T: From<i32>, B: From<i64>> Default for Foo<T, B>
430
+ where
431
+ Option<T>: Debug, Option<B>: Debug,
432
+ {
433
+ fn default() -> Self {
434
+ Self::new()
435
+ }
436
+ }
437
+ "# ,
438
+ ) ;
439
+ }
440
+
178
441
#[ test]
179
442
fn new_function_with_parameters ( ) {
180
443
cov_mark:: check!( new_function_with_parameters) ;
0 commit comments