1use ide_db::famous_defs::FamousDefs;
2use stdx::format_to;
3use syntax::{
4 AstNode,
5 ast::{self, HasGenericParams, HasName, HasTypeBounds, Impl, make},
6};
7
8use crate::{
9 AssistId,
10 assist_context::{AssistContext, Assists},
11};
12
13pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
44 let fn_node = ctx.find_node_at_offset::<ast::Fn>()?;
45 let fn_name = fn_node.name()?;
46
47 if fn_name.text() != "new" {
48 cov_mark::hit!(other_function_than_new);
49 return None;
50 }
51
52 if fn_node.param_list()?.params().next().is_some() {
53 cov_mark::hit!(new_function_with_parameters);
54 return None;
55 }
56
57 let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?;
58 let self_ty = impl_.self_ty()?;
59 if is_default_implemented(ctx, &impl_) {
60 cov_mark::hit!(default_block_is_already_present);
61 cov_mark::hit!(struct_in_module_with_default);
62 return None;
63 }
64
65 let insert_location = impl_.syntax().text_range();
66
67 acc.add(
68 AssistId::generate("generate_default_from_new"),
69 "Generate a Default impl from a new fn",
70 insert_location,
71 move |builder| {
72 let default_code = " fn default() -> Self {
73 Self::new()
74 }";
75 let code = generate_trait_impl_text_from_impl(&impl_, self_ty, "Default", default_code);
76 builder.insert(insert_location.end(), code);
77 },
78 )
79}
80
81fn generate_trait_impl_text_from_impl(
83 impl_: &ast::Impl,
84 self_ty: ast::Type,
85 trait_text: &str,
86 code: &str,
87) -> String {
88 let generic_params = impl_.generic_param_list().map(|generic_params| {
89 let lifetime_params =
90 generic_params.lifetime_params().map(ast::GenericParam::LifetimeParam);
91 let ty_or_const_params = generic_params.type_or_const_params().filter_map(|param| {
92 let param = match param {
94 ast::TypeOrConstParam::Type(param) => {
95 let param = make::type_param(param.name()?, param.type_bound_list());
96 ast::GenericParam::TypeParam(param)
97 }
98 ast::TypeOrConstParam::Const(param) => {
99 let param = make::const_param(param.name()?, param.ty()?);
100 ast::GenericParam::ConstParam(param)
101 }
102 };
103 Some(param)
104 });
105
106 make::generic_param_list(itertools::chain(lifetime_params, ty_or_const_params))
107 });
108
109 let mut buf = String::with_capacity(code.len());
110 buf.push_str("\n\n");
111
112 buf.push_str("impl");
114 if let Some(generic_params) = &generic_params {
115 format_to!(buf, "{generic_params}")
116 }
117 format_to!(buf, " {trait_text} for {self_ty}");
118
119 match impl_.where_clause() {
120 Some(where_clause) => {
121 format_to!(buf, "\n{where_clause}\n{{\n{code}\n}}");
122 }
123 None => {
124 format_to!(buf, " {{\n{code}\n}}");
125 }
126 }
127
128 buf
129}
130
131fn is_default_implemented(ctx: &AssistContext<'_>, impl_: &Impl) -> bool {
132 let db = ctx.sema.db;
133 let impl_ = ctx.sema.to_def(impl_);
134 let impl_def = match impl_ {
135 Some(value) => value,
136 None => return false,
137 };
138
139 let ty = impl_def.self_ty(db);
140 let krate = impl_def.module(db).krate(ctx.db());
141 let default = FamousDefs(&ctx.sema, krate).core_default_Default();
142 let default_trait = match default {
143 Some(value) => value,
144 None => return true,
147 };
148
149 ty.impls_trait(db, default_trait, &[])
150}
151
152#[cfg(test)]
153mod tests {
154 use crate::tests::{check_assist, check_assist_not_applicable};
155
156 use super::*;
157
158 #[test]
159 fn generate_default() {
160 check_assist(
161 generate_default_from_new,
162 r#"
163//- minicore: default
164struct Example { _inner: () }
165
166impl Example {
167 pub fn ne$0w() -> Self {
168 Self { _inner: () }
169 }
170}
171
172fn main() {}
173"#,
174 r#"
175struct Example { _inner: () }
176
177impl Example {
178 pub fn new() -> Self {
179 Self { _inner: () }
180 }
181}
182
183impl Default for Example {
184 fn default() -> Self {
185 Self::new()
186 }
187}
188
189fn main() {}
190"#,
191 );
192 }
193
194 #[test]
195 fn generate_default2() {
196 check_assist(
197 generate_default_from_new,
198 r#"
199//- minicore: default
200struct Test { value: u32 }
201
202impl Test {
203 pub fn ne$0w() -> Self {
204 Self { value: 0 }
205 }
206}
207"#,
208 r#"
209struct Test { value: u32 }
210
211impl Test {
212 pub fn new() -> Self {
213 Self { value: 0 }
214 }
215}
216
217impl Default for Test {
218 fn default() -> Self {
219 Self::new()
220 }
221}
222"#,
223 );
224 }
225
226 #[test]
227 fn new_function_with_generic() {
228 check_assist(
229 generate_default_from_new,
230 r#"
231//- minicore: default
232pub struct Foo<T> {
233 _bar: *mut T,
234}
235
236impl<T> Foo<T> {
237 pub fn ne$0w() -> Self {
238 unimplemented!()
239 }
240}
241"#,
242 r#"
243pub struct Foo<T> {
244 _bar: *mut T,
245}
246
247impl<T> Foo<T> {
248 pub fn new() -> Self {
249 unimplemented!()
250 }
251}
252
253impl<T> Default for Foo<T> {
254 fn default() -> Self {
255 Self::new()
256 }
257}
258"#,
259 );
260 }
261
262 #[test]
263 fn new_function_with_generics() {
264 check_assist(
265 generate_default_from_new,
266 r#"
267//- minicore: default
268pub struct Foo<T, B> {
269 _tars: *mut T,
270 _bar: *mut B,
271}
272
273impl<T, B> Foo<T, B> {
274 pub fn ne$0w() -> Self {
275 unimplemented!()
276 }
277}
278"#,
279 r#"
280pub struct Foo<T, B> {
281 _tars: *mut T,
282 _bar: *mut B,
283}
284
285impl<T, B> Foo<T, B> {
286 pub fn new() -> Self {
287 unimplemented!()
288 }
289}
290
291impl<T, B> Default for Foo<T, B> {
292 fn default() -> Self {
293 Self::new()
294 }
295}
296"#,
297 );
298 }
299
300 #[test]
301 fn new_function_with_generic_and_bound() {
302 check_assist(
303 generate_default_from_new,
304 r#"
305//- minicore: default
306pub struct Foo<T> {
307 t: T,
308}
309
310impl<T: From<i32>> Foo<T> {
311 pub fn ne$0w() -> Self {
312 Foo { t: 0.into() }
313 }
314}
315"#,
316 r#"
317pub struct Foo<T> {
318 t: T,
319}
320
321impl<T: From<i32>> Foo<T> {
322 pub fn new() -> Self {
323 Foo { t: 0.into() }
324 }
325}
326
327impl<T: From<i32>> Default for Foo<T> {
328 fn default() -> Self {
329 Self::new()
330 }
331}
332"#,
333 );
334 }
335
336 #[test]
337 fn new_function_with_generics_and_bounds() {
338 check_assist(
339 generate_default_from_new,
340 r#"
341//- minicore: default
342pub struct Foo<T, B> {
343 _tars: T,
344 _bar: B,
345}
346
347impl<T: From<i32>, B: From<i64>> Foo<T, B> {
348 pub fn ne$0w() -> Self {
349 unimplemented!()
350 }
351}
352"#,
353 r#"
354pub struct Foo<T, B> {
355 _tars: T,
356 _bar: B,
357}
358
359impl<T: From<i32>, B: From<i64>> Foo<T, B> {
360 pub fn new() -> Self {
361 unimplemented!()
362 }
363}
364
365impl<T: From<i32>, B: From<i64>> Default for Foo<T, B> {
366 fn default() -> Self {
367 Self::new()
368 }
369}
370"#,
371 );
372 }
373
374 #[test]
375 fn new_function_with_generic_and_where() {
376 check_assist(
377 generate_default_from_new,
378 r#"
379//- minicore: default
380pub struct Foo<T> {
381 t: T,
382}
383
384impl<T: From<i32>> Foo<T>
385where
386 Option<T>: Debug
387{
388 pub fn ne$0w() -> Self {
389 Foo { t: 0.into() }
390 }
391}
392"#,
393 r#"
394pub struct Foo<T> {
395 t: T,
396}
397
398impl<T: From<i32>> Foo<T>
399where
400 Option<T>: Debug
401{
402 pub fn new() -> Self {
403 Foo { t: 0.into() }
404 }
405}
406
407impl<T: From<i32>> Default for Foo<T>
408where
409 Option<T>: Debug
410{
411 fn default() -> Self {
412 Self::new()
413 }
414}
415"#,
416 );
417 }
418
419 #[test]
420 fn new_function_with_generics_and_where() {
421 check_assist(
422 generate_default_from_new,
423 r#"
424//- minicore: default
425pub struct Foo<T, B> {
426 _tars: T,
427 _bar: B,
428}
429
430impl<T: From<i32>, B: From<i64>> Foo<T, B>
431where
432 Option<T>: Debug, Option<B>: Debug,
433{
434 pub fn ne$0w() -> Self {
435 unimplemented!()
436 }
437}
438"#,
439 r#"
440pub struct Foo<T, B> {
441 _tars: T,
442 _bar: B,
443}
444
445impl<T: From<i32>, B: From<i64>> Foo<T, B>
446where
447 Option<T>: Debug, Option<B>: Debug,
448{
449 pub fn new() -> Self {
450 unimplemented!()
451 }
452}
453
454impl<T: From<i32>, B: From<i64>> Default for Foo<T, B>
455where
456 Option<T>: Debug, Option<B>: Debug,
457{
458 fn default() -> Self {
459 Self::new()
460 }
461}
462"#,
463 );
464 }
465
466 #[test]
467 fn new_function_with_parameters() {
468 cov_mark::check!(new_function_with_parameters);
469 check_assist_not_applicable(
470 generate_default_from_new,
471 r#"
472//- minicore: default
473struct Example { _inner: () }
474
475impl Example {
476 pub fn $0new(value: ()) -> Self {
477 Self { _inner: value }
478 }
479}
480"#,
481 );
482 }
483
484 #[test]
485 fn other_function_than_new() {
486 cov_mark::check!(other_function_than_new);
487 check_assist_not_applicable(
488 generate_default_from_new,
489 r#"
490//- minicore: default
491struct Example { _inner: () }
492
493impl Example {
494 pub fn a$0dd() -> Self {
495 Self { _inner: () }
496 }
497}
498
499"#,
500 );
501 }
502
503 #[test]
504 fn default_block_is_already_present() {
505 cov_mark::check!(default_block_is_already_present);
506 check_assist_not_applicable(
507 generate_default_from_new,
508 r#"
509//- minicore: default
510struct Example { _inner: () }
511
512impl Example {
513 pub fn n$0ew() -> Self {
514 Self { _inner: () }
515 }
516}
517
518impl Default for Example {
519 fn default() -> Self {
520 Self::new()
521 }
522}
523"#,
524 );
525 }
526
527 #[test]
528 fn standalone_new_function() {
529 check_assist_not_applicable(
530 generate_default_from_new,
531 r#"
532fn n$0ew() -> u32 {
533 0
534}
535"#,
536 );
537 }
538
539 #[test]
540 fn multiple_struct_blocks() {
541 check_assist(
542 generate_default_from_new,
543 r#"
544//- minicore: default
545struct Example { _inner: () }
546struct Test { value: u32 }
547
548impl Example {
549 pub fn new$0() -> Self {
550 Self { _inner: () }
551 }
552}
553"#,
554 r#"
555struct Example { _inner: () }
556struct Test { value: u32 }
557
558impl Example {
559 pub fn new() -> Self {
560 Self { _inner: () }
561 }
562}
563
564impl Default for Example {
565 fn default() -> Self {
566 Self::new()
567 }
568}
569"#,
570 );
571 }
572
573 #[test]
574 fn when_struct_is_after_impl() {
575 check_assist(
576 generate_default_from_new,
577 r#"
578//- minicore: default
579impl Example {
580 pub fn $0new() -> Self {
581 Self { _inner: () }
582 }
583}
584
585struct Example { _inner: () }
586"#,
587 r#"
588impl Example {
589 pub fn new() -> Self {
590 Self { _inner: () }
591 }
592}
593
594impl Default for Example {
595 fn default() -> Self {
596 Self::new()
597 }
598}
599
600struct Example { _inner: () }
601"#,
602 );
603 }
604
605 #[test]
606 fn struct_in_module() {
607 check_assist(
608 generate_default_from_new,
609 r#"
610//- minicore: default
611mod test {
612 struct Example { _inner: () }
613
614 impl Example {
615 pub fn n$0ew() -> Self {
616 Self { _inner: () }
617 }
618 }
619}
620"#,
621 r#"
622mod test {
623 struct Example { _inner: () }
624
625 impl Example {
626 pub fn new() -> Self {
627 Self { _inner: () }
628 }
629 }
630
631impl Default for Example {
632 fn default() -> Self {
633 Self::new()
634 }
635}
636}
637"#,
638 );
639 }
640
641 #[test]
642 fn struct_in_module_with_default() {
643 cov_mark::check!(struct_in_module_with_default);
644 check_assist_not_applicable(
645 generate_default_from_new,
646 r#"
647//- minicore: default
648mod test {
649 struct Example { _inner: () }
650
651 impl Example {
652 pub fn n$0ew() -> Self {
653 Self { _inner: () }
654 }
655 }
656
657 impl Default for Example {
658 fn default() -> Self {
659 Self::new()
660 }
661 }
662}
663"#,
664 );
665 }
666
667 #[test]
668 fn not_applicable_when_default_lang_item_is_missing() {
669 check_assist_not_applicable(
670 generate_default_from_new,
671 r#"
672struct S;
673impl S {
674 fn new$0() -> Self {}
675}
676"#,
677 );
678 }
679
680 #[test]
681 fn not_applicable_for_missing_self_ty() {
682 check_assist_not_applicable(generate_default_from_new, "impl { fn new$0() -> Self {} }");
684 }
685}