]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
Merge commit 'ac0e10aa68325235069a842f47499852b2dee79e' into clippyup
[rust.git] / src / tools / rust-analyzer / crates / ide-completion / src / completions / item_list / trait_impl.rs
1 //! Completion for associated items in a trait implementation.
2 //!
3 //! This module adds the completion items related to implementing associated
4 //! items within an `impl Trait for Struct` block. The current context node
5 //! must be within either a `FN`, `TYPE_ALIAS`, or `CONST` node
6 //! and an direct child of an `IMPL`.
7 //!
8 //! # Examples
9 //!
10 //! Considering the following trait `impl`:
11 //!
12 //! ```ignore
13 //! trait SomeTrait {
14 //!     fn foo();
15 //! }
16 //!
17 //! impl SomeTrait for () {
18 //!     fn f$0
19 //! }
20 //! ```
21 //!
22 //! may result in the completion of the following method:
23 //!
24 //! ```ignore
25 //! # trait SomeTrait {
26 //! #    fn foo();
27 //! # }
28 //!
29 //! impl SomeTrait for () {
30 //!     fn foo() {}$0
31 //! }
32 //! ```
33
34 use hir::{self, HasAttrs};
35 use ide_db::{
36     path_transform::PathTransform, syntax_helpers::insert_whitespace_into_node,
37     traits::get_missing_assoc_items, SymbolKind,
38 };
39 use syntax::{
40     ast::{self, edit_in_place::AttrsOwnerEdit},
41     AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, T,
42 };
43 use text_edit::TextEdit;
44
45 use crate::{
46     context::PathCompletionCtx, CompletionContext, CompletionItem, CompletionItemKind,
47     CompletionRelevance, Completions,
48 };
49
50 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
51 enum ImplCompletionKind {
52     All,
53     Fn,
54     TypeAlias,
55     Const,
56 }
57
58 pub(crate) fn complete_trait_impl_const(
59     acc: &mut Completions,
60     ctx: &CompletionContext<'_>,
61     name: &Option<ast::Name>,
62 ) -> Option<()> {
63     complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::Const)
64 }
65
66 pub(crate) fn complete_trait_impl_type_alias(
67     acc: &mut Completions,
68     ctx: &CompletionContext<'_>,
69     name: &Option<ast::Name>,
70 ) -> Option<()> {
71     complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::TypeAlias)
72 }
73
74 pub(crate) fn complete_trait_impl_fn(
75     acc: &mut Completions,
76     ctx: &CompletionContext<'_>,
77     name: &Option<ast::Name>,
78 ) -> Option<()> {
79     complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::Fn)
80 }
81
82 fn complete_trait_impl_name(
83     acc: &mut Completions,
84     ctx: &CompletionContext<'_>,
85     name: &Option<ast::Name>,
86     kind: ImplCompletionKind,
87 ) -> Option<()> {
88     let token = ctx.token.clone();
89     let item = match name {
90         Some(name) => name.syntax().parent(),
91         None => if token.kind() == SyntaxKind::WHITESPACE { token.prev_token()? } else { token }
92             .parent(),
93     }?;
94     complete_trait_impl(
95         acc,
96         ctx,
97         kind,
98         replacement_range(ctx, &item),
99         // item -> ASSOC_ITEM_LIST -> IMPL
100         &ast::Impl::cast(item.parent()?.parent()?)?,
101     );
102     Some(())
103 }
104
105 pub(crate) fn complete_trait_impl_item_by_name(
106     acc: &mut Completions,
107     ctx: &CompletionContext<'_>,
108     path_ctx: &PathCompletionCtx,
109     name_ref: &Option<ast::NameRef>,
110     impl_: &Option<ast::Impl>,
111 ) {
112     if !path_ctx.is_trivial_path() {
113         return;
114     }
115     if let Some(impl_) = impl_ {
116         complete_trait_impl(
117             acc,
118             ctx,
119             ImplCompletionKind::All,
120             match name_ref {
121                 Some(name) => name.syntax().text_range(),
122                 None => ctx.source_range(),
123             },
124             impl_,
125         );
126     }
127 }
128
129 fn complete_trait_impl(
130     acc: &mut Completions,
131     ctx: &CompletionContext<'_>,
132     kind: ImplCompletionKind,
133     replacement_range: TextRange,
134     impl_def: &ast::Impl,
135 ) {
136     if let Some(hir_impl) = ctx.sema.to_def(impl_def) {
137         get_missing_assoc_items(&ctx.sema, impl_def).into_iter().for_each(|item| {
138             use self::ImplCompletionKind::*;
139             match (item, kind) {
140                 (hir::AssocItem::Function(func), All | Fn) => {
141                     add_function_impl(acc, ctx, replacement_range, func, hir_impl)
142                 }
143                 (hir::AssocItem::TypeAlias(type_alias), All | TypeAlias) => {
144                     add_type_alias_impl(acc, ctx, replacement_range, type_alias)
145                 }
146                 (hir::AssocItem::Const(const_), All | Const) => {
147                     add_const_impl(acc, ctx, replacement_range, const_, hir_impl)
148                 }
149                 _ => {}
150             }
151         });
152     }
153 }
154
155 fn add_function_impl(
156     acc: &mut Completions,
157     ctx: &CompletionContext<'_>,
158     replacement_range: TextRange,
159     func: hir::Function,
160     impl_def: hir::Impl,
161 ) {
162     let fn_name = func.name(ctx.db);
163
164     let label = format!(
165         "fn {}({})",
166         fn_name,
167         if func.assoc_fn_params(ctx.db).is_empty() { "" } else { ".." }
168     );
169
170     let completion_kind = if func.has_self_param(ctx.db) {
171         CompletionItemKind::Method
172     } else {
173         CompletionItemKind::SymbolKind(SymbolKind::Function)
174     };
175
176     let mut item = CompletionItem::new(completion_kind, replacement_range, label);
177     item.lookup_by(format!("fn {}", fn_name))
178         .set_documentation(func.docs(ctx.db))
179         .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
180
181     if let Some(source) = ctx.sema.source(func) {
182         let assoc_item = ast::AssocItem::Fn(source.value);
183         if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) {
184             let transformed_fn = match transformed_item {
185                 ast::AssocItem::Fn(func) => func,
186                 _ => unreachable!(),
187             };
188
189             let function_decl = function_declaration(&transformed_fn, source.file_id.is_macro());
190             match ctx.config.snippet_cap {
191                 Some(cap) => {
192                     let snippet = format!("{} {{\n    $0\n}}", function_decl);
193                     item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet));
194                 }
195                 None => {
196                     let header = format!("{} {{", function_decl);
197                     item.text_edit(TextEdit::replace(replacement_range, header));
198                 }
199             };
200             item.add_to(acc);
201         }
202     }
203 }
204
205 /// Transform a relevant associated item to inline generics from the impl, remove attrs and docs, etc.
206 fn get_transformed_assoc_item(
207     ctx: &CompletionContext<'_>,
208     assoc_item: ast::AssocItem,
209     impl_def: hir::Impl,
210 ) -> Option<ast::AssocItem> {
211     let assoc_item = assoc_item.clone_for_update();
212     let trait_ = impl_def.trait_(ctx.db)?;
213     let source_scope = &ctx.sema.scope_for_def(trait_);
214     let target_scope = &ctx.sema.scope(ctx.sema.source(impl_def)?.syntax().value)?;
215     let transform = PathTransform::trait_impl(
216         target_scope,
217         source_scope,
218         trait_,
219         ctx.sema.source(impl_def)?.value,
220     );
221
222     transform.apply(assoc_item.syntax());
223     if let ast::AssocItem::Fn(func) = &assoc_item {
224         func.remove_attrs_and_docs();
225     }
226     Some(assoc_item)
227 }
228
229 fn add_type_alias_impl(
230     acc: &mut Completions,
231     ctx: &CompletionContext<'_>,
232     replacement_range: TextRange,
233     type_alias: hir::TypeAlias,
234 ) {
235     let alias_name = type_alias.name(ctx.db);
236     let (alias_name, escaped_name) =
237         (alias_name.unescaped().to_smol_str(), alias_name.to_smol_str());
238
239     let label = format!("type {} =", alias_name);
240     let replacement = format!("type {} = ", escaped_name);
241
242     let mut item = CompletionItem::new(SymbolKind::TypeAlias, replacement_range, label);
243     item.lookup_by(format!("type {}", alias_name))
244         .set_documentation(type_alias.docs(ctx.db))
245         .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
246     match ctx.config.snippet_cap {
247         Some(cap) => item
248             .snippet_edit(cap, TextEdit::replace(replacement_range, format!("{}$0;", replacement))),
249         None => item.text_edit(TextEdit::replace(replacement_range, replacement)),
250     };
251     item.add_to(acc);
252 }
253
254 fn add_const_impl(
255     acc: &mut Completions,
256     ctx: &CompletionContext<'_>,
257     replacement_range: TextRange,
258     const_: hir::Const,
259     impl_def: hir::Impl,
260 ) {
261     let const_name = const_.name(ctx.db).map(|n| n.to_smol_str());
262
263     if let Some(const_name) = const_name {
264         if let Some(source) = ctx.sema.source(const_) {
265             let assoc_item = ast::AssocItem::Const(source.value);
266             if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) {
267                 let transformed_const = match transformed_item {
268                     ast::AssocItem::Const(const_) => const_,
269                     _ => unreachable!(),
270                 };
271
272                 let label = make_const_compl_syntax(&transformed_const, source.file_id.is_macro());
273                 let replacement = format!("{} ", label);
274
275                 let mut item = CompletionItem::new(SymbolKind::Const, replacement_range, label);
276                 item.lookup_by(format!("const {}", const_name))
277                     .set_documentation(const_.docs(ctx.db))
278                     .set_relevance(CompletionRelevance {
279                         is_item_from_trait: true,
280                         ..Default::default()
281                     });
282                 match ctx.config.snippet_cap {
283                     Some(cap) => item.snippet_edit(
284                         cap,
285                         TextEdit::replace(replacement_range, format!("{}$0;", replacement)),
286                     ),
287                     None => item.text_edit(TextEdit::replace(replacement_range, replacement)),
288                 };
289                 item.add_to(acc);
290             }
291         }
292     }
293 }
294
295 fn make_const_compl_syntax(const_: &ast::Const, needs_whitespace: bool) -> String {
296     const_.remove_attrs_and_docs();
297     let const_ = if needs_whitespace {
298         insert_whitespace_into_node::insert_ws_into(const_.syntax().clone())
299     } else {
300         const_.syntax().clone()
301     };
302
303     let start = const_.text_range().start();
304     let const_end = const_.text_range().end();
305
306     let end = const_
307         .children_with_tokens()
308         .find(|s| s.kind() == T![;] || s.kind() == T![=])
309         .map_or(const_end, |f| f.text_range().start());
310
311     let len = end - start;
312     let range = TextRange::new(0.into(), len);
313
314     let syntax = const_.text().slice(range).to_string();
315
316     format!("{} =", syntax.trim_end())
317 }
318
319 fn function_declaration(node: &ast::Fn, needs_whitespace: bool) -> String {
320     node.remove_attrs_and_docs();
321
322     let node = if needs_whitespace {
323         insert_whitespace_into_node::insert_ws_into(node.syntax().clone())
324     } else {
325         node.syntax().clone()
326     };
327
328     let start = node.text_range().start();
329     let end = node.text_range().end();
330
331     let end = node
332         .last_child_or_token()
333         .filter(|s| s.kind() == T![;] || s.kind() == SyntaxKind::BLOCK_EXPR)
334         .map_or(end, |f| f.text_range().start());
335
336     let len = end - start;
337     let range = TextRange::new(0.into(), len);
338
339     let syntax = node.text().slice(range).to_string();
340
341     syntax.trim_end().to_owned()
342 }
343
344 fn replacement_range(ctx: &CompletionContext<'_>, item: &SyntaxNode) -> TextRange {
345     let first_child = item
346         .children_with_tokens()
347         .find(|child| {
348             !matches!(child.kind(), SyntaxKind::COMMENT | SyntaxKind::WHITESPACE | SyntaxKind::ATTR)
349         })
350         .unwrap_or_else(|| SyntaxElement::Node(item.clone()));
351
352     TextRange::new(first_child.text_range().start(), ctx.source_range().end())
353 }
354
355 #[cfg(test)]
356 mod tests {
357     use expect_test::{expect, Expect};
358
359     use crate::tests::{check_edit, completion_list_no_kw};
360
361     fn check(ra_fixture: &str, expect: Expect) {
362         let actual = completion_list_no_kw(ra_fixture);
363         expect.assert_eq(&actual)
364     }
365
366     #[test]
367     fn no_completion_inside_fn() {
368         check(
369             r"
370 trait Test { fn test(); fn test2(); }
371 struct T;
372
373 impl Test for T {
374     fn test() {
375         t$0
376     }
377 }
378 ",
379             expect![[r#"
380                 sp Self
381                 st T
382                 tt Test
383                 bt u32
384             "#]],
385         );
386
387         check(
388             r"
389 trait Test { fn test(); fn test2(); }
390 struct T;
391
392 impl Test for T {
393     fn test() {
394         fn t$0
395     }
396 }
397 ",
398             expect![[""]],
399         );
400
401         check(
402             r"
403 trait Test { fn test(); fn test2(); }
404 struct T;
405
406 impl Test for T {
407     fn test() {
408         fn $0
409     }
410 }
411 ",
412             expect![[""]],
413         );
414
415         // https://github.com/rust-lang/rust-analyzer/pull/5976#issuecomment-692332191
416         check(
417             r"
418 trait Test { fn test(); fn test2(); }
419 struct T;
420
421 impl Test for T {
422     fn test() {
423         foo.$0
424     }
425 }
426 ",
427             expect![[r#""#]],
428         );
429
430         check(
431             r"
432 trait Test { fn test(_: i32); fn test2(); }
433 struct T;
434
435 impl Test for T {
436     fn test(t$0)
437 }
438 ",
439             expect![[r#"
440                 sp Self
441                 st T
442                 bn &mut self
443                 bn &self
444                 bn mut self
445                 bn self
446             "#]],
447         );
448
449         check(
450             r"
451 trait Test { fn test(_: fn()); fn test2(); }
452 struct T;
453
454 impl Test for T {
455     fn test(f: fn $0)
456 }
457 ",
458             expect![[r#"
459                 sp Self
460                 st T
461             "#]],
462         );
463     }
464
465     #[test]
466     fn no_completion_inside_const() {
467         check(
468             r"
469 trait Test { const TEST: fn(); const TEST2: u32; type Test; fn test(); }
470 struct T;
471
472 impl Test for T {
473     const TEST: fn $0
474 }
475 ",
476             expect![[r#""#]],
477         );
478
479         check(
480             r"
481 trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
482 struct T;
483
484 impl Test for T {
485     const TEST: T$0
486 }
487 ",
488             expect![[r#"
489                 sp Self
490                 st T
491                 tt Test
492                 bt u32
493             "#]],
494         );
495
496         check(
497             r"
498 trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
499 struct T;
500
501 impl Test for T {
502     const TEST: u32 = f$0
503 }
504 ",
505             expect![[r#"
506                 sp Self
507                 st T
508                 tt Test
509                 bt u32
510             "#]],
511         );
512
513         check(
514             r"
515 trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
516 struct T;
517
518 impl Test for T {
519     const TEST: u32 = {
520         t$0
521     };
522 }
523 ",
524             expect![[r#"
525                 sp Self
526                 st T
527                 tt Test
528                 bt u32
529             "#]],
530         );
531
532         check(
533             r"
534 trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
535 struct T;
536
537 impl Test for T {
538     const TEST: u32 = {
539         fn $0
540     };
541 }
542 ",
543             expect![[""]],
544         );
545
546         check(
547             r"
548 trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
549 struct T;
550
551 impl Test for T {
552     const TEST: u32 = {
553         fn t$0
554     };
555 }
556 ",
557             expect![[""]],
558         );
559     }
560
561     #[test]
562     fn no_completion_inside_type() {
563         check(
564             r"
565 trait Test { type Test; type Test2; fn test(); }
566 struct T;
567
568 impl Test for T {
569     type Test = T$0;
570 }
571 ",
572             expect![[r#"
573                 sp Self
574                 st T
575                 tt Test
576                 bt u32
577             "#]],
578         );
579
580         check(
581             r"
582 trait Test { type Test; type Test2; fn test(); }
583 struct T;
584
585 impl Test for T {
586     type Test = fn $0;
587 }
588 ",
589             expect![[r#""#]],
590         );
591     }
592
593     #[test]
594     fn name_ref_single_function() {
595         check_edit(
596             "fn test",
597             r#"
598 trait Test {
599     fn test();
600 }
601 struct T;
602
603 impl Test for T {
604     t$0
605 }
606 "#,
607             r#"
608 trait Test {
609     fn test();
610 }
611 struct T;
612
613 impl Test for T {
614     fn test() {
615     $0
616 }
617 }
618 "#,
619         );
620     }
621
622     #[test]
623     fn single_function() {
624         check_edit(
625             "fn test",
626             r#"
627 trait Test {
628     fn test();
629 }
630 struct T;
631
632 impl Test for T {
633     fn t$0
634 }
635 "#,
636             r#"
637 trait Test {
638     fn test();
639 }
640 struct T;
641
642 impl Test for T {
643     fn test() {
644     $0
645 }
646 }
647 "#,
648         );
649     }
650
651     #[test]
652     fn generic_fn() {
653         check_edit(
654             "fn foo",
655             r#"
656 trait Test {
657     fn foo<T>();
658 }
659 struct T;
660
661 impl Test for T {
662     fn f$0
663 }
664 "#,
665             r#"
666 trait Test {
667     fn foo<T>();
668 }
669 struct T;
670
671 impl Test for T {
672     fn foo<T>() {
673     $0
674 }
675 }
676 "#,
677         );
678         check_edit(
679             "fn foo",
680             r#"
681 trait Test {
682     fn foo<T>() where T: Into<String>;
683 }
684 struct T;
685
686 impl Test for T {
687     fn f$0
688 }
689 "#,
690             r#"
691 trait Test {
692     fn foo<T>() where T: Into<String>;
693 }
694 struct T;
695
696 impl Test for T {
697     fn foo<T>() where T: Into<String> {
698     $0
699 }
700 }
701 "#,
702         );
703     }
704
705     #[test]
706     fn associated_type() {
707         check_edit(
708             "type SomeType",
709             r#"
710 trait Test {
711     type SomeType;
712 }
713
714 impl Test for () {
715     type S$0
716 }
717 "#,
718             "
719 trait Test {
720     type SomeType;
721 }
722
723 impl Test for () {
724     type SomeType = $0;\n\
725 }
726 ",
727         );
728         check_edit(
729             "type SomeType",
730             r#"
731 trait Test {
732     type SomeType;
733 }
734
735 impl Test for () {
736     type$0
737 }
738 "#,
739             "
740 trait Test {
741     type SomeType;
742 }
743
744 impl Test for () {
745     type SomeType = $0;\n\
746 }
747 ",
748         );
749     }
750
751     #[test]
752     fn associated_const() {
753         check_edit(
754             "const SOME_CONST",
755             r#"
756 trait Test {
757     const SOME_CONST: u16;
758 }
759
760 impl Test for () {
761     const S$0
762 }
763 "#,
764             "
765 trait Test {
766     const SOME_CONST: u16;
767 }
768
769 impl Test for () {
770     const SOME_CONST: u16 = $0;\n\
771 }
772 ",
773         );
774
775         check_edit(
776             "const SOME_CONST",
777             r#"
778 trait Test {
779     const SOME_CONST: u16 = 92;
780 }
781
782 impl Test for () {
783     const S$0
784 }
785 "#,
786             "
787 trait Test {
788     const SOME_CONST: u16 = 92;
789 }
790
791 impl Test for () {
792     const SOME_CONST: u16 = $0;\n\
793 }
794 ",
795         );
796     }
797
798     #[test]
799     fn complete_without_name() {
800         let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| {
801             check_edit(
802                 completion,
803                 &format!(
804                     r#"
805 trait Test {{
806     type Foo;
807     const CONST: u16;
808     fn bar();
809 }}
810 struct T;
811
812 impl Test for T {{
813     {}
814     {}
815 }}
816 "#,
817                     hint, next_sibling
818                 ),
819                 &format!(
820                     r#"
821 trait Test {{
822     type Foo;
823     const CONST: u16;
824     fn bar();
825 }}
826 struct T;
827
828 impl Test for T {{
829     {}
830     {}
831 }}
832 "#,
833                     completed, next_sibling
834                 ),
835             )
836         };
837
838         // Enumerate some possible next siblings.
839         for next_sibling in &[
840             "",
841             "fn other_fn() {}", // `const $0 fn` -> `const fn`
842             "type OtherType = i32;",
843             "const OTHER_CONST: i32 = 0;",
844             "async fn other_fn() {}",
845             "unsafe fn other_fn() {}",
846             "default fn other_fn() {}",
847             "default type OtherType = i32;",
848             "default const OTHER_CONST: i32 = 0;",
849         ] {
850             test("fn bar", "fn $0", "fn bar() {\n    $0\n}", next_sibling);
851             test("type Foo", "type $0", "type Foo = $0;", next_sibling);
852             test("const CONST", "const $0", "const CONST: u16 = $0;", next_sibling);
853         }
854     }
855
856     #[test]
857     fn snippet_does_not_overwrite_comment_or_attr() {
858         let test = |completion: &str, hint: &str, completed: &str| {
859             check_edit(
860                 completion,
861                 &format!(
862                     r#"
863 trait Foo {{
864     type Type;
865     fn function();
866     const CONST: i32 = 0;
867 }}
868 struct T;
869
870 impl Foo for T {{
871     // Comment
872     #[bar]
873     {}
874 }}
875 "#,
876                     hint
877                 ),
878                 &format!(
879                     r#"
880 trait Foo {{
881     type Type;
882     fn function();
883     const CONST: i32 = 0;
884 }}
885 struct T;
886
887 impl Foo for T {{
888     // Comment
889     #[bar]
890     {}
891 }}
892 "#,
893                     completed
894                 ),
895             )
896         };
897         test("fn function", "fn f$0", "fn function() {\n    $0\n}");
898         test("type Type", "type T$0", "type Type = $0;");
899         test("const CONST", "const C$0", "const CONST: i32 = $0;");
900     }
901
902     #[test]
903     fn generics_are_inlined_in_return_type() {
904         check_edit(
905             "fn function",
906             r#"
907 trait Foo<T> {
908     fn function() -> T;
909 }
910 struct Bar;
911
912 impl Foo<u32> for Bar {
913     fn f$0
914 }
915 "#,
916             r#"
917 trait Foo<T> {
918     fn function() -> T;
919 }
920 struct Bar;
921
922 impl Foo<u32> for Bar {
923     fn function() -> u32 {
924     $0
925 }
926 }
927 "#,
928         )
929     }
930
931     #[test]
932     fn generics_are_inlined_in_parameter() {
933         check_edit(
934             "fn function",
935             r#"
936 trait Foo<T> {
937     fn function(bar: T);
938 }
939 struct Bar;
940
941 impl Foo<u32> for Bar {
942     fn f$0
943 }
944 "#,
945             r#"
946 trait Foo<T> {
947     fn function(bar: T);
948 }
949 struct Bar;
950
951 impl Foo<u32> for Bar {
952     fn function(bar: u32) {
953     $0
954 }
955 }
956 "#,
957         )
958     }
959
960     #[test]
961     fn generics_are_inlined_when_part_of_other_types() {
962         check_edit(
963             "fn function",
964             r#"
965 trait Foo<T> {
966     fn function(bar: Vec<T>);
967 }
968 struct Bar;
969
970 impl Foo<u32> for Bar {
971     fn f$0
972 }
973 "#,
974             r#"
975 trait Foo<T> {
976     fn function(bar: Vec<T>);
977 }
978 struct Bar;
979
980 impl Foo<u32> for Bar {
981     fn function(bar: Vec<u32>) {
982     $0
983 }
984 }
985 "#,
986         )
987     }
988
989     #[test]
990     fn generics_are_inlined_complex() {
991         check_edit(
992             "fn function",
993             r#"
994 trait Foo<T, U, V> {
995     fn function(bar: Vec<T>, baz: U) -> Arc<Vec<V>>;
996 }
997 struct Bar;
998
999 impl Foo<u32, Vec<usize>, u8> for Bar {
1000     fn f$0
1001 }
1002 "#,
1003             r#"
1004 trait Foo<T, U, V> {
1005     fn function(bar: Vec<T>, baz: U) -> Arc<Vec<V>>;
1006 }
1007 struct Bar;
1008
1009 impl Foo<u32, Vec<usize>, u8> for Bar {
1010     fn function(bar: Vec<u32>, baz: Vec<usize>) -> Arc<Vec<u8>> {
1011     $0
1012 }
1013 }
1014 "#,
1015         )
1016     }
1017
1018     #[test]
1019     fn generics_are_inlined_in_associated_const() {
1020         check_edit(
1021             "const BAR",
1022             r#"
1023 trait Foo<T> {
1024     const BAR: T;
1025 }
1026 struct Bar;
1027
1028 impl Foo<u32> for Bar {
1029     const B$0
1030 }
1031 "#,
1032             r#"
1033 trait Foo<T> {
1034     const BAR: T;
1035 }
1036 struct Bar;
1037
1038 impl Foo<u32> for Bar {
1039     const BAR: u32 = $0;
1040 }
1041 "#,
1042         )
1043     }
1044
1045     #[test]
1046     fn generics_are_inlined_in_where_clause() {
1047         check_edit(
1048             "fn function",
1049             r#"
1050 trait SomeTrait<T> {}
1051
1052 trait Foo<T> {
1053     fn function()
1054         where Self: SomeTrait<T>;
1055 }
1056 struct Bar;
1057
1058 impl Foo<u32> for Bar {
1059     fn f$0
1060 }
1061 "#,
1062             r#"
1063 trait SomeTrait<T> {}
1064
1065 trait Foo<T> {
1066     fn function()
1067         where Self: SomeTrait<T>;
1068 }
1069 struct Bar;
1070
1071 impl Foo<u32> for Bar {
1072     fn function()
1073         where Self: SomeTrait<u32> {
1074     $0
1075 }
1076 }
1077 "#,
1078         )
1079     }
1080
1081     #[test]
1082     fn works_directly_in_impl() {
1083         check(
1084             r#"
1085 trait Tr {
1086     fn required();
1087 }
1088
1089 impl Tr for () {
1090     $0
1091 }
1092 "#,
1093             expect![[r#"
1094             fn fn required()
1095         "#]],
1096         );
1097         check(
1098             r#"
1099 trait Tr {
1100     fn provided() {}
1101     fn required();
1102 }
1103
1104 impl Tr for () {
1105     fn provided() {}
1106     $0
1107 }
1108 "#,
1109             expect![[r#"
1110             fn fn required()
1111         "#]],
1112         );
1113     }
1114
1115     #[test]
1116     fn fixes_up_macro_generated() {
1117         check_edit(
1118             "fn foo",
1119             r#"
1120 macro_rules! noop {
1121     ($($item: item)*) => {
1122         $($item)*
1123     }
1124 }
1125
1126 noop! {
1127     trait Foo {
1128         fn foo(&mut self, bar: i64, baz: &mut u32) -> Result<(), u32>;
1129     }
1130 }
1131
1132 struct Test;
1133
1134 impl Foo for Test {
1135     $0
1136 }
1137 "#,
1138             r#"
1139 macro_rules! noop {
1140     ($($item: item)*) => {
1141         $($item)*
1142     }
1143 }
1144
1145 noop! {
1146     trait Foo {
1147         fn foo(&mut self, bar: i64, baz: &mut u32) -> Result<(), u32>;
1148     }
1149 }
1150
1151 struct Test;
1152
1153 impl Foo for Test {
1154     fn foo(&mut self,bar:i64,baz: &mut u32) -> Result<(),u32> {
1155     $0
1156 }
1157 }
1158 "#,
1159         );
1160     }
1161 }