]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/generate_default_from_new.rs
Merge #8795
[rust.git] / crates / ide_assists / src / handlers / generate_default_from_new.rs
1 use crate::{
2     assist_context::{AssistContext, Assists},
3     AssistId,
4 };
5 use ide_db::helpers::FamousDefs;
6 use itertools::Itertools;
7 use stdx::format_to;
8 use syntax::{
9     ast::{self, GenericParamsOwner, Impl, NameOwner, TypeBoundsOwner},
10     AstNode,
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 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     }
118
119     buf
120 }
121
122 fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> bool {
123     let db = ctx.sema.db;
124     let impl_ = ctx.sema.to_def(impl_);
125     let impl_def = match impl_ {
126         Some(value) => value,
127         None => return false,
128     };
129
130     let ty = impl_def.self_ty(db);
131     let krate = impl_def.module(db).krate();
132     let default = FamousDefs(&ctx.sema, Some(krate)).core_default_Default();
133     let default_trait = match default {
134         Some(value) => value,
135         None => return false,
136     };
137
138     ty.impls_trait(db, default_trait, &[])
139 }
140
141 #[cfg(test)]
142 mod tests {
143     use ide_db::helpers::FamousDefs;
144
145     use crate::tests::{check_assist, check_assist_not_applicable};
146
147     use super::*;
148
149     #[test]
150     fn generate_default() {
151         check_pass(
152             r#"
153 struct Example { _inner: () }
154
155 impl Example {
156     pub fn ne$0w() -> Self {
157         Self { _inner: () }
158     }
159 }
160
161 fn main() {}
162 "#,
163             r#"
164 struct Example { _inner: () }
165
166 impl Example {
167     pub fn new() -> Self {
168         Self { _inner: () }
169     }
170 }
171
172 impl Default for Example {
173     fn default() -> Self {
174         Self::new()
175     }
176 }
177
178 fn main() {}
179 "#,
180         );
181     }
182
183     #[test]
184     fn generate_default2() {
185         check_pass(
186             r#"
187 struct Test { value: u32 }
188
189 impl Test {
190     pub fn ne$0w() -> Self {
191         Self { value: 0 }
192     }
193 }
194 "#,
195             r#"
196 struct Test { value: u32 }
197
198 impl Test {
199     pub fn new() -> Self {
200         Self { value: 0 }
201     }
202 }
203
204 impl Default for Test {
205     fn default() -> Self {
206         Self::new()
207     }
208 }
209 "#,
210         );
211     }
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
441     #[test]
442     fn new_function_with_parameters() {
443         cov_mark::check!(new_function_with_parameters);
444         check_not_applicable(
445             r#"
446 struct Example { _inner: () }
447
448 impl Example {
449     pub fn $0new(value: ()) -> Self {
450         Self { _inner: value }
451     }
452 }
453 "#,
454         );
455     }
456
457     #[test]
458     fn other_function_than_new() {
459         cov_mark::check!(other_function_than_new);
460         check_not_applicable(
461             r#"
462 struct Example { _inner: () }
463
464 impl Example {
465     pub fn a$0dd() -> Self {
466         Self { _inner: () }
467     }
468 }
469
470 "#,
471         );
472     }
473
474     #[test]
475     fn default_block_is_already_present() {
476         cov_mark::check!(default_block_is_already_present);
477         check_not_applicable(
478             r#"
479 struct Example { _inner: () }
480
481 impl Example {
482     pub fn n$0ew() -> Self {
483         Self { _inner: () }
484     }
485 }
486
487 impl Default for Example {
488     fn default() -> Self {
489         Self::new()
490     }
491 }
492 "#,
493         );
494     }
495
496     #[test]
497     fn standalone_new_function() {
498         check_not_applicable(
499             r#"
500 fn n$0ew() -> u32 {
501     0
502 }
503 "#,
504         );
505     }
506
507     #[test]
508     fn multiple_struct_blocks() {
509         check_pass(
510             r#"
511 struct Example { _inner: () }
512 struct Test { value: u32 }
513
514 impl Example {
515     pub fn new$0() -> Self {
516         Self { _inner: () }
517     }
518 }
519 "#,
520             r#"
521 struct Example { _inner: () }
522 struct Test { value: u32 }
523
524 impl Example {
525     pub fn new() -> Self {
526         Self { _inner: () }
527     }
528 }
529
530 impl Default for Example {
531     fn default() -> Self {
532         Self::new()
533     }
534 }
535 "#,
536         );
537     }
538
539     #[test]
540     fn when_struct_is_after_impl() {
541         check_pass(
542             r#"
543 impl Example {
544     pub fn $0new() -> Self {
545         Self { _inner: () }
546     }
547 }
548
549 struct Example { _inner: () }
550 "#,
551             r#"
552 impl Example {
553     pub fn new() -> Self {
554         Self { _inner: () }
555     }
556 }
557
558 impl Default for Example {
559     fn default() -> Self {
560         Self::new()
561     }
562 }
563
564 struct Example { _inner: () }
565 "#,
566         );
567     }
568
569     #[test]
570     fn struct_in_module() {
571         check_pass(
572             r#"
573 mod test {
574     struct Example { _inner: () }
575
576     impl Example {
577         pub fn n$0ew() -> Self {
578             Self { _inner: () }
579         }
580     }
581 }
582 "#,
583             r#"
584 mod test {
585     struct Example { _inner: () }
586
587     impl Example {
588         pub fn new() -> Self {
589             Self { _inner: () }
590         }
591     }
592
593 impl Default for Example {
594     fn default() -> Self {
595         Self::new()
596     }
597 }
598 }
599 "#,
600         );
601     }
602
603     #[test]
604     fn struct_in_module_with_default() {
605         cov_mark::check!(struct_in_module_with_default);
606         check_not_applicable(
607             r#"
608 mod test {
609     struct Example { _inner: () }
610
611     impl Example {
612         pub fn n$0ew() -> Self {
613             Self { _inner: () }
614         }
615     }
616
617     impl Default for Example {
618         fn default() -> Self {
619             Self::new()
620         }
621     }
622 }
623 "#,
624         );
625     }
626
627     fn check_pass(before: &str, after: &str) {
628         let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
629         check_assist(generate_default_from_new, before, after);
630     }
631
632     fn check_not_applicable(before: &str) {
633         let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
634         check_assist_not_applicable(generate_default_from_new, before);
635     }
636 }