Skip to main content

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