Skip to main content

ide_completion/
completions.rs

1//! This module defines an accumulator for completions which are going to be presented to user.
2
3pub(crate) mod attribute;
4pub(crate) mod dot;
5pub(crate) mod env_vars;
6pub(crate) mod expr;
7pub(crate) mod extern_abi;
8pub(crate) mod extern_crate;
9pub(crate) mod field;
10pub(crate) mod flyimport;
11pub(crate) mod fn_param;
12pub(crate) mod format_string;
13pub(crate) mod item_list;
14pub(crate) mod keyword;
15pub(crate) mod lifetime;
16pub(crate) mod macro_def;
17pub(crate) mod mod_;
18pub(crate) mod pattern;
19pub(crate) mod postfix;
20pub(crate) mod ra_fixture;
21pub(crate) mod record;
22pub(crate) mod snippet;
23pub(crate) mod r#type;
24pub(crate) mod use_;
25pub(crate) mod vis;
26
27use std::iter;
28
29use hir::{EnumVariant, HasAttrs, Name, ScopeDef, sym};
30use ide_db::{RootDatabase, SymbolKind, imports::import_assets::LocatedImport};
31use syntax::{SmolStr, ToSmolStr, ast};
32
33use crate::{
34    CompletionContext, CompletionItem, CompletionItemKind,
35    context::{
36        DotAccess, ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind,
37        PathCompletionCtx, PathKind, PatternContext, Qualified, TypeAscriptionTarget, TypeLocation,
38        Visible,
39    },
40    item::Builder,
41    render::{
42        RenderContext,
43        const_::render_const,
44        function::{render_fn, render_method},
45        literal::{render_struct_literal, render_variant_lit},
46        macro_::render_macro,
47        pattern::{render_struct_pat, render_variant_pat},
48        render_expr, render_field, render_path_resolution, render_pattern_resolution,
49        render_tuple_field, render_type_keyword_snippet,
50        type_alias::{render_type_alias, render_type_alias_with_eq},
51        union_literal::render_union_literal,
52    },
53};
54
55/// Represents an in-progress set of completions being built.
56#[derive(Debug, Default)]
57pub struct Completions {
58    buf: Vec<CompletionItem>,
59}
60
61impl From<Completions> for Vec<CompletionItem> {
62    fn from(val: Completions) -> Self {
63        val.buf
64    }
65}
66
67impl Builder {
68    /// Convenience method, which allows to add a freshly created completion into accumulator
69    /// without binding it to the variable.
70    pub(crate) fn add_to(self, acc: &mut Completions, db: &RootDatabase) {
71        acc.add(self.build(db))
72    }
73}
74
75impl Completions {
76    fn add(&mut self, item: CompletionItem) {
77        self.buf.push(item)
78    }
79
80    fn add_many(&mut self, items: impl IntoIterator<Item = CompletionItem>) {
81        self.buf.extend(items)
82    }
83
84    fn add_opt(&mut self, item: Option<CompletionItem>) {
85        if let Some(item) = item {
86            self.buf.push(item)
87        }
88    }
89
90    pub(crate) fn add_keyword(&mut self, ctx: &CompletionContext<'_, '_>, keyword: &'static str) {
91        let item = CompletionItem::new(
92            CompletionItemKind::Keyword,
93            ctx.source_range(),
94            SmolStr::new_static(keyword),
95            ctx.edition,
96        );
97        item.add_to(self, ctx.db);
98    }
99
100    pub(crate) fn add_nameref_keywords_with_colon(&mut self, ctx: &CompletionContext<'_, '_>) {
101        ["self::", "crate::"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
102
103        if ctx.depth_from_crate_root > 0 {
104            self.add_keyword(ctx, "super::");
105        }
106    }
107
108    pub(crate) fn add_nameref_keywords_with_type_like(
109        &mut self,
110        ctx: &CompletionContext<'_, '_>,
111        path_ctx: &PathCompletionCtx<'_>,
112    ) {
113        let mut add_keyword = |kw| {
114            render_type_keyword_snippet(ctx, path_ctx, kw, kw).add_to(self, ctx.db);
115        };
116        ["self::", "crate::"].into_iter().for_each(&mut add_keyword);
117
118        if ctx.depth_from_crate_root > 0 {
119            add_keyword("super::");
120        }
121    }
122
123    pub(crate) fn add_nameref_keywords(&mut self, ctx: &CompletionContext<'_, '_>) {
124        ["self", "crate"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
125
126        if ctx.depth_from_crate_root > 0 {
127            self.add_keyword(ctx, "super");
128        }
129    }
130
131    pub(crate) fn add_type_keywords(
132        &mut self,
133        ctx: &CompletionContext<'_, '_>,
134        path_ctx: &PathCompletionCtx<'_>,
135    ) {
136        let mut add_keyword = |kw, snippet| {
137            render_type_keyword_snippet(ctx, path_ctx, kw, snippet).add_to(self, ctx.db);
138        };
139
140        add_keyword("fn", "fn($1)");
141        add_keyword("dyn", "dyn $0");
142        add_keyword("impl", "impl $0");
143        add_keyword("for", "for<$1>");
144    }
145
146    pub(crate) fn add_super_keyword(
147        &mut self,
148        ctx: &CompletionContext<'_, '_>,
149        super_chain_len: Option<usize>,
150    ) {
151        if let Some(len) = super_chain_len
152            && len > 0
153            && len < ctx.depth_from_crate_root
154        {
155            self.add_keyword(ctx, "super::");
156        }
157    }
158
159    pub(crate) fn add_keyword_snippet_expr(
160        &mut self,
161        ctx: &CompletionContext<'_, '_>,
162        incomplete_let: bool,
163        kw: &str,
164        snippet: &str,
165    ) {
166        let mut item =
167            CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw, ctx.edition);
168
169        match ctx.config.snippet_cap {
170            Some(cap) => {
171                if incomplete_let && snippet.ends_with('}') {
172                    // complete block expression snippets with a trailing semicolon, if inside an incomplete let
173                    cov_mark::hit!(let_semi);
174                    item.insert_snippet(cap, format!("{snippet};"));
175                } else {
176                    item.insert_snippet(cap, snippet);
177                }
178            }
179            None => {
180                item.insert_text(if snippet.contains('$') { kw } else { snippet });
181            }
182        };
183        item.add_to(self, ctx.db);
184    }
185
186    pub(crate) fn add_keyword_snippet(
187        &mut self,
188        ctx: &CompletionContext<'_, '_>,
189        kw: &str,
190        snippet: &str,
191    ) {
192        let mut item =
193            CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw, ctx.edition);
194
195        match ctx.config.snippet_cap {
196            Some(cap) => item.insert_snippet(cap, snippet),
197            None => item.insert_text(if snippet.contains('$') { kw } else { snippet }),
198        };
199        item.add_to(self, ctx.db);
200    }
201
202    pub(crate) fn add_expr(
203        &mut self,
204        ctx: &CompletionContext<'_, '_>,
205        expr: &hir::term_search::Expr<'_>,
206    ) {
207        if let Some(item) = render_expr(ctx, expr) {
208            item.add_to(self, ctx.db)
209        }
210    }
211
212    pub(crate) fn add_crate_roots(
213        &mut self,
214        ctx: &CompletionContext<'_, '_>,
215        path_ctx: &PathCompletionCtx<'_>,
216    ) {
217        ctx.process_all_names(&mut |name, res, doc_aliases| match res {
218            ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root(ctx.db) => {
219                self.add_module(ctx, path_ctx, m, name, doc_aliases);
220            }
221            _ => (),
222        });
223    }
224
225    pub(crate) fn add_path_resolution(
226        &mut self,
227        ctx: &CompletionContext<'_, '_>,
228        path_ctx: &PathCompletionCtx<'_>,
229        local_name: hir::Name,
230        resolution: hir::ScopeDef,
231        doc_aliases: Vec<syntax::SmolStr>,
232    ) {
233        let is_private_editable = match ctx.def_is_visible(&resolution) {
234            Visible::Yes => false,
235            Visible::Editable => true,
236            Visible::No => return,
237        };
238        render_path_resolution(
239            RenderContext::new(ctx).private_editable(is_private_editable).doc_aliases(doc_aliases),
240            path_ctx,
241            local_name,
242            resolution,
243        )
244        .add_to(self, ctx.db);
245    }
246
247    pub(crate) fn add_pattern_resolution(
248        &mut self,
249        ctx: &CompletionContext<'_, '_>,
250        pattern_ctx: &PatternContext,
251        local_name: hir::Name,
252        resolution: hir::ScopeDef,
253    ) {
254        let is_private_editable = match ctx.def_is_visible(&resolution) {
255            Visible::Yes => false,
256            Visible::Editable => true,
257            Visible::No => return,
258        };
259        render_pattern_resolution(
260            RenderContext::new(ctx).private_editable(is_private_editable),
261            pattern_ctx,
262            local_name,
263            resolution,
264        )
265        .add_to(self, ctx.db);
266    }
267
268    pub(crate) fn add_enum_variants(
269        &mut self,
270        ctx: &CompletionContext<'_, '_>,
271        path_ctx: &PathCompletionCtx<'_>,
272        e: hir::Enum,
273    ) {
274        e.variants(ctx.db)
275            .into_iter()
276            .for_each(|variant| self.add_enum_variant(ctx, path_ctx, variant, None));
277    }
278
279    pub(crate) fn add_module(
280        &mut self,
281        ctx: &CompletionContext<'_, '_>,
282        path_ctx: &PathCompletionCtx<'_>,
283        module: hir::Module,
284        local_name: hir::Name,
285        doc_aliases: Vec<syntax::SmolStr>,
286    ) {
287        self.add_path_resolution(
288            ctx,
289            path_ctx,
290            local_name,
291            hir::ScopeDef::ModuleDef(module.into()),
292            doc_aliases,
293        );
294    }
295
296    pub(crate) fn add_macro(
297        &mut self,
298        ctx: &CompletionContext<'_, '_>,
299        path_ctx: &PathCompletionCtx<'_>,
300        mac: hir::Macro,
301        local_name: hir::Name,
302    ) {
303        let is_private_editable = match ctx.is_visible(&mac) {
304            Visible::Yes => false,
305            Visible::Editable => true,
306            Visible::No => return,
307        };
308        render_macro(
309            RenderContext::new(ctx).private_editable(is_private_editable),
310            path_ctx,
311            local_name,
312            mac,
313        )
314        .add_to(self, ctx.db);
315    }
316
317    pub(crate) fn add_function(
318        &mut self,
319        ctx: &CompletionContext<'_, '_>,
320        path_ctx: &PathCompletionCtx<'_>,
321        func: hir::Function,
322        local_name: Option<hir::Name>,
323    ) {
324        let is_private_editable = match ctx.is_visible(&func) {
325            Visible::Yes => false,
326            Visible::Editable => true,
327            Visible::No => return,
328        };
329        let doc_aliases = ctx.doc_aliases(&func);
330        render_fn(
331            RenderContext::new(ctx).private_editable(is_private_editable).doc_aliases(doc_aliases),
332            path_ctx,
333            local_name,
334            func,
335        )
336        .add_to(self, ctx.db);
337    }
338
339    pub(crate) fn add_method(
340        &mut self,
341        ctx: &CompletionContext<'_, '_>,
342        dot_access: &DotAccess<'_>,
343        func: hir::Function,
344        receiver: Option<SmolStr>,
345        local_name: Option<hir::Name>,
346    ) {
347        let is_private_editable = match ctx.is_visible(&func) {
348            Visible::Yes => false,
349            Visible::Editable => true,
350            Visible::No => return,
351        };
352        let doc_aliases = ctx.doc_aliases(&func);
353        render_method(
354            RenderContext::new(ctx).private_editable(is_private_editable).doc_aliases(doc_aliases),
355            dot_access,
356            receiver,
357            local_name,
358            func,
359        )
360        .add_to(self, ctx.db);
361    }
362
363    pub(crate) fn add_method_with_import(
364        &mut self,
365        ctx: &CompletionContext<'_, '_>,
366        dot_access: &DotAccess<'_>,
367        func: hir::Function,
368        import: LocatedImport,
369    ) {
370        let is_private_editable = match ctx.is_visible(&func) {
371            Visible::Yes => false,
372            Visible::Editable => true,
373            Visible::No => return,
374        };
375        let doc_aliases = ctx.doc_aliases(&func);
376        render_method(
377            RenderContext::new(ctx)
378                .private_editable(is_private_editable)
379                .doc_aliases(doc_aliases)
380                .import_to_add(Some(import)),
381            dot_access,
382            None,
383            None,
384            func,
385        )
386        .add_to(self, ctx.db);
387    }
388
389    pub(crate) fn add_const(&mut self, ctx: &CompletionContext<'_, '_>, konst: hir::Const) {
390        let is_private_editable = match ctx.is_visible(&konst) {
391            Visible::Yes => false,
392            Visible::Editable => true,
393            Visible::No => return,
394        };
395        self.add_opt(render_const(
396            RenderContext::new(ctx).private_editable(is_private_editable),
397            konst,
398        ));
399    }
400
401    pub(crate) fn add_type_alias(
402        &mut self,
403        ctx: &CompletionContext<'_, '_>,
404        type_alias: hir::TypeAlias,
405    ) {
406        let is_private_editable = match ctx.is_visible(&type_alias) {
407            Visible::Yes => false,
408            Visible::Editable => true,
409            Visible::No => return,
410        };
411        self.add_opt(render_type_alias(
412            RenderContext::new(ctx).private_editable(is_private_editable),
413            type_alias,
414        ));
415    }
416
417    pub(crate) fn add_type_alias_with_eq(
418        &mut self,
419        ctx: &CompletionContext<'_, '_>,
420        type_alias: hir::TypeAlias,
421    ) {
422        if !ctx.check_stability(Some(&type_alias.attrs(ctx.db))) {
423            return;
424        }
425        self.add_opt(render_type_alias_with_eq(RenderContext::new(ctx), type_alias));
426    }
427
428    pub(crate) fn add_qualified_enum_variant(
429        &mut self,
430        ctx: &CompletionContext<'_, '_>,
431        path_ctx: &PathCompletionCtx<'_>,
432        variant: hir::EnumVariant,
433        path: hir::ModPath,
434    ) {
435        if !ctx.check_stability_and_hidden(variant) {
436            return;
437        }
438        if let Some(builder) =
439            render_variant_lit(RenderContext::new(ctx), path_ctx, None, variant, Some(path))
440        {
441            self.add(builder.build(ctx.db));
442        }
443    }
444
445    pub(crate) fn add_enum_variant(
446        &mut self,
447        ctx: &CompletionContext<'_, '_>,
448        path_ctx: &PathCompletionCtx<'_>,
449        variant: hir::EnumVariant,
450        local_name: Option<hir::Name>,
451    ) {
452        if !ctx.check_stability_and_hidden(variant) {
453            return;
454        }
455        if let PathCompletionCtx { kind: PathKind::Pat { pat_ctx }, .. } = path_ctx {
456            cov_mark::hit!(enum_variant_pattern_path);
457            self.add_variant_pat(ctx, pat_ctx, Some(path_ctx), variant, local_name);
458            return;
459        }
460
461        if let Some(builder) =
462            render_variant_lit(RenderContext::new(ctx), path_ctx, local_name, variant, None)
463        {
464            self.add(builder.build(ctx.db));
465        }
466    }
467
468    pub(crate) fn add_field(
469        &mut self,
470        ctx: &CompletionContext<'_, '_>,
471        dot_access: &DotAccess<'_>,
472        receiver: Option<SmolStr>,
473        field: hir::Field,
474        ty: &hir::Type<'_>,
475    ) {
476        let is_private_editable = match ctx.is_visible(&field) {
477            Visible::Yes => false,
478            Visible::Editable => true,
479            Visible::No => return,
480        };
481        let doc_aliases = ctx.doc_aliases(&field);
482        let item = render_field(
483            RenderContext::new(ctx).private_editable(is_private_editable).doc_aliases(doc_aliases),
484            dot_access,
485            receiver,
486            field,
487            ty,
488        );
489        self.add(item);
490    }
491
492    pub(crate) fn add_struct_literal(
493        &mut self,
494        ctx: &CompletionContext<'_, '_>,
495        path_ctx: &PathCompletionCtx<'_>,
496        strukt: hir::Struct,
497        path: Option<hir::ModPath>,
498        local_name: Option<hir::Name>,
499    ) {
500        let is_private_editable = match ctx.is_visible(&strukt) {
501            Visible::Yes => false,
502            Visible::Editable => true,
503            Visible::No => return,
504        };
505        if let Some(builder) = render_struct_literal(
506            RenderContext::new(ctx).private_editable(is_private_editable),
507            path_ctx,
508            strukt,
509            path,
510            local_name,
511        ) {
512            self.add(builder.build(ctx.db));
513        }
514    }
515
516    pub(crate) fn add_union_literal(
517        &mut self,
518        ctx: &CompletionContext<'_, '_>,
519        un: hir::Union,
520        path: Option<hir::ModPath>,
521        local_name: Option<hir::Name>,
522    ) {
523        let is_private_editable = match ctx.is_visible(&un) {
524            Visible::Yes => false,
525            Visible::Editable => true,
526            Visible::No => return,
527        };
528        let item = render_union_literal(
529            RenderContext::new(ctx).private_editable(is_private_editable),
530            un,
531            path,
532            local_name,
533        );
534        self.add_opt(item);
535    }
536
537    pub(crate) fn add_tuple_field(
538        &mut self,
539        ctx: &CompletionContext<'_, '_>,
540        receiver: Option<SmolStr>,
541        field: usize,
542        ty: &hir::Type<'_>,
543    ) {
544        // Only used for (unnamed) tuples, whose all fields *are* stable. No need to check
545        // stability here.
546        let item = render_tuple_field(RenderContext::new(ctx), receiver, field, ty);
547        self.add(item);
548    }
549
550    pub(crate) fn add_lifetime(&mut self, ctx: &CompletionContext<'_, '_>, name: hir::Name) {
551        CompletionItem::new(
552            SymbolKind::LifetimeParam,
553            ctx.source_range(),
554            name.display_no_db(ctx.edition).to_smolstr(),
555            ctx.edition,
556        )
557        .add_to(self, ctx.db)
558    }
559
560    pub(crate) fn add_label(&mut self, ctx: &CompletionContext<'_, '_>, name: hir::Name) {
561        CompletionItem::new(
562            SymbolKind::Label,
563            ctx.source_range(),
564            name.display_no_db(ctx.edition).to_smolstr(),
565            ctx.edition,
566        )
567        .add_to(self, ctx.db)
568    }
569
570    pub(crate) fn add_variant_pat(
571        &mut self,
572        ctx: &CompletionContext<'_, '_>,
573        pattern_ctx: &PatternContext,
574        path_ctx: Option<&PathCompletionCtx<'_>>,
575        variant: hir::EnumVariant,
576        local_name: Option<hir::Name>,
577    ) {
578        if !ctx.check_stability_and_hidden(variant) {
579            return;
580        }
581        self.add_opt(render_variant_pat(
582            RenderContext::new(ctx),
583            pattern_ctx,
584            path_ctx,
585            variant,
586            local_name,
587            None,
588        ));
589    }
590
591    pub(crate) fn add_qualified_variant_pat(
592        &mut self,
593        ctx: &CompletionContext<'_, '_>,
594        pattern_ctx: &PatternContext,
595        variant: hir::EnumVariant,
596        path: hir::ModPath,
597    ) {
598        if !ctx.check_stability_and_hidden(variant) {
599            return;
600        }
601        let path = Some(&path);
602        self.add_opt(render_variant_pat(
603            RenderContext::new(ctx),
604            pattern_ctx,
605            None,
606            variant,
607            None,
608            path,
609        ));
610    }
611
612    pub(crate) fn add_struct_pat(
613        &mut self,
614        ctx: &CompletionContext<'_, '_>,
615        pattern_ctx: &PatternContext,
616        strukt: hir::Struct,
617        local_name: Option<hir::Name>,
618    ) {
619        let is_private_editable = match ctx.is_visible(&strukt) {
620            Visible::Yes => false,
621            Visible::Editable => true,
622            Visible::No => return,
623        };
624        self.add_opt(render_struct_pat(
625            RenderContext::new(ctx).private_editable(is_private_editable),
626            pattern_ctx,
627            strukt,
628            local_name,
629        ));
630    }
631
632    pub(crate) fn suggest_name(&mut self, ctx: &CompletionContext<'_, '_>, name: &str) {
633        let item = CompletionItem::new(
634            CompletionItemKind::Binding,
635            ctx.source_range(),
636            SmolStr::from(name),
637            ctx.edition,
638        );
639        item.add_to(self, ctx.db);
640    }
641}
642
643/// Calls the callback for each variant of the provided enum with the path to the variant.
644/// Skips variants that are visible with single segment paths.
645fn enum_variants_with_paths(
646    acc: &mut Completions,
647    ctx: &CompletionContext<'_, '_>,
648    enum_: hir::Enum,
649    impl_: Option<&ast::Impl>,
650    cb: impl Fn(&mut Completions, &CompletionContext<'_, '_>, hir::EnumVariant, hir::ModPath),
651) {
652    let mut process_variant = |variant: EnumVariant| {
653        let self_path = hir::ModPath::from_segments(
654            hir::PathKind::Plain,
655            iter::once(Name::new_symbol_root(sym::Self_)).chain(iter::once(variant.name(ctx.db))),
656        );
657
658        cb(acc, ctx, variant, self_path);
659    };
660
661    let variants = enum_.variants(ctx.db);
662
663    if let Some(impl_) = impl_.and_then(|impl_| ctx.sema.to_def(impl_))
664        && impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_))
665    {
666        variants.iter().for_each(|variant| process_variant(*variant));
667    }
668
669    for variant in variants {
670        if let Some(path) = ctx.module.find_path(
671            ctx.db,
672            hir::ModuleDef::from(variant),
673            ctx.config.find_path_config(ctx.is_nightly),
674        ) {
675            // Variants with trivial paths are already added by the existing completion logic,
676            // so we should avoid adding these twice
677            if path.segments().len() > 1 {
678                cb(acc, ctx, variant, path);
679            }
680        }
681    }
682}
683
684pub(super) fn complete_name(
685    acc: &mut Completions,
686    ctx: &CompletionContext<'_, '_>,
687    NameContext { name, kind }: &NameContext,
688) {
689    match kind {
690        NameKind::Const => {
691            item_list::trait_impl::complete_trait_impl_const(acc, ctx, name);
692        }
693        NameKind::Function => {
694            item_list::trait_impl::complete_trait_impl_fn(acc, ctx, name);
695        }
696        NameKind::IdentPat(pattern_ctx) => {
697            if ctx.token.kind() != syntax::T![_] {
698                complete_patterns(acc, ctx, pattern_ctx)
699            }
700        }
701        NameKind::Module(mod_under_caret) => {
702            mod_::complete_mod(acc, ctx, mod_under_caret);
703        }
704        NameKind::TypeAlias => {
705            item_list::trait_impl::complete_trait_impl_type_alias(acc, ctx, name);
706        }
707        NameKind::RecordField => {
708            field::complete_field_list_record_variant(acc, ctx);
709        }
710        NameKind::TypeParam => {
711            acc.add_keyword_snippet(ctx, "const", "const $1: $0");
712        }
713        NameKind::ConstParam
714        | NameKind::Enum
715        | NameKind::MacroDef
716        | NameKind::MacroRules
717        | NameKind::Rename
718        | NameKind::SelfParam
719        | NameKind::Static
720        | NameKind::Struct
721        | NameKind::Trait
722        | NameKind::Union
723        | NameKind::Variant => (),
724    }
725}
726
727pub(super) fn complete_name_ref<'db>(
728    acc: &mut Completions,
729    ctx: &CompletionContext<'_, 'db>,
730    NameRefContext { nameref, kind }: &NameRefContext<'db>,
731) {
732    match kind {
733        NameRefKind::Path(path_ctx) => {
734            flyimport::import_on_the_fly_path(acc, ctx, path_ctx);
735
736            match &path_ctx.kind {
737                PathKind::Expr { expr_ctx } => {
738                    expr::complete_expr_path(acc, ctx, path_ctx, expr_ctx);
739                    expr::complete_expr(acc, ctx, path_ctx);
740
741                    dot::complete_undotted_self(acc, ctx, path_ctx, expr_ctx);
742                    item_list::complete_item_list_in_expr(acc, ctx, path_ctx, expr_ctx);
743                    snippet::complete_expr_snippet(acc, ctx, path_ctx, expr_ctx);
744                }
745                PathKind::Type { location } => {
746                    r#type::complete_type_path(acc, ctx, path_ctx, location);
747
748                    match location {
749                        TypeLocation::TupleField => {
750                            field::complete_field_list_tuple_variant(acc, ctx, path_ctx);
751                        }
752                        TypeLocation::TypeAscription(ascription) => {
753                            if let TypeAscriptionTarget::RetType { item: Some(item), .. } =
754                                ascription
755                                && path_ctx.required_thin_arrow().is_some()
756                                && matches!(path_ctx.qualified, Qualified::No)
757                            {
758                                keyword::complete_for_and_where(acc, ctx, &item.clone().into());
759                            }
760                            r#type::complete_ascribed_type(acc, ctx, path_ctx, ascription);
761                        }
762                        TypeLocation::GenericArg { .. }
763                        | TypeLocation::AssocConstEq
764                        | TypeLocation::AssocTypeEq
765                        | TypeLocation::TypeBound
766                        | TypeLocation::ImplTarget
767                        | TypeLocation::ImplTrait
768                        | TypeLocation::Other => (),
769                    }
770                }
771                PathKind::Attr { attr_ctx } => {
772                    attribute::complete_attribute_path(acc, ctx, path_ctx, attr_ctx);
773                }
774                PathKind::Derive { existing_derives } => {
775                    attribute::complete_derive_path(acc, ctx, path_ctx, existing_derives);
776                }
777                PathKind::Item { kind } => {
778                    item_list::complete_item_list(acc, ctx, path_ctx, kind);
779
780                    snippet::complete_item_snippet(acc, ctx, path_ctx, kind);
781                    if let ItemListKind::TraitImpl(impl_) = kind {
782                        item_list::trait_impl::complete_trait_impl_item_by_name(
783                            acc, ctx, path_ctx, nameref, impl_,
784                        );
785                    }
786                }
787                PathKind::Pat { .. } => {
788                    pattern::complete_pattern_path(acc, ctx, path_ctx);
789                }
790                PathKind::Vis { has_in_token } => {
791                    vis::complete_vis_path(acc, ctx, path_ctx, has_in_token);
792                }
793                PathKind::Use => {
794                    use_::complete_use_path(acc, ctx, path_ctx, nameref);
795                }
796            }
797        }
798        NameRefKind::ExternCrate => extern_crate::complete_extern_crate(acc, ctx),
799        NameRefKind::DotAccess(dot_access) => {
800            flyimport::import_on_the_fly_dot(acc, ctx, dot_access);
801            dot::complete_dot(acc, ctx, dot_access);
802            postfix::complete_postfix(acc, ctx, dot_access);
803        }
804        NameRefKind::Keyword(item) => {
805            keyword::complete_for_and_where(acc, ctx, item);
806        }
807        NameRefKind::RecordExpr { dot_prefix, expr } => {
808            record::complete_record_expr_fields(acc, ctx, expr, dot_prefix);
809        }
810        NameRefKind::Pattern(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx),
811    }
812}
813
814fn complete_patterns(
815    acc: &mut Completions,
816    ctx: &CompletionContext<'_, '_>,
817    pattern_ctx: &PatternContext,
818) {
819    flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
820    fn_param::complete_fn_param(acc, ctx, pattern_ctx);
821    pattern::complete_pattern(acc, ctx, pattern_ctx);
822    record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
823}