]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/add_missing_impl_members.rs
Merge #9841
[rust.git] / crates / ide_assists / src / handlers / add_missing_impl_members.rs
1 use hir::HasSource;
2 use ide_db::traits::resolve_target_trait;
3 use syntax::ast::{self, make, AstNode};
4
5 use crate::{
6     assist_context::{AssistContext, Assists},
7     utils::{
8         add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body, render_snippet,
9         Cursor, DefaultMethods,
10     },
11     AssistId, AssistKind,
12 };
13
14 // Assist: add_impl_missing_members
15 //
16 // Adds scaffold for required impl members.
17 //
18 // ```
19 // trait Trait<T> {
20 //     type X;
21 //     fn foo(&self) -> T;
22 //     fn bar(&self) {}
23 // }
24 //
25 // impl Trait<u32> for () {$0
26 //
27 // }
28 // ```
29 // ->
30 // ```
31 // trait Trait<T> {
32 //     type X;
33 //     fn foo(&self) -> T;
34 //     fn bar(&self) {}
35 // }
36 //
37 // impl Trait<u32> for () {
38 //     $0type X;
39 //
40 //     fn foo(&self) -> u32 {
41 //         todo!()
42 //     }
43 // }
44 // ```
45 pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
46     add_missing_impl_members_inner(
47         acc,
48         ctx,
49         DefaultMethods::No,
50         "add_impl_missing_members",
51         "Implement missing members",
52     )
53 }
54
55 // Assist: add_impl_default_members
56 //
57 // Adds scaffold for overriding default impl members.
58 //
59 // ```
60 // trait Trait {
61 //     type X;
62 //     fn foo(&self);
63 //     fn bar(&self) {}
64 // }
65 //
66 // impl Trait for () {
67 //     type X = ();
68 //     fn foo(&self) {}$0
69 // }
70 // ```
71 // ->
72 // ```
73 // trait Trait {
74 //     type X;
75 //     fn foo(&self);
76 //     fn bar(&self) {}
77 // }
78 //
79 // impl Trait for () {
80 //     type X = ();
81 //     fn foo(&self) {}
82 //
83 //     $0fn bar(&self) {}
84 // }
85 // ```
86 pub(crate) fn add_missing_default_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
87     add_missing_impl_members_inner(
88         acc,
89         ctx,
90         DefaultMethods::Only,
91         "add_impl_default_members",
92         "Implement default members",
93     )
94 }
95
96 fn add_missing_impl_members_inner(
97     acc: &mut Assists,
98     ctx: &AssistContext,
99     mode: DefaultMethods,
100     assist_id: &'static str,
101     label: &'static str,
102 ) -> Option<()> {
103     let _p = profile::span("add_missing_impl_members_inner");
104     let impl_def = ctx.find_node_at_offset::<ast::Impl>()?;
105     let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?;
106
107     let missing_items = filter_assoc_items(
108         ctx.db(),
109         &ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def),
110         mode,
111     );
112
113     if missing_items.is_empty() {
114         return None;
115     }
116
117     let target = impl_def.syntax().text_range();
118     acc.add(AssistId(assist_id, AssistKind::QuickFix), label, target, |builder| {
119         let target_scope = ctx.sema.scope(impl_def.syntax());
120         let (new_impl_def, first_new_item) = add_trait_assoc_items_to_impl(
121             &ctx.sema,
122             missing_items,
123             trait_,
124             impl_def.clone(),
125             target_scope,
126         );
127         match ctx.config.snippet_cap {
128             None => builder.replace(target, new_impl_def.to_string()),
129             Some(cap) => {
130                 let mut cursor = Cursor::Before(first_new_item.syntax());
131                 let placeholder;
132                 if let ast::AssocItem::Fn(func) = &first_new_item {
133                     if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
134                         if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
135                         {
136                             if m.syntax().text() == "todo!()" {
137                                 placeholder = m;
138                                 cursor = Cursor::Replace(placeholder.syntax());
139                             }
140                         }
141                     }
142                 }
143                 builder.replace_snippet(
144                     cap,
145                     target,
146                     render_snippet(cap, new_impl_def.syntax(), cursor),
147                 )
148             }
149         };
150     })
151 }
152
153 fn try_gen_trait_body(
154     ctx: &AssistContext,
155     func: &ast::Fn,
156     trait_: &hir::Trait,
157     impl_def: &ast::Impl,
158 ) -> Option<()> {
159     let trait_path = make::ext::ident_path(&trait_.name(ctx.db()).to_string());
160     let hir_ty = ctx.sema.resolve_type(&impl_def.self_ty()?)?;
161     let adt = hir_ty.as_adt()?.source(ctx.db())?;
162     gen_trait_fn_body(func, &trait_path, &adt.value)
163 }
164
165 #[cfg(test)]
166 mod tests {
167     use crate::tests::{check_assist, check_assist_not_applicable};
168
169     use super::*;
170
171     #[test]
172     fn test_add_missing_impl_members() {
173         check_assist(
174             add_missing_impl_members,
175             r#"
176 trait Foo {
177     type Output;
178
179     const CONST: usize = 42;
180
181     fn foo(&self);
182     fn bar(&self);
183     fn baz(&self);
184 }
185
186 struct S;
187
188 impl Foo for S {
189     fn bar(&self) {}
190 $0
191 }"#,
192             r#"
193 trait Foo {
194     type Output;
195
196     const CONST: usize = 42;
197
198     fn foo(&self);
199     fn bar(&self);
200     fn baz(&self);
201 }
202
203 struct S;
204
205 impl Foo for S {
206     fn bar(&self) {}
207
208     $0type Output;
209
210     const CONST: usize = 42;
211
212     fn foo(&self) {
213         todo!()
214     }
215
216     fn baz(&self) {
217         todo!()
218     }
219
220 }"#,
221         );
222     }
223
224     #[test]
225     fn test_copied_overriden_members() {
226         check_assist(
227             add_missing_impl_members,
228             r#"
229 trait Foo {
230     fn foo(&self);
231     fn bar(&self) -> bool { true }
232     fn baz(&self) -> u32 { 42 }
233 }
234
235 struct S;
236
237 impl Foo for S {
238     fn bar(&self) {}
239 $0
240 }"#,
241             r#"
242 trait Foo {
243     fn foo(&self);
244     fn bar(&self) -> bool { true }
245     fn baz(&self) -> u32 { 42 }
246 }
247
248 struct S;
249
250 impl Foo for S {
251     fn bar(&self) {}
252
253     fn foo(&self) {
254         ${0:todo!()}
255     }
256
257 }"#,
258         );
259     }
260
261     #[test]
262     fn test_empty_impl_def() {
263         check_assist(
264             add_missing_impl_members,
265             r#"
266 trait Foo { fn foo(&self); }
267 struct S;
268 impl Foo for S { $0 }"#,
269             r#"
270 trait Foo { fn foo(&self); }
271 struct S;
272 impl Foo for S {
273     fn foo(&self) {
274         ${0:todo!()}
275     }
276 }"#,
277         );
278     }
279
280     #[test]
281     fn test_impl_def_without_braces() {
282         check_assist(
283             add_missing_impl_members,
284             r#"
285 trait Foo { fn foo(&self); }
286 struct S;
287 impl Foo for S$0"#,
288             r#"
289 trait Foo { fn foo(&self); }
290 struct S;
291 impl Foo for S {
292     fn foo(&self) {
293         ${0:todo!()}
294     }
295 }"#,
296         );
297     }
298
299     #[test]
300     fn fill_in_type_params_1() {
301         check_assist(
302             add_missing_impl_members,
303             r#"
304 trait Foo<T> { fn foo(&self, t: T) -> &T; }
305 struct S;
306 impl Foo<u32> for S { $0 }"#,
307             r#"
308 trait Foo<T> { fn foo(&self, t: T) -> &T; }
309 struct S;
310 impl Foo<u32> for S {
311     fn foo(&self, t: u32) -> &u32 {
312         ${0:todo!()}
313     }
314 }"#,
315         );
316     }
317
318     #[test]
319     fn fill_in_type_params_2() {
320         check_assist(
321             add_missing_impl_members,
322             r#"
323 trait Foo<T> { fn foo(&self, t: T) -> &T; }
324 struct S;
325 impl<U> Foo<U> for S { $0 }"#,
326             r#"
327 trait Foo<T> { fn foo(&self, t: T) -> &T; }
328 struct S;
329 impl<U> Foo<U> for S {
330     fn foo(&self, t: U) -> &U {
331         ${0:todo!()}
332     }
333 }"#,
334         );
335     }
336
337     #[test]
338     fn test_cursor_after_empty_impl_def() {
339         check_assist(
340             add_missing_impl_members,
341             r#"
342 trait Foo { fn foo(&self); }
343 struct S;
344 impl Foo for S {}$0"#,
345             r#"
346 trait Foo { fn foo(&self); }
347 struct S;
348 impl Foo for S {
349     fn foo(&self) {
350         ${0:todo!()}
351     }
352 }"#,
353         )
354     }
355
356     #[test]
357     fn test_qualify_path_1() {
358         check_assist(
359             add_missing_impl_members,
360             r#"
361 mod foo {
362     pub struct Bar;
363     trait Foo { fn foo(&self, bar: Bar); }
364 }
365 struct S;
366 impl foo::Foo for S { $0 }"#,
367             r#"
368 mod foo {
369     pub struct Bar;
370     trait Foo { fn foo(&self, bar: Bar); }
371 }
372 struct S;
373 impl foo::Foo for S {
374     fn foo(&self, bar: foo::Bar) {
375         ${0:todo!()}
376     }
377 }"#,
378         );
379     }
380
381     #[test]
382     fn test_qualify_path_2() {
383         check_assist(
384             add_missing_impl_members,
385             r#"
386 mod foo {
387     pub mod bar {
388         pub struct Bar;
389         pub trait Foo { fn foo(&self, bar: Bar); }
390     }
391 }
392
393 use foo::bar;
394
395 struct S;
396 impl bar::Foo for S { $0 }"#,
397             r#"
398 mod foo {
399     pub mod bar {
400         pub struct Bar;
401         pub trait Foo { fn foo(&self, bar: Bar); }
402     }
403 }
404
405 use foo::bar;
406
407 struct S;
408 impl bar::Foo for S {
409     fn foo(&self, bar: bar::Bar) {
410         ${0:todo!()}
411     }
412 }"#,
413         );
414     }
415
416     #[test]
417     fn test_qualify_path_generic() {
418         check_assist(
419             add_missing_impl_members,
420             r#"
421 mod foo {
422     pub struct Bar<T>;
423     trait Foo { fn foo(&self, bar: Bar<u32>); }
424 }
425 struct S;
426 impl foo::Foo for S { $0 }"#,
427             r#"
428 mod foo {
429     pub struct Bar<T>;
430     trait Foo { fn foo(&self, bar: Bar<u32>); }
431 }
432 struct S;
433 impl foo::Foo for S {
434     fn foo(&self, bar: foo::Bar<u32>) {
435         ${0:todo!()}
436     }
437 }"#,
438         );
439     }
440
441     #[test]
442     fn test_qualify_path_and_substitute_param() {
443         check_assist(
444             add_missing_impl_members,
445             r#"
446 mod foo {
447     pub struct Bar<T>;
448     trait Foo<T> { fn foo(&self, bar: Bar<T>); }
449 }
450 struct S;
451 impl foo::Foo<u32> for S { $0 }"#,
452             r#"
453 mod foo {
454     pub struct Bar<T>;
455     trait Foo<T> { fn foo(&self, bar: Bar<T>); }
456 }
457 struct S;
458 impl foo::Foo<u32> for S {
459     fn foo(&self, bar: foo::Bar<u32>) {
460         ${0:todo!()}
461     }
462 }"#,
463         );
464     }
465
466     #[test]
467     fn test_substitute_param_no_qualify() {
468         // when substituting params, the substituted param should not be qualified!
469         check_assist(
470             add_missing_impl_members,
471             r#"
472 mod foo {
473     trait Foo<T> { fn foo(&self, bar: T); }
474     pub struct Param;
475 }
476 struct Param;
477 struct S;
478 impl foo::Foo<Param> for S { $0 }"#,
479             r#"
480 mod foo {
481     trait Foo<T> { fn foo(&self, bar: T); }
482     pub struct Param;
483 }
484 struct Param;
485 struct S;
486 impl foo::Foo<Param> for S {
487     fn foo(&self, bar: Param) {
488         ${0:todo!()}
489     }
490 }"#,
491         );
492     }
493
494     #[test]
495     fn test_qualify_path_associated_item() {
496         check_assist(
497             add_missing_impl_members,
498             r#"
499 mod foo {
500     pub struct Bar<T>;
501     impl Bar<T> { type Assoc = u32; }
502     trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
503 }
504 struct S;
505 impl foo::Foo for S { $0 }"#,
506             r#"
507 mod foo {
508     pub struct Bar<T>;
509     impl Bar<T> { type Assoc = u32; }
510     trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
511 }
512 struct S;
513 impl foo::Foo for S {
514     fn foo(&self, bar: foo::Bar<u32>::Assoc) {
515         ${0:todo!()}
516     }
517 }"#,
518         );
519     }
520
521     #[test]
522     fn test_qualify_path_nested() {
523         check_assist(
524             add_missing_impl_members,
525             r#"
526 mod foo {
527     pub struct Bar<T>;
528     pub struct Baz;
529     trait Foo { fn foo(&self, bar: Bar<Baz>); }
530 }
531 struct S;
532 impl foo::Foo for S { $0 }"#,
533             r#"
534 mod foo {
535     pub struct Bar<T>;
536     pub struct Baz;
537     trait Foo { fn foo(&self, bar: Bar<Baz>); }
538 }
539 struct S;
540 impl foo::Foo for S {
541     fn foo(&self, bar: foo::Bar<foo::Baz>) {
542         ${0:todo!()}
543     }
544 }"#,
545         );
546     }
547
548     #[test]
549     fn test_qualify_path_fn_trait_notation() {
550         check_assist(
551             add_missing_impl_members,
552             r#"
553 mod foo {
554     pub trait Fn<Args> { type Output; }
555     trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
556 }
557 struct S;
558 impl foo::Foo for S { $0 }"#,
559             r#"
560 mod foo {
561     pub trait Fn<Args> { type Output; }
562     trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
563 }
564 struct S;
565 impl foo::Foo for S {
566     fn foo(&self, bar: dyn Fn(u32) -> i32) {
567         ${0:todo!()}
568     }
569 }"#,
570         );
571     }
572
573     #[test]
574     fn test_empty_trait() {
575         check_assist_not_applicable(
576             add_missing_impl_members,
577             r#"
578 trait Foo;
579 struct S;
580 impl Foo for S { $0 }"#,
581         )
582     }
583
584     #[test]
585     fn test_ignore_unnamed_trait_members_and_default_methods() {
586         check_assist_not_applicable(
587             add_missing_impl_members,
588             r#"
589 trait Foo {
590     fn (arg: u32);
591     fn valid(some: u32) -> bool { false }
592 }
593 struct S;
594 impl Foo for S { $0 }"#,
595         )
596     }
597
598     #[test]
599     fn test_with_docstring_and_attrs() {
600         check_assist(
601             add_missing_impl_members,
602             r#"
603 #[doc(alias = "test alias")]
604 trait Foo {
605     /// doc string
606     type Output;
607
608     #[must_use]
609     fn foo(&self);
610 }
611 struct S;
612 impl Foo for S {}$0"#,
613             r#"
614 #[doc(alias = "test alias")]
615 trait Foo {
616     /// doc string
617     type Output;
618
619     #[must_use]
620     fn foo(&self);
621 }
622 struct S;
623 impl Foo for S {
624     $0type Output;
625
626     fn foo(&self) {
627         todo!()
628     }
629 }"#,
630         )
631     }
632
633     #[test]
634     fn test_default_methods() {
635         check_assist(
636             add_missing_default_members,
637             r#"
638 trait Foo {
639     type Output;
640
641     const CONST: usize = 42;
642
643     fn valid(some: u32) -> bool { false }
644     fn foo(some: u32) -> bool;
645 }
646 struct S;
647 impl Foo for S { $0 }"#,
648             r#"
649 trait Foo {
650     type Output;
651
652     const CONST: usize = 42;
653
654     fn valid(some: u32) -> bool { false }
655     fn foo(some: u32) -> bool;
656 }
657 struct S;
658 impl Foo for S {
659     $0fn valid(some: u32) -> bool { false }
660 }"#,
661         )
662     }
663
664     #[test]
665     fn test_generic_single_default_parameter() {
666         check_assist(
667             add_missing_impl_members,
668             r#"
669 trait Foo<T = Self> {
670     fn bar(&self, other: &T);
671 }
672
673 struct S;
674 impl Foo for S { $0 }"#,
675             r#"
676 trait Foo<T = Self> {
677     fn bar(&self, other: &T);
678 }
679
680 struct S;
681 impl Foo for S {
682     fn bar(&self, other: &Self) {
683         ${0:todo!()}
684     }
685 }"#,
686         )
687     }
688
689     #[test]
690     fn test_generic_default_parameter_is_second() {
691         check_assist(
692             add_missing_impl_members,
693             r#"
694 trait Foo<T1, T2 = Self> {
695     fn bar(&self, this: &T1, that: &T2);
696 }
697
698 struct S<T>;
699 impl Foo<T> for S<T> { $0 }"#,
700             r#"
701 trait Foo<T1, T2 = Self> {
702     fn bar(&self, this: &T1, that: &T2);
703 }
704
705 struct S<T>;
706 impl Foo<T> for S<T> {
707     fn bar(&self, this: &T, that: &Self) {
708         ${0:todo!()}
709     }
710 }"#,
711         )
712     }
713
714     #[test]
715     fn test_assoc_type_bounds_are_removed() {
716         check_assist(
717             add_missing_impl_members,
718             r#"
719 trait Tr {
720     type Ty: Copy + 'static;
721 }
722
723 impl Tr for ()$0 {
724 }"#,
725             r#"
726 trait Tr {
727     type Ty: Copy + 'static;
728 }
729
730 impl Tr for () {
731     $0type Ty;
732 }"#,
733         )
734     }
735
736     #[test]
737     fn test_whitespace_fixup_preserves_bad_tokens() {
738         check_assist(
739             add_missing_impl_members,
740             r#"
741 trait Tr {
742     fn foo();
743 }
744
745 impl Tr for ()$0 {
746     +++
747 }"#,
748             r#"
749 trait Tr {
750     fn foo();
751 }
752
753 impl Tr for () {
754     fn foo() {
755         ${0:todo!()}
756     }
757     +++
758 }"#,
759         )
760     }
761
762     #[test]
763     fn test_whitespace_fixup_preserves_comments() {
764         check_assist(
765             add_missing_impl_members,
766             r#"
767 trait Tr {
768     fn foo();
769 }
770
771 impl Tr for ()$0 {
772     // very important
773 }"#,
774             r#"
775 trait Tr {
776     fn foo();
777 }
778
779 impl Tr for () {
780     fn foo() {
781         ${0:todo!()}
782     }
783     // very important
784 }"#,
785         )
786     }
787
788     #[test]
789     fn weird_path() {
790         check_assist(
791             add_missing_impl_members,
792             r#"
793 trait Test {
794     fn foo(&self, x: crate)
795 }
796 impl Test for () {
797     $0
798 }
799 "#,
800             r#"
801 trait Test {
802     fn foo(&self, x: crate)
803 }
804 impl Test for () {
805     fn foo(&self, x: crate) {
806         ${0:todo!()}
807     }
808 }
809 "#,
810         )
811     }
812
813     #[test]
814     fn missing_generic_type() {
815         check_assist(
816             add_missing_impl_members,
817             r#"
818 trait Foo<BAR> {
819     fn foo(&self, bar: BAR);
820 }
821 impl Foo for () {
822     $0
823 }
824 "#,
825             r#"
826 trait Foo<BAR> {
827     fn foo(&self, bar: BAR);
828 }
829 impl Foo for () {
830     fn foo(&self, bar: BAR) {
831         ${0:todo!()}
832     }
833 }
834 "#,
835         )
836     }
837
838     #[test]
839     fn does_not_requalify_self_as_crate() {
840         check_assist(
841             add_missing_default_members,
842             r"
843 struct Wrapper<T>(T);
844
845 trait T {
846     fn f(self) -> Wrapper<Self> {
847         Wrapper(self)
848     }
849 }
850
851 impl T for () {
852     $0
853 }
854 ",
855             r"
856 struct Wrapper<T>(T);
857
858 trait T {
859     fn f(self) -> Wrapper<Self> {
860         Wrapper(self)
861     }
862 }
863
864 impl T for () {
865     $0fn f(self) -> Wrapper<Self> {
866         Wrapper(self)
867     }
868 }
869 ",
870         );
871     }
872
873     #[test]
874     fn test_default_body_generation() {
875         check_assist(
876             add_missing_impl_members,
877             r#"
878 //- minicore: default
879 struct Foo(usize);
880
881 impl Default for Foo {
882     $0
883 }
884 "#,
885             r#"
886 struct Foo(usize);
887
888 impl Default for Foo {
889     $0fn default() -> Self {
890         Self(Default::default())
891     }
892 }
893 "#,
894         )
895     }
896 }