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