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