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