ide_completion/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
34use hir::{MacroCallId, Name, db::ExpandDatabase};
35use ide_db::text_edit::TextEdit;
36use ide_db::{
37    SymbolKind, documentation::HasDocs, path_transform::PathTransform,
38    syntax_helpers::prettify_macro_expansion, traits::get_missing_assoc_items,
39};
40use syntax::ast::HasGenericParams;
41use syntax::{
42    AstNode, SmolStr, SyntaxElement, SyntaxKind, T, TextRange, ToSmolStr,
43    ast::{self, HasGenericArgs, HasTypeBounds, edit_in_place::AttrsOwnerEdit, make},
44    format_smolstr, ted,
45};
46
47use crate::{
48    CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
49    context::PathCompletionCtx,
50};
51
52#[derive(Copy, Clone, Debug, PartialEq, Eq)]
53enum ImplCompletionKind {
54    All,
55    Fn,
56    TypeAlias,
57    Const,
58}
59
60pub(crate) fn complete_trait_impl_const(
61    acc: &mut Completions,
62    ctx: &CompletionContext<'_>,
63    name: &Option<ast::Name>,
64) -> Option<()> {
65    complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::Const)
66}
67
68pub(crate) fn complete_trait_impl_type_alias(
69    acc: &mut Completions,
70    ctx: &CompletionContext<'_>,
71    name: &Option<ast::Name>,
72) -> Option<()> {
73    complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::TypeAlias)
74}
75
76pub(crate) fn complete_trait_impl_fn(
77    acc: &mut Completions,
78    ctx: &CompletionContext<'_>,
79    name: &Option<ast::Name>,
80) -> Option<()> {
81    complete_trait_impl_name(acc, ctx, name, ImplCompletionKind::Fn)
82}
83
84fn complete_trait_impl_name(
85    acc: &mut Completions,
86    ctx: &CompletionContext<'_>,
87    name: &Option<ast::Name>,
88    kind: ImplCompletionKind,
89) -> Option<()> {
90    let macro_file_item = match name {
91        Some(name) => name.syntax().parent(),
92        None => {
93            let token = &ctx.token;
94            match token.kind() {
95                SyntaxKind::WHITESPACE => token.prev_token()?,
96                _ => token.clone(),
97            }
98            .parent()
99        }
100    }?;
101    let real_file_item = ctx.sema.original_syntax_node_rooted(&macro_file_item)?;
102    // item -> ASSOC_ITEM_LIST -> IMPL
103    let impl_def = ast::Impl::cast(macro_file_item.parent()?.parent()?)?;
104    let replacement_range = {
105        // ctx.sema.original_ast_node(item)?;
106        let first_child = real_file_item
107            .children_with_tokens()
108            .find(|child| {
109                !matches!(
110                    child.kind(),
111                    SyntaxKind::COMMENT | SyntaxKind::WHITESPACE | SyntaxKind::ATTR
112                )
113            })
114            .unwrap_or_else(|| SyntaxElement::Node(real_file_item.clone()));
115
116        TextRange::new(first_child.text_range().start(), ctx.source_range().end())
117    };
118
119    complete_trait_impl(acc, ctx, kind, replacement_range, &impl_def);
120    Some(())
121}
122
123pub(crate) fn complete_trait_impl_item_by_name(
124    acc: &mut Completions,
125    ctx: &CompletionContext<'_>,
126    path_ctx: &PathCompletionCtx<'_>,
127    name_ref: &Option<ast::NameRef>,
128    impl_: &Option<ast::Impl>,
129) {
130    if !path_ctx.is_trivial_path() {
131        return;
132    }
133    if let Some(impl_) = impl_ {
134        complete_trait_impl(
135            acc,
136            ctx,
137            ImplCompletionKind::All,
138            match name_ref
139                .as_ref()
140                .and_then(|name| ctx.sema.original_syntax_node_rooted(name.syntax()))
141            {
142                Some(name) => name.text_range(),
143                None => ctx.source_range(),
144            },
145            impl_,
146        );
147    }
148}
149
150fn complete_trait_impl(
151    acc: &mut Completions,
152    ctx: &CompletionContext<'_>,
153    kind: ImplCompletionKind,
154    replacement_range: TextRange,
155    impl_def: &ast::Impl,
156) {
157    if let Some(hir_impl) = ctx.sema.to_def(impl_def) {
158        get_missing_assoc_items(&ctx.sema, impl_def)
159            .into_iter()
160            .filter(|item| ctx.check_stability_and_hidden(*item))
161            .for_each(|item| {
162                use self::ImplCompletionKind::*;
163                match (item, kind) {
164                    (hir::AssocItem::Function(func), All | Fn) => {
165                        add_function_impl(acc, ctx, replacement_range, func, hir_impl)
166                    }
167                    (hir::AssocItem::TypeAlias(type_alias), All | TypeAlias) => {
168                        add_type_alias_impl(acc, ctx, replacement_range, type_alias, hir_impl)
169                    }
170                    (hir::AssocItem::Const(const_), All | Const) => {
171                        add_const_impl(acc, ctx, replacement_range, const_, hir_impl)
172                    }
173                    _ => {}
174                }
175            });
176    }
177}
178
179fn add_function_impl(
180    acc: &mut Completions,
181    ctx: &CompletionContext<'_>,
182    replacement_range: TextRange,
183    func: hir::Function,
184    impl_def: hir::Impl,
185) {
186    let fn_name = &func.name(ctx.db);
187    let sugar: &[_] = if func.is_async(ctx.db) {
188        &[AsyncSugaring::Async, AsyncSugaring::Desugar]
189    } else if func.returns_impl_future(ctx.db) {
190        &[AsyncSugaring::Plain, AsyncSugaring::Resugar]
191    } else {
192        &[AsyncSugaring::Plain]
193    };
194    for &sugaring in sugar {
195        add_function_impl_(acc, ctx, replacement_range, func, impl_def, fn_name, sugaring);
196    }
197}
198
199fn add_function_impl_(
200    acc: &mut Completions,
201    ctx: &CompletionContext<'_>,
202    replacement_range: TextRange,
203    func: hir::Function,
204    impl_def: hir::Impl,
205    fn_name: &Name,
206    async_sugaring: AsyncSugaring,
207) {
208    let async_ = if let AsyncSugaring::Async | AsyncSugaring::Resugar = async_sugaring {
209        "async "
210    } else {
211        ""
212    };
213    let label = format_smolstr!(
214        "{}fn {}({})",
215        async_,
216        fn_name.display(ctx.db, ctx.edition),
217        if func.assoc_fn_params(ctx.db).is_empty() { "" } else { ".." }
218    );
219
220    let completion_kind = CompletionItemKind::SymbolKind(if func.has_self_param(ctx.db) {
221        SymbolKind::Method
222    } else {
223        SymbolKind::Function
224    });
225
226    let mut item = CompletionItem::new(completion_kind, replacement_range, label, ctx.edition);
227    item.lookup_by(format!("{}fn {}", async_, fn_name.display(ctx.db, ctx.edition)))
228        .set_documentation(func.docs(ctx.db))
229        .set_relevance(CompletionRelevance { exact_name_match: true, ..Default::default() });
230
231    if let Some(source) = ctx.sema.source(func)
232        && let Some(transformed_fn) =
233            get_transformed_fn(ctx, source.value, impl_def, async_sugaring)
234    {
235        let function_decl = function_declaration(ctx, &transformed_fn, source.file_id.macro_file());
236        match ctx.config.snippet_cap {
237            Some(cap) => {
238                let snippet = format!("{function_decl} {{\n    $0\n}}");
239                item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet));
240            }
241            None => {
242                let header = format!("{function_decl} {{");
243                item.text_edit(TextEdit::replace(replacement_range, header));
244            }
245        };
246        item.add_to(acc, ctx.db);
247    }
248}
249
250#[derive(Copy, Clone)]
251enum AsyncSugaring {
252    Desugar,
253    Resugar,
254    Async,
255    Plain,
256}
257
258/// Transform a relevant associated item to inline generics from the impl, remove attrs and docs, etc.
259fn get_transformed_assoc_item(
260    ctx: &CompletionContext<'_>,
261    assoc_item: ast::AssocItem,
262    impl_def: hir::Impl,
263) -> Option<ast::AssocItem> {
264    let trait_ = impl_def.trait_(ctx.db)?;
265    let source_scope = &ctx.sema.scope(assoc_item.syntax())?;
266    let target_scope = &ctx.sema.scope(ctx.sema.source(impl_def)?.syntax().value)?;
267    let transform = PathTransform::trait_impl(
268        target_scope,
269        source_scope,
270        trait_,
271        ctx.sema.source(impl_def)?.value,
272    );
273
274    let assoc_item = assoc_item.clone_for_update();
275    // FIXME: Paths in nested macros are not handled well. See
276    // `macro_generated_assoc_item2` test.
277    let assoc_item = ast::AssocItem::cast(transform.apply(assoc_item.syntax()))?;
278    assoc_item.remove_attrs_and_docs();
279    Some(assoc_item)
280}
281
282/// Transform a relevant associated item to inline generics from the impl, remove attrs and docs, etc.
283fn get_transformed_fn(
284    ctx: &CompletionContext<'_>,
285    fn_: ast::Fn,
286    impl_def: hir::Impl,
287    async_: AsyncSugaring,
288) -> Option<ast::Fn> {
289    let trait_ = impl_def.trait_(ctx.db)?;
290    let source_scope = &ctx.sema.scope(fn_.syntax())?;
291    let target_scope = &ctx.sema.scope(ctx.sema.source(impl_def)?.syntax().value)?;
292    let transform = PathTransform::trait_impl(
293        target_scope,
294        source_scope,
295        trait_,
296        ctx.sema.source(impl_def)?.value,
297    );
298
299    let fn_ = fn_.clone_for_update();
300    // FIXME: Paths in nested macros are not handled well. See
301    // `macro_generated_assoc_item2` test.
302    let fn_ = ast::Fn::cast(transform.apply(fn_.syntax()))?;
303    fn_.remove_attrs_and_docs();
304    match async_ {
305        AsyncSugaring::Desugar => {
306            match fn_.ret_type() {
307                Some(ret_ty) => {
308                    let ty = ret_ty.ty()?;
309                    ted::replace(
310                        ty.syntax(),
311                        make::ty(&format!("impl Future<Output = {ty}>"))
312                            .syntax()
313                            .clone_for_update(),
314                    );
315                }
316                None => ted::append_child(
317                    fn_.param_list()?.syntax(),
318                    make::ret_type(make::ty("impl Future<Output = ()>"))
319                        .syntax()
320                        .clone_for_update(),
321                ),
322            }
323            fn_.async_token().unwrap().detach();
324        }
325        AsyncSugaring::Resugar => {
326            let ty = fn_.ret_type()?.ty()?;
327            match &ty {
328                // best effort guessing here
329                ast::Type::ImplTraitType(t) => {
330                    let output = t.type_bound_list()?.bounds().find_map(|b| match b.ty()? {
331                        ast::Type::PathType(p) => {
332                            let p = p.path()?.segment()?;
333                            if p.name_ref()?.text() != "Future" {
334                                return None;
335                            }
336                            match p.generic_arg_list()?.generic_args().next()? {
337                                ast::GenericArg::AssocTypeArg(a)
338                                    if a.name_ref()?.text() == "Output" =>
339                                {
340                                    a.ty()
341                                }
342                                _ => None,
343                            }
344                        }
345                        _ => None,
346                    })?;
347                    if let ast::Type::TupleType(ty) = &output
348                        && ty.fields().next().is_none()
349                    {
350                        ted::remove(fn_.ret_type()?.syntax());
351                    } else {
352                        ted::replace(ty.syntax(), output.syntax());
353                    }
354                }
355                _ => (),
356            }
357            ted::prepend_child(fn_.syntax(), make::token(T![async]));
358        }
359        AsyncSugaring::Async | AsyncSugaring::Plain => (),
360    }
361    Some(fn_)
362}
363
364fn add_type_alias_impl(
365    acc: &mut Completions,
366    ctx: &CompletionContext<'_>,
367    replacement_range: TextRange,
368    type_alias: hir::TypeAlias,
369    impl_def: hir::Impl,
370) {
371    let alias_name = type_alias.name(ctx.db).as_str().to_smolstr();
372
373    let label = format_smolstr!("type {alias_name} =");
374
375    let mut item =
376        CompletionItem::new(SymbolKind::TypeAlias, replacement_range, label, ctx.edition);
377    item.lookup_by(format!("type {alias_name}"))
378        .set_documentation(type_alias.docs(ctx.db))
379        .set_relevance(CompletionRelevance { exact_name_match: true, ..Default::default() });
380
381    if let Some(source) = ctx.sema.source(type_alias) {
382        let assoc_item = ast::AssocItem::TypeAlias(source.value);
383        if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) {
384            let transformed_ty = match transformed_item {
385                ast::AssocItem::TypeAlias(ty) => ty,
386                _ => unreachable!(),
387            };
388
389            let start = transformed_ty.syntax().text_range().start();
390
391            let end = if let Some(end) =
392                transformed_ty.colon_token().map(|tok| tok.text_range().start())
393            {
394                end
395            } else if let Some(end) = transformed_ty.eq_token().map(|tok| tok.text_range().start())
396            {
397                end
398            } else if let Some(end) = transformed_ty
399                .where_clause()
400                .and_then(|wc| wc.where_token())
401                .map(|tok| tok.text_range().start())
402            {
403                end
404            } else if let Some(end) =
405                transformed_ty.semicolon_token().map(|tok| tok.text_range().start())
406            {
407                end
408            } else {
409                return;
410            };
411
412            let len = end - start;
413            let mut decl = transformed_ty.syntax().text().slice(..len).to_string();
414            decl.truncate(decl.trim_end().len());
415            decl.push_str(" = ");
416
417            let wc = transformed_ty
418                .where_clause()
419                .map(|wc| {
420                    let ws = wc
421                        .where_token()
422                        .and_then(|it| it.prev_token())
423                        .filter(|token| token.kind() == SyntaxKind::WHITESPACE)
424                        .map(|token| token.to_string())
425                        .unwrap_or_else(|| " ".into());
426                    format!("{ws}{wc}")
427                })
428                .unwrap_or_default();
429
430            match ctx.config.snippet_cap {
431                Some(cap) => {
432                    let snippet = format!("{decl}$0{wc};");
433                    item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet));
434                }
435                None => {
436                    decl.push_str(&wc);
437                    item.text_edit(TextEdit::replace(replacement_range, decl));
438                }
439            };
440            item.add_to(acc, ctx.db);
441        }
442    }
443}
444
445fn add_const_impl(
446    acc: &mut Completions,
447    ctx: &CompletionContext<'_>,
448    replacement_range: TextRange,
449    const_: hir::Const,
450    impl_def: hir::Impl,
451) {
452    let const_name = const_.name(ctx.db).map(|n| n.display_no_db(ctx.edition).to_smolstr());
453
454    if let Some(const_name) = const_name
455        && let Some(source) = ctx.sema.source(const_)
456    {
457        let assoc_item = ast::AssocItem::Const(source.value);
458        if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) {
459            let transformed_const = match transformed_item {
460                ast::AssocItem::Const(const_) => const_,
461                _ => unreachable!(),
462            };
463
464            let label =
465                make_const_compl_syntax(ctx, &transformed_const, source.file_id.macro_file());
466            let replacement = format!("{label} ");
467
468            let mut item =
469                CompletionItem::new(SymbolKind::Const, replacement_range, label, ctx.edition);
470            item.lookup_by(format_smolstr!("const {const_name}"))
471                .set_documentation(const_.docs(ctx.db))
472                .set_relevance(CompletionRelevance {
473                    exact_name_match: true,
474                    ..Default::default()
475                });
476            match ctx.config.snippet_cap {
477                Some(cap) => item.snippet_edit(
478                    cap,
479                    TextEdit::replace(replacement_range, format!("{replacement}$0;")),
480                ),
481                None => item.text_edit(TextEdit::replace(replacement_range, replacement)),
482            };
483            item.add_to(acc, ctx.db);
484        }
485    }
486}
487
488fn make_const_compl_syntax(
489    ctx: &CompletionContext<'_>,
490    const_: &ast::Const,
491    macro_file: Option<MacroCallId>,
492) -> SmolStr {
493    let const_ = if let Some(macro_file) = macro_file {
494        let span_map = ctx.db.expansion_span_map(macro_file);
495        prettify_macro_expansion(ctx.db, const_.syntax().clone(), &span_map, ctx.krate.into())
496    } else {
497        const_.syntax().clone()
498    };
499
500    let start = const_.text_range().start();
501    let const_end = const_.text_range().end();
502
503    let end = const_
504        .children_with_tokens()
505        .find(|s| s.kind() == T![;] || s.kind() == T![=])
506        .map_or(const_end, |f| f.text_range().start());
507
508    let len = end - start;
509    let range = TextRange::new(0.into(), len);
510
511    let syntax = const_.text().slice(range).to_string();
512
513    format_smolstr!("{} =", syntax.trim_end())
514}
515
516fn function_declaration(
517    ctx: &CompletionContext<'_>,
518    node: &ast::Fn,
519    macro_file: Option<MacroCallId>,
520) -> String {
521    let node = if let Some(macro_file) = macro_file {
522        let span_map = ctx.db.expansion_span_map(macro_file);
523        prettify_macro_expansion(ctx.db, node.syntax().clone(), &span_map, ctx.krate.into())
524    } else {
525        node.syntax().clone()
526    };
527
528    let start = node.text_range().start();
529    let end = node.text_range().end();
530
531    let end = node
532        .last_child_or_token()
533        .filter(|s| s.kind() == T![;] || s.kind() == SyntaxKind::BLOCK_EXPR)
534        .map_or(end, |f| f.text_range().start());
535
536    let len = end - start;
537    let syntax = node.text().slice(..len).to_string();
538
539    syntax.trim_end().to_owned()
540}
541
542#[cfg(test)]
543mod tests {
544    use expect_test::expect;
545
546    use crate::tests::{check, check_edit, check_no_kw};
547
548    #[test]
549    fn no_completion_inside_fn() {
550        check_no_kw(
551            r"
552trait Test { fn test(); fn test2(); }
553struct T;
554
555impl Test for T {
556    fn test() {
557        t$0
558    }
559}
560",
561            expect![[r#"
562                sp Self  T
563                st T     T
564                tt Test
565                bt u32 u32
566            "#]],
567        );
568
569        check_no_kw(
570            r"
571trait Test { fn test(); fn test2(); }
572struct T;
573
574impl Test for T {
575    fn test() {
576        fn t$0
577    }
578}
579",
580            expect![[""]],
581        );
582
583        check_no_kw(
584            r"
585trait Test { fn test(); fn test2(); }
586struct T;
587
588impl Test for T {
589    fn test() {
590        fn $0
591    }
592}
593",
594            expect![[""]],
595        );
596
597        // https://github.com/rust-lang/rust-analyzer/pull/5976#issuecomment-692332191
598        check_no_kw(
599            r"
600trait Test { fn test(); fn test2(); }
601struct T;
602
603impl Test for T {
604    fn test() {
605        foo.$0
606    }
607}
608",
609            expect![[r#""#]],
610        );
611
612        check_no_kw(
613            r"
614trait Test { fn test(_: i32); fn test2(); }
615struct T;
616
617impl Test for T {
618    fn test(t$0)
619}
620",
621            expect![[r#"
622                sp Self
623                st T
624                bn &mut self
625                bn &self
626                bn mut self
627                bn self
628            "#]],
629        );
630
631        check_no_kw(
632            r"
633trait Test { fn test(_: fn()); fn test2(); }
634struct T;
635
636impl Test for T {
637    fn test(f: fn $0)
638}
639",
640            expect![[r#"
641                sp Self
642                st T
643            "#]],
644        );
645    }
646
647    #[test]
648    fn no_completion_inside_const() {
649        check_no_kw(
650            r"
651trait Test { const TEST: fn(); const TEST2: u32; type Test; fn test(); }
652struct T;
653
654impl Test for T {
655    const TEST: fn $0
656}
657",
658            expect![[r#""#]],
659        );
660
661        check_no_kw(
662            r"
663trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
664struct T;
665
666impl Test for T {
667    const TEST: T$0
668}
669",
670            expect![[r#"
671                sp Self  T
672                st T     T
673                tt Test
674                bt u32 u32
675            "#]],
676        );
677
678        check_no_kw(
679            r"
680trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
681struct T;
682
683impl Test for T {
684    const TEST: u32 = f$0
685}
686",
687            expect![[r#"
688                sp Self  T
689                st T     T
690                tt Test
691                bt u32 u32
692            "#]],
693        );
694
695        check_no_kw(
696            r"
697trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
698struct T;
699
700impl Test for T {
701    const TEST: u32 = {
702        t$0
703    };
704}
705",
706            expect![[r#"
707                sp Self  T
708                st T     T
709                tt Test
710                bt u32 u32
711            "#]],
712        );
713
714        check_no_kw(
715            r"
716trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
717struct T;
718
719impl Test for T {
720    const TEST: u32 = {
721        fn $0
722    };
723}
724",
725            expect![[""]],
726        );
727
728        check_no_kw(
729            r"
730trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
731struct T;
732
733impl Test for T {
734    const TEST: u32 = {
735        fn t$0
736    };
737}
738",
739            expect![[""]],
740        );
741    }
742
743    #[test]
744    fn no_completion_inside_type() {
745        check_no_kw(
746            r"
747trait Test { type Test; type Test2; fn test(); }
748struct T;
749
750impl Test for T {
751    type Test = T$0;
752}
753",
754            expect![[r#"
755                sp Self  T
756                st T     T
757                tt Test
758                bt u32 u32
759            "#]],
760        );
761
762        check_no_kw(
763            r"
764trait Test { type Test; type Test2; fn test(); }
765struct T;
766
767impl Test for T {
768    type Test = fn $0;
769}
770",
771            expect![[r#""#]],
772        );
773    }
774
775    #[test]
776    fn name_ref_single_function() {
777        check_edit(
778            "fn test",
779            r#"
780trait Test {
781    fn test();
782}
783struct T;
784
785impl Test for T {
786    t$0
787}
788"#,
789            r#"
790trait Test {
791    fn test();
792}
793struct T;
794
795impl Test for T {
796    fn test() {
797    $0
798}
799}
800"#,
801        );
802    }
803
804    #[test]
805    fn single_function() {
806        check_edit(
807            "fn test",
808            r#"
809trait Test {
810    fn test();
811}
812struct T;
813
814impl Test for T {
815    fn t$0
816}
817"#,
818            r#"
819trait Test {
820    fn test();
821}
822struct T;
823
824impl Test for T {
825    fn test() {
826    $0
827}
828}
829"#,
830        );
831    }
832
833    #[test]
834    fn generic_fn() {
835        check_edit(
836            "fn foo",
837            r#"
838trait Test {
839    fn foo<T>();
840}
841struct T;
842
843impl Test for T {
844    fn f$0
845}
846"#,
847            r#"
848trait Test {
849    fn foo<T>();
850}
851struct T;
852
853impl Test for T {
854    fn foo<T>() {
855    $0
856}
857}
858"#,
859        );
860        check_edit(
861            "fn foo",
862            r#"
863trait Test {
864    fn foo<T>() where T: Into<String>;
865}
866struct T;
867
868impl Test for T {
869    fn f$0
870}
871"#,
872            r#"
873trait Test {
874    fn foo<T>() where T: Into<String>;
875}
876struct T;
877
878impl Test for T {
879    fn foo<T>() where T: Into<String> {
880    $0
881}
882}
883"#,
884        );
885    }
886
887    #[test]
888    fn associated_type() {
889        check_edit(
890            "type SomeType",
891            r#"
892trait Test {
893    type SomeType;
894}
895
896impl Test for () {
897    type S$0
898}
899"#,
900            "
901trait Test {
902    type SomeType;
903}
904
905impl Test for () {
906    type SomeType = $0;\n\
907}
908",
909        );
910        check_edit(
911            "type SomeType",
912            r#"
913trait Test {
914    type SomeType;
915}
916
917impl Test for () {
918    type$0
919}
920"#,
921            "
922trait Test {
923    type SomeType;
924}
925
926impl Test for () {
927    type SomeType = $0;\n\
928}
929",
930        );
931    }
932
933    #[test]
934    fn associated_const() {
935        check_edit(
936            "const SOME_CONST",
937            r#"
938trait Test {
939    const SOME_CONST: u16;
940}
941
942impl Test for () {
943    const S$0
944}
945"#,
946            "
947trait Test {
948    const SOME_CONST: u16;
949}
950
951impl Test for () {
952    const SOME_CONST: u16 = $0;\n\
953}
954",
955        );
956
957        check_edit(
958            "const SOME_CONST",
959            r#"
960trait Test {
961    const SOME_CONST: u16 = 92;
962}
963
964impl Test for () {
965    const S$0
966}
967"#,
968            "
969trait Test {
970    const SOME_CONST: u16 = 92;
971}
972
973impl Test for () {
974    const SOME_CONST: u16 = $0;\n\
975}
976",
977        );
978    }
979
980    #[test]
981    fn fn_with_lifetimes() {
982        check_edit(
983            "fn foo",
984            r#"
985trait Test<'a, 'b, T> {
986    fn foo(&self, a: &'a T, b: &'b T) -> &'a T;
987}
988
989impl<'x, 'y, A> Test<'x, 'y, A> for () {
990    t$0
991}
992"#,
993            r#"
994trait Test<'a, 'b, T> {
995    fn foo(&self, a: &'a T, b: &'b T) -> &'a T;
996}
997
998impl<'x, 'y, A> Test<'x, 'y, A> for () {
999    fn foo(&self, a: &'x A, b: &'y A) -> &'x A {
1000    $0
1001}
1002}
1003"#,
1004        );
1005    }
1006
1007    #[test]
1008    fn complete_without_name() {
1009        let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| {
1010            check_edit(
1011                completion,
1012                &format!(
1013                    r#"
1014trait Test {{
1015    type Foo;
1016    const CONST: u16;
1017    fn bar();
1018}}
1019struct T;
1020
1021impl Test for T {{
1022    {hint}
1023    {next_sibling}
1024}}
1025"#
1026                ),
1027                &format!(
1028                    r#"
1029trait Test {{
1030    type Foo;
1031    const CONST: u16;
1032    fn bar();
1033}}
1034struct T;
1035
1036impl Test for T {{
1037    {completed}
1038    {next_sibling}
1039}}
1040"#
1041                ),
1042            )
1043        };
1044
1045        // Enumerate some possible next siblings.
1046        for next_sibling in [
1047            "",
1048            "fn other_fn() {}", // `const $0 fn` -> `const fn`
1049            "type OtherType = i32;",
1050            "const OTHER_CONST: i32 = 0;",
1051            "async fn other_fn() {}",
1052            "unsafe fn other_fn() {}",
1053            "default fn other_fn() {}",
1054            "default type OtherType = i32;",
1055            "default const OTHER_CONST: i32 = 0;",
1056        ] {
1057            test("fn bar", "fn $0", "fn bar() {\n    $0\n}", next_sibling);
1058            test("type Foo", "type $0", "type Foo = $0;", next_sibling);
1059            test("const CONST", "const $0", "const CONST: u16 = $0;", next_sibling);
1060        }
1061    }
1062
1063    #[test]
1064    fn snippet_does_not_overwrite_comment_or_attr() {
1065        let test = |completion: &str, hint: &str, completed: &str| {
1066            check_edit(
1067                completion,
1068                &format!(
1069                    r#"
1070trait Foo {{
1071    type Type;
1072    fn function();
1073    const CONST: i32 = 0;
1074}}
1075struct T;
1076
1077impl Foo for T {{
1078    // Comment
1079    #[bar]
1080    {hint}
1081}}
1082"#
1083                ),
1084                &format!(
1085                    r#"
1086trait Foo {{
1087    type Type;
1088    fn function();
1089    const CONST: i32 = 0;
1090}}
1091struct T;
1092
1093impl Foo for T {{
1094    // Comment
1095    #[bar]
1096    {completed}
1097}}
1098"#
1099                ),
1100            )
1101        };
1102        test("fn function", "fn f$0", "fn function() {\n    $0\n}");
1103        test("type Type", "type T$0", "type Type = $0;");
1104        test("const CONST", "const C$0", "const CONST: i32 = $0;");
1105    }
1106
1107    #[test]
1108    fn generics_are_inlined_in_return_type() {
1109        check_edit(
1110            "fn function",
1111            r#"
1112trait Foo<T> {
1113    fn function() -> T;
1114}
1115struct Bar;
1116
1117impl Foo<u32> for Bar {
1118    fn f$0
1119}
1120"#,
1121            r#"
1122trait Foo<T> {
1123    fn function() -> T;
1124}
1125struct Bar;
1126
1127impl Foo<u32> for Bar {
1128    fn function() -> u32 {
1129    $0
1130}
1131}
1132"#,
1133        )
1134    }
1135
1136    #[test]
1137    fn generics_are_inlined_in_parameter() {
1138        check_edit(
1139            "fn function",
1140            r#"
1141trait Foo<T> {
1142    fn function(bar: T);
1143}
1144struct Bar;
1145
1146impl Foo<u32> for Bar {
1147    fn f$0
1148}
1149"#,
1150            r#"
1151trait Foo<T> {
1152    fn function(bar: T);
1153}
1154struct Bar;
1155
1156impl Foo<u32> for Bar {
1157    fn function(bar: u32) {
1158    $0
1159}
1160}
1161"#,
1162        )
1163    }
1164
1165    #[test]
1166    fn generics_are_inlined_when_part_of_other_types() {
1167        check_edit(
1168            "fn function",
1169            r#"
1170trait Foo<T> {
1171    fn function(bar: Vec<T>);
1172}
1173struct Bar;
1174
1175impl Foo<u32> for Bar {
1176    fn f$0
1177}
1178"#,
1179            r#"
1180trait Foo<T> {
1181    fn function(bar: Vec<T>);
1182}
1183struct Bar;
1184
1185impl Foo<u32> for Bar {
1186    fn function(bar: Vec<u32>) {
1187    $0
1188}
1189}
1190"#,
1191        )
1192    }
1193
1194    #[test]
1195    fn generics_are_inlined_complex() {
1196        check_edit(
1197            "fn function",
1198            r#"
1199trait Foo<T, U, V> {
1200    fn function(bar: Vec<T>, baz: U) -> Arc<Vec<V>>;
1201}
1202struct Bar;
1203
1204impl Foo<u32, Vec<usize>, u8> for Bar {
1205    fn f$0
1206}
1207"#,
1208            r#"
1209trait Foo<T, U, V> {
1210    fn function(bar: Vec<T>, baz: U) -> Arc<Vec<V>>;
1211}
1212struct Bar;
1213
1214impl Foo<u32, Vec<usize>, u8> for Bar {
1215    fn function(bar: Vec<u32>, baz: Vec<usize>) -> Arc<Vec<u8>> {
1216    $0
1217}
1218}
1219"#,
1220        )
1221    }
1222
1223    #[test]
1224    fn generics_are_inlined_in_associated_const() {
1225        check_edit(
1226            "const BAR",
1227            r#"
1228trait Foo<T> {
1229    const BAR: T;
1230}
1231struct Bar;
1232
1233impl Foo<u32> for Bar {
1234    const B$0
1235}
1236"#,
1237            r#"
1238trait Foo<T> {
1239    const BAR: T;
1240}
1241struct Bar;
1242
1243impl Foo<u32> for Bar {
1244    const BAR: u32 = $0;
1245}
1246"#,
1247        )
1248    }
1249
1250    #[test]
1251    fn generics_are_inlined_in_where_clause() {
1252        check_edit(
1253            "fn function",
1254            r#"
1255trait SomeTrait<T> {}
1256
1257trait Foo<T> {
1258    fn function()
1259        where Self: SomeTrait<T>;
1260}
1261struct Bar;
1262
1263impl Foo<u32> for Bar {
1264    fn f$0
1265}
1266"#,
1267            r#"
1268trait SomeTrait<T> {}
1269
1270trait Foo<T> {
1271    fn function()
1272        where Self: SomeTrait<T>;
1273}
1274struct Bar;
1275
1276impl Foo<u32> for Bar {
1277    fn function()
1278        where Self: SomeTrait<u32> {
1279    $0
1280}
1281}
1282"#,
1283        )
1284    }
1285
1286    #[test]
1287    fn works_directly_in_impl() {
1288        check_no_kw(
1289            r#"
1290trait Tr {
1291    fn required();
1292}
1293
1294impl Tr for () {
1295    $0
1296}
1297"#,
1298            expect![[r#"
1299            fn fn required()
1300        "#]],
1301        );
1302        check_no_kw(
1303            r#"
1304trait Tr {
1305    fn provided() {}
1306    fn required();
1307}
1308
1309impl Tr for () {
1310    fn provided() {}
1311    $0
1312}
1313"#,
1314            expect![[r#"
1315            fn fn required()
1316        "#]],
1317        );
1318    }
1319
1320    #[test]
1321    fn fixes_up_macro_generated() {
1322        check_edit(
1323            "fn foo",
1324            r#"
1325macro_rules! noop {
1326    ($($item: item)*) => {
1327        $($item)*
1328    }
1329}
1330
1331noop! {
1332    trait Foo {
1333        fn foo(&mut self, bar: i64, baz: &mut u32) -> Result<(), u32>;
1334    }
1335}
1336
1337struct Test;
1338
1339impl Foo for Test {
1340    $0
1341}
1342"#,
1343            r#"
1344macro_rules! noop {
1345    ($($item: item)*) => {
1346        $($item)*
1347    }
1348}
1349
1350noop! {
1351    trait Foo {
1352        fn foo(&mut self, bar: i64, baz: &mut u32) -> Result<(), u32>;
1353    }
1354}
1355
1356struct Test;
1357
1358impl Foo for Test {
1359    fn foo(&mut self,bar:i64,baz: &mut u32) -> Result<(),u32> {
1360    $0
1361}
1362}
1363"#,
1364        );
1365    }
1366
1367    #[test]
1368    fn macro_generated_assoc_item() {
1369        check_edit(
1370            "fn method",
1371            r#"
1372macro_rules! ty { () => { i32 } }
1373trait SomeTrait { type Output; }
1374impl SomeTrait for i32 { type Output = i64; }
1375macro_rules! define_method {
1376    () => {
1377        fn method(&mut self, params: <ty!() as SomeTrait>::Output);
1378    };
1379}
1380trait AnotherTrait { define_method!(); }
1381impl AnotherTrait for () {
1382    $0
1383}
1384"#,
1385            r#"
1386macro_rules! ty { () => { i32 } }
1387trait SomeTrait { type Output; }
1388impl SomeTrait for i32 { type Output = i64; }
1389macro_rules! define_method {
1390    () => {
1391        fn method(&mut self, params: <ty!() as SomeTrait>::Output);
1392    };
1393}
1394trait AnotherTrait { define_method!(); }
1395impl AnotherTrait for () {
1396    fn method(&mut self,params: <ty!()as SomeTrait>::Output) {
1397    $0
1398}
1399}
1400"#,
1401        );
1402    }
1403
1404    // FIXME: `T` in `ty!(T)` should be replaced by `PathTransform`.
1405    #[test]
1406    fn macro_generated_assoc_item2() {
1407        check_edit(
1408            "fn method",
1409            r#"
1410macro_rules! ty { ($me:ty) => { $me } }
1411trait SomeTrait { type Output; }
1412impl SomeTrait for i32 { type Output = i64; }
1413macro_rules! define_method {
1414    ($t:ty) => {
1415        fn method(&mut self, params: <ty!($t) as SomeTrait>::Output);
1416    };
1417}
1418trait AnotherTrait<T: SomeTrait> { define_method!(T); }
1419impl AnotherTrait<i32> for () {
1420    $0
1421}
1422"#,
1423            r#"
1424macro_rules! ty { ($me:ty) => { $me } }
1425trait SomeTrait { type Output; }
1426impl SomeTrait for i32 { type Output = i64; }
1427macro_rules! define_method {
1428    ($t:ty) => {
1429        fn method(&mut self, params: <ty!($t) as SomeTrait>::Output);
1430    };
1431}
1432trait AnotherTrait<T: SomeTrait> { define_method!(T); }
1433impl AnotherTrait<i32> for () {
1434    fn method(&mut self,params: <ty!(T)as SomeTrait>::Output) {
1435    $0
1436}
1437}
1438"#,
1439        );
1440    }
1441
1442    #[test]
1443    fn includes_gat_generics() {
1444        check_edit(
1445            "type Ty",
1446            r#"
1447trait Tr<'b> {
1448    type Ty<'a: 'b, T: Copy, const C: usize>;
1449}
1450
1451impl<'b> Tr<'b> for () {
1452    $0
1453}
1454"#,
1455            r#"
1456trait Tr<'b> {
1457    type Ty<'a: 'b, T: Copy, const C: usize>;
1458}
1459
1460impl<'b> Tr<'b> for () {
1461    type Ty<'a: 'b, T: Copy, const C: usize> = $0;
1462}
1463"#,
1464        );
1465    }
1466    #[test]
1467    fn includes_where_clause() {
1468        check_edit(
1469            "type Ty",
1470            r#"
1471trait Tr {
1472    type Ty where Self: Copy;
1473}
1474
1475impl Tr for () {
1476    $0
1477}
1478"#,
1479            r#"
1480trait Tr {
1481    type Ty where Self: Copy;
1482}
1483
1484impl Tr for () {
1485    type Ty = $0 where Self: Copy;
1486}
1487"#,
1488        );
1489    }
1490
1491    #[test]
1492    fn strips_comments() {
1493        check_edit(
1494            "fn func",
1495            r#"
1496trait Tr {
1497    /// docs
1498    #[attr]
1499    fn func();
1500}
1501impl Tr for () {
1502    $0
1503}
1504"#,
1505            r#"
1506trait Tr {
1507    /// docs
1508    #[attr]
1509    fn func();
1510}
1511impl Tr for () {
1512    fn func() {
1513    $0
1514}
1515}
1516"#,
1517        );
1518        check_edit(
1519            "const C",
1520            r#"
1521trait Tr {
1522    /// docs
1523    #[attr]
1524    const C: usize;
1525}
1526impl Tr for () {
1527    $0
1528}
1529"#,
1530            r#"
1531trait Tr {
1532    /// docs
1533    #[attr]
1534    const C: usize;
1535}
1536impl Tr for () {
1537    const C: usize = $0;
1538}
1539"#,
1540        );
1541        check_edit(
1542            "type Item",
1543            r#"
1544trait Tr {
1545    /// docs
1546    #[attr]
1547    type Item;
1548}
1549impl Tr for () {
1550    $0
1551}
1552"#,
1553            r#"
1554trait Tr {
1555    /// docs
1556    #[attr]
1557    type Item;
1558}
1559impl Tr for () {
1560    type Item = $0;
1561}
1562"#,
1563        );
1564    }
1565
1566    #[test]
1567    fn impl_fut() {
1568        check_edit(
1569            "fn foo",
1570            r#"
1571//- minicore: future, send, sized
1572use core::future::Future;
1573
1574trait DesugaredAsyncTrait {
1575    fn foo(&self) -> impl Future<Output = usize> + Send;
1576}
1577
1578impl DesugaredAsyncTrait for () {
1579    $0
1580}
1581"#,
1582            r#"
1583use core::future::Future;
1584
1585trait DesugaredAsyncTrait {
1586    fn foo(&self) -> impl Future<Output = usize> + Send;
1587}
1588
1589impl DesugaredAsyncTrait for () {
1590    fn foo(&self) -> impl Future<Output = usize> + Send {
1591    $0
1592}
1593}
1594"#,
1595        );
1596    }
1597
1598    #[test]
1599    fn impl_fut_resugared() {
1600        check_edit(
1601            "async fn foo",
1602            r#"
1603//- minicore: future, send, sized
1604use core::future::Future;
1605
1606trait DesugaredAsyncTrait {
1607    fn foo(&self) -> impl Future<Output = usize> + Send;
1608}
1609
1610impl DesugaredAsyncTrait for () {
1611    $0
1612}
1613"#,
1614            r#"
1615use core::future::Future;
1616
1617trait DesugaredAsyncTrait {
1618    fn foo(&self) -> impl Future<Output = usize> + Send;
1619}
1620
1621impl DesugaredAsyncTrait for () {
1622    async fn foo(&self) -> usize {
1623    $0
1624}
1625}
1626"#,
1627        );
1628
1629        check_edit(
1630            "async fn foo",
1631            r#"
1632//- minicore: future, send, sized
1633use core::future::Future;
1634
1635trait DesugaredAsyncTrait {
1636    fn foo(&self) -> impl Future<Output = ()> + Send;
1637}
1638
1639impl DesugaredAsyncTrait for () {
1640    $0
1641}
1642"#,
1643            r#"
1644use core::future::Future;
1645
1646trait DesugaredAsyncTrait {
1647    fn foo(&self) -> impl Future<Output = ()> + Send;
1648}
1649
1650impl DesugaredAsyncTrait for () {
1651    async fn foo(&self) {
1652    $0
1653}
1654}
1655"#,
1656        );
1657    }
1658
1659    #[test]
1660    fn async_desugared() {
1661        check_edit(
1662            "fn foo",
1663            r#"
1664//- minicore: future, send, sized
1665use core::future::Future;
1666
1667trait DesugaredAsyncTrait {
1668    async fn foo(&self) -> usize;
1669}
1670
1671impl DesugaredAsyncTrait for () {
1672    $0
1673}
1674"#,
1675            r#"
1676use core::future::Future;
1677
1678trait DesugaredAsyncTrait {
1679    async fn foo(&self) -> usize;
1680}
1681
1682impl DesugaredAsyncTrait for () {
1683     fn foo(&self) -> impl Future<Output = usize> {
1684    $0
1685}
1686}
1687"#,
1688        );
1689    }
1690
1691    #[test]
1692    fn async_() {
1693        check_edit(
1694            "async fn foo",
1695            r#"
1696//- minicore: future, send, sized
1697use core::future::Future;
1698
1699trait DesugaredAsyncTrait {
1700    async fn foo(&self) -> usize;
1701}
1702
1703impl DesugaredAsyncTrait for () {
1704    $0
1705}
1706"#,
1707            r#"
1708use core::future::Future;
1709
1710trait DesugaredAsyncTrait {
1711    async fn foo(&self) -> usize;
1712}
1713
1714impl DesugaredAsyncTrait for () {
1715    async fn foo(&self) -> usize {
1716    $0
1717}
1718}
1719"#,
1720        );
1721    }
1722
1723    #[test]
1724    fn within_attr_macro() {
1725        check(
1726            r#"
1727//- proc_macros: identity
1728trait Trait {
1729    fn foo(&self) {}
1730    fn bar(&self) {}
1731    fn baz(&self) {}
1732}
1733
1734#[proc_macros::identity]
1735impl Trait for () {
1736    f$0
1737}
1738                "#,
1739            expect![[r#"
1740                me fn bar(..)
1741                me fn baz(..)
1742                me fn foo(..)
1743                md proc_macros
1744                kw crate::
1745                kw self::
1746            "#]],
1747        );
1748        check(
1749            r#"
1750//- proc_macros: identity
1751trait Trait {
1752    fn foo(&self) {}
1753    fn bar(&self) {}
1754    fn baz(&self) {}
1755}
1756
1757#[proc_macros::identity]
1758impl Trait for () {
1759    fn $0
1760}
1761        "#,
1762            expect![[r#"
1763                me fn bar(..)
1764                me fn baz(..)
1765                me fn foo(..)
1766            "#]],
1767        );
1768    }
1769}