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