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