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