Skip to main content

ide_completion/
render.rs

1//! `render` module provides utilities for rendering completion suggestions
2//! into code pieces that will be presented to user.
3
4pub(crate) mod const_;
5pub(crate) mod function;
6pub(crate) mod literal;
7pub(crate) mod macro_;
8pub(crate) mod pattern;
9pub(crate) mod type_alias;
10pub(crate) mod union_literal;
11pub(crate) mod variant;
12
13use hir::{AsAssocItem, HasAttrs, HirDisplay, Impl, ModuleDef, ScopeDef, Type};
14use ide_db::text_edit::TextEdit;
15use ide_db::{
16    RootDatabase, SnippetCap, SymbolKind,
17    documentation::{Documentation, HasDocs},
18    helpers::item_name,
19    imports::import_assets::LocatedImport,
20};
21use syntax::{AstNode, SmolStr, SyntaxKind, TextRange, ToSmolStr, ast, format_smolstr};
22
23use crate::{
24    CompletionContext, CompletionItem, CompletionItemKind, CompletionItemRefMode,
25    CompletionRelevance,
26    context::{
27        DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext, TypeLocation,
28    },
29    item::{Builder, CompletionRelevanceTypeMatch},
30    render::{
31        function::render_fn,
32        literal::render_variant_lit,
33        macro_::{render_macro, render_macro_pat},
34    },
35};
36/// Interface for data and methods required for items rendering.
37#[derive(Debug, Clone)]
38pub(crate) struct RenderContext<'a, 'db> {
39    completion: &'a CompletionContext<'a, 'db>,
40    is_private_editable: bool,
41    import_to_add: Option<LocatedImport>,
42    doc_aliases: Vec<SmolStr>,
43}
44
45impl<'a, 'db> RenderContext<'a, 'db> {
46    pub(crate) fn new(completion: &'a CompletionContext<'a, 'db>) -> RenderContext<'a, 'db> {
47        RenderContext {
48            completion,
49            is_private_editable: false,
50            import_to_add: None,
51            doc_aliases: vec![],
52        }
53    }
54
55    pub(crate) fn private_editable(mut self, private_editable: bool) -> Self {
56        self.is_private_editable = private_editable;
57        self
58    }
59
60    pub(crate) fn import_to_add(mut self, import_to_add: Option<LocatedImport>) -> Self {
61        self.import_to_add = import_to_add;
62        self
63    }
64
65    pub(crate) fn doc_aliases(mut self, doc_aliases: Vec<SmolStr>) -> Self {
66        self.doc_aliases = doc_aliases;
67        self
68    }
69
70    fn snippet_cap(&self) -> Option<SnippetCap> {
71        self.completion.config.snippet_cap
72    }
73
74    fn db(&self) -> &'db RootDatabase {
75        self.completion.db
76    }
77
78    fn source_range(&self) -> TextRange {
79        self.completion.source_range()
80    }
81
82    fn completion_relevance(&self) -> CompletionRelevance {
83        CompletionRelevance {
84            is_private_editable: self.is_private_editable,
85            requires_import: self.import_to_add.is_some(),
86            ..Default::default()
87        }
88    }
89
90    fn is_immediately_after_macro_bang(&self) -> bool {
91        self.completion.token.kind() == SyntaxKind::BANG
92            && self.completion.token.parent().is_some_and(|it| it.kind() == SyntaxKind::MACRO_CALL)
93    }
94
95    /// Whether `def` is deprecated.
96    ///
97    /// This can happen for two reasons:
98    /// - the def is marked with `#[deprecated]`
99    /// - the def is an assoc item whose trait is deprecated
100    ///
101    /// In order to be able to check for the latter, we'd ideally want to `try_as_dyn<_, dyn AsAssocItem>(def)`
102    /// (see [`try_as_dyn`][]), but that function is currently unstable. Therefore, we employ a hack instead:
103    /// if `def` can be an assoc item, it should be passed to this method as follows:
104    /// ```ignore
105    /// self.is_deprecated(def, Some(def))
106    /// ```
107    /// otherwise, it should be passed as:
108    /// ```ignore
109    /// self.is_deprecated(def, None)
110    /// ```
111    ///
112    /// [`try_as_dyn`]: https://doc.rust-lang.org/std/any/fn.try_as_dyn.html
113    fn is_deprecated(&self, def: impl HasAttrs, def_as_assoc_item: Option<hir::AssocItem>) -> bool {
114        let db = self.db();
115        def.attrs(db).is_deprecated()
116            || def_as_assoc_item
117                .and_then(|assoc| assoc.container_or_implemented_trait(db))
118                .is_some_and(|trait_| {
119                    self.is_deprecated(trait_, None /* traits can't be assoc items */)
120                })
121    }
122
123    /// Whether an enum variant should be rendered as deprecated.
124    ///
125    /// A variant inherits deprecation from its parent enum, matching rustc's
126    /// behavior where `#[deprecated]` on an enum applies to its variants.
127    fn is_variant_deprecated(&self, variant: hir::EnumVariant) -> bool {
128        let db = self.db();
129        variant.attrs(db).is_deprecated() || variant.parent_enum(db).attrs(db).is_deprecated()
130    }
131
132    // FIXME: remove this
133    fn docs(&self, def: impl HasDocs) -> Option<Documentation<'a>> {
134        def.docs(self.db())
135    }
136}
137
138pub(crate) fn render_field(
139    ctx: RenderContext<'_, '_>,
140    dot_access: &DotAccess<'_>,
141    receiver: Option<SmolStr>,
142    field: hir::Field,
143    ty: &hir::Type<'_>,
144) -> CompletionItem {
145    let db = ctx.db();
146    let is_deprecated = ctx.is_deprecated(field, None /* fields can't be assoc items */);
147    let name = field.name(db);
148    let (name, escaped_name) =
149        (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr());
150    let mut item = CompletionItem::new(
151        SymbolKind::Field,
152        ctx.source_range(),
153        field_with_receiver(receiver.as_deref(), &name),
154        ctx.completion.edition,
155    );
156    item.set_relevance(CompletionRelevance {
157        type_match: compute_type_match(ctx.completion, ty),
158        exact_name_match: compute_exact_name_match(ctx.completion, &name),
159        is_skipping_completion: receiver.is_some(),
160        ..CompletionRelevance::default()
161    });
162    item.detail(ty.display(db, ctx.completion.display_target).to_string())
163        .set_documentation(field.docs(db))
164        .set_deprecated(is_deprecated)
165        .lookup_by(name);
166
167    let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
168    if !is_field_access || ty.is_fn() || ty.is_closure() {
169        let mut builder = TextEdit::builder();
170        // Using TextEdit, insert '(' before the struct name and ')' before the
171        // dot access, then comes the field name and optionally insert function
172        // call parens.
173
174        builder.replace(
175            ctx.source_range(),
176            field_with_receiver(receiver.as_deref(), &escaped_name).into(),
177        );
178
179        let expected_fn_type =
180            ctx.completion.expected_type.as_ref().is_some_and(|ty| ty.is_fn() || ty.is_closure());
181
182        if !expected_fn_type
183            && let Some(receiver) = &dot_access.receiver
184            && let Some(receiver) = ctx.completion.sema.original_range_opt(receiver.syntax())
185        {
186            builder.insert(receiver.range.start(), "(".to_owned());
187            builder.insert(ctx.source_range().end(), ")".to_owned());
188
189            let is_parens_needed = !matches!(dot_access.kind, DotAccessKind::Method);
190
191            if is_parens_needed {
192                builder.insert(ctx.source_range().end(), "()".to_owned());
193            }
194        }
195
196        item.text_edit(builder.finish());
197    } else {
198        item.insert_text(field_with_receiver(receiver.as_deref(), &escaped_name));
199    }
200    if let Some(receiver) = &dot_access.receiver
201        && let Some(original) = ctx.completion.sema.original_range_opt(receiver.syntax())
202        && let Some(ref_mode) = compute_ref_match(ctx.completion, ty)
203    {
204        item.ref_match(ref_mode, original.range.start());
205    }
206    item.doc_aliases(ctx.doc_aliases);
207    item.build(db)
208}
209
210fn field_with_receiver(receiver: Option<&str>, field_name: &str) -> SmolStr {
211    receiver
212        .map_or_else(|| field_name.into(), |receiver| format_smolstr!("{}.{field_name}", receiver))
213}
214
215pub(crate) fn render_tuple_field(
216    ctx: RenderContext<'_, '_>,
217    receiver: Option<SmolStr>,
218    field: usize,
219    ty: &hir::Type<'_>,
220) -> CompletionItem {
221    let mut item = CompletionItem::new(
222        SymbolKind::Field,
223        ctx.source_range(),
224        field_with_receiver(receiver.as_deref(), &field.to_string()),
225        ctx.completion.edition,
226    );
227    item.detail(ty.display(ctx.db(), ctx.completion.display_target).to_string())
228        .lookup_by(field.to_string());
229    item.set_relevance(CompletionRelevance {
230        is_skipping_completion: receiver.is_some(),
231        ..ctx.completion_relevance()
232    });
233    item.build(ctx.db())
234}
235
236pub(crate) fn render_type_inference(
237    ty_string: String,
238    ctx: &CompletionContext<'_, '_>,
239    path_ctx: &PathCompletionCtx<'_>,
240) -> CompletionItem {
241    let mut builder = CompletionItem::new(
242        CompletionItemKind::InferredType,
243        ctx.source_range(),
244        &ty_string,
245        ctx.edition,
246    );
247    adds_ret_type_arrow(ctx, path_ctx, &mut builder, ty_string);
248    builder.set_relevance(CompletionRelevance {
249        type_match: Some(CompletionRelevanceTypeMatch::Exact),
250        exact_name_match: true,
251        ..Default::default()
252    });
253    builder.build(ctx.db)
254}
255
256pub(crate) fn render_path_resolution(
257    ctx: RenderContext<'_, '_>,
258    path_ctx: &PathCompletionCtx<'_>,
259    local_name: hir::Name,
260    resolution: ScopeDef,
261) -> Builder {
262    render_resolution_path(ctx, path_ctx, local_name, None, resolution)
263}
264
265pub(crate) fn render_pattern_resolution(
266    ctx: RenderContext<'_, '_>,
267    pattern_ctx: &PatternContext,
268    local_name: hir::Name,
269    resolution: ScopeDef,
270) -> Builder {
271    render_resolution_pat(ctx, pattern_ctx, local_name, None, resolution)
272}
273
274pub(crate) fn render_resolution_with_import(
275    ctx: RenderContext<'_, '_>,
276    path_ctx: &PathCompletionCtx<'_>,
277    import_edit: LocatedImport,
278) -> Option<Builder> {
279    let resolution = ScopeDef::from(import_edit.original_item);
280    let local_name = get_import_name(resolution, &ctx, &import_edit)?;
281    // This now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead.
282    let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution);
283    let ctx = ctx.doc_aliases(doc_aliases);
284    Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
285}
286
287pub(crate) fn render_resolution_with_import_pat(
288    ctx: RenderContext<'_, '_>,
289    pattern_ctx: &PatternContext,
290    import_edit: LocatedImport,
291) -> Option<Builder> {
292    let resolution = ScopeDef::from(import_edit.original_item);
293    let local_name = get_import_name(resolution, &ctx, &import_edit)?;
294    Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
295}
296
297pub(crate) fn render_expr<'db>(
298    ctx: &CompletionContext<'_, 'db>,
299    expr: &hir::term_search::Expr<'db>,
300) -> Option<Builder> {
301    let mut i = 1;
302    let mut snippet_formatter = |ty: &hir::Type<'_>| {
303        let arg_name = ty
304            .as_adt()
305            .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
306            .unwrap_or_else(|| String::from("_"));
307        let res = format!("${{{i}:{arg_name}}}");
308        i += 1;
309        res
310    };
311
312    let mut label_formatter = |ty: &hir::Type<'_>| {
313        ty.as_adt()
314            .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
315            .unwrap_or_else(|| String::from("..."))
316    };
317
318    let cfg = ctx.config.find_path_config(ctx.is_nightly);
319
320    let label =
321        expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.display_target).ok()?;
322
323    let source_range = match ctx.original_token.parent() {
324        Some(node) => match node.ancestors().find_map(ast::Path::cast) {
325            Some(path) => path.syntax().text_range(),
326            None => node.text_range(),
327        },
328        None => ctx.source_range(),
329    };
330
331    let mut item =
332        CompletionItem::new(CompletionItemKind::Expression, source_range, label, ctx.edition);
333
334    let snippet = format!(
335        "{}$0",
336        expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.display_target).ok()?
337    );
338    let edit = TextEdit::replace(source_range, snippet);
339    item.snippet_edit(ctx.config.snippet_cap?, edit);
340    item.documentation(Documentation::new_owned(String::from(
341        "Autogenerated expression by term search",
342    )));
343    item.set_relevance(crate::CompletionRelevance {
344        type_match: compute_type_match(ctx, &ctx.rebase_ty(&expr.ty(ctx.db))),
345        ..Default::default()
346    });
347    for trait_ in expr.traits_used(ctx.db) {
348        let trait_item = hir::ItemInNs::from(hir::ModuleDef::from(trait_));
349        let Some(path) = ctx.module.find_path(ctx.db, trait_item, cfg) else {
350            continue;
351        };
352
353        item.add_import(LocatedImport::new_no_completion(path, trait_item, trait_item));
354    }
355
356    Some(item)
357}
358
359fn get_import_name(
360    resolution: ScopeDef,
361    ctx: &RenderContext<'_, '_>,
362    import_edit: &LocatedImport,
363) -> Option<hir::Name> {
364    // FIXME: Temporary workaround for handling aliased import.
365    // This should be removed after we have proper support for importing alias.
366    // <https://github.com/rust-lang/rust-analyzer/issues/14079>
367
368    // If `item_to_import` matches `original_item`, we are importing the item itself (not its parent module).
369    // In this case, we can use the last segment of `import_path`, as it accounts for the aliased name.
370    if import_edit.item_to_import == import_edit.original_item {
371        import_edit.import_path.segments().last().cloned()
372    } else {
373        scope_def_to_name(resolution, ctx, import_edit)
374    }
375}
376
377fn scope_def_to_name(
378    resolution: ScopeDef,
379    ctx: &RenderContext<'_, '_>,
380    import_edit: &LocatedImport,
381) -> Option<hir::Name> {
382    Some(match resolution {
383        ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
384        ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
385        ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
386        _ => item_name(ctx.db(), import_edit.original_item)?,
387    })
388}
389
390fn render_resolution_pat(
391    ctx: RenderContext<'_, '_>,
392    pattern_ctx: &PatternContext,
393    local_name: hir::Name,
394    import_to_add: Option<LocatedImport>,
395    resolution: ScopeDef,
396) -> Builder {
397    let _p = tracing::info_span!("render_resolution_pat").entered();
398    use hir::ModuleDef::*;
399
400    if let ScopeDef::ModuleDef(Macro(mac)) = resolution {
401        let ctx = ctx.import_to_add(import_to_add);
402        render_macro_pat(ctx, pattern_ctx, local_name, mac)
403    } else {
404        render_resolution_simple_(ctx, &local_name, import_to_add, resolution)
405    }
406}
407
408fn render_resolution_path<'db>(
409    ctx: RenderContext<'_, 'db>,
410    path_ctx: &PathCompletionCtx<'_>,
411    local_name: hir::Name,
412    import_to_add: Option<LocatedImport>,
413    resolution: ScopeDef,
414) -> Builder {
415    let _p = tracing::info_span!("render_resolution_path").entered();
416    use hir::ModuleDef::*;
417
418    let krate = ctx.completion.display_target;
419
420    match resolution {
421        ScopeDef::ModuleDef(Macro(mac)) => {
422            let ctx = ctx.import_to_add(import_to_add);
423            return render_macro(ctx, path_ctx, local_name, mac);
424        }
425        ScopeDef::ModuleDef(Function(func)) => {
426            let ctx = ctx.import_to_add(import_to_add);
427            return render_fn(ctx, path_ctx, Some(local_name), func);
428        }
429        ScopeDef::ModuleDef(EnumVariant(var)) => {
430            let ctx = ctx.clone().import_to_add(import_to_add.clone());
431            if let Some(item) =
432                render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
433            {
434                return item;
435            }
436        }
437        _ => (),
438    }
439
440    let completion = ctx.completion;
441    let module = completion.module;
442    let cap = ctx.snippet_cap();
443    let db = completion.db;
444    let config = completion.config;
445    let requires_import = import_to_add.is_some();
446
447    let name = local_name.display(db, completion.edition).to_smolstr();
448    let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
449    let mut insert_text = name.clone();
450
451    // Add `<>` for generic types
452    let type_path_no_ty_args = matches!(
453        path_ctx,
454        PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
455    ) && config.callable.is_some();
456    if type_path_no_ty_args && let Some(cap) = cap {
457        let has_non_default_type_params = match resolution {
458            ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
459            ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
460                it.has_non_default_type_params(db)
461            }
462            _ => false,
463        };
464
465        if has_non_default_type_params {
466            cov_mark::hit!(inserts_angle_brackets_for_generics);
467            insert_text = format_smolstr!("{insert_text}<$0>");
468            item.lookup_by(name.clone())
469                .label(SmolStr::from_iter([&name, "<…>"]))
470                .trigger_call_info()
471                .insert_snippet(cap, ""); // set is snippet
472        }
473    }
474    let allow_module_path = matches!(path_ctx.kind, PathKind::Use)
475        || completion.token.next_token().is_some_and(|it| it.kind() == syntax::T![::])
476        || !config.add_colons_to_module;
477    if !allow_module_path && matches!(resolution, ScopeDef::ModuleDef(Module(_))) {
478        insert_text = format_smolstr!("{insert_text}::");
479        item.lookup_by(name.clone()).label(insert_text.clone());
480    }
481    adds_ret_type_arrow(completion, path_ctx, &mut item, insert_text.into());
482
483    let mut set_item_relevance = |ty: Type<'db>| {
484        if !ty.is_unknown() {
485            item.detail(ty.display(db, krate).to_string());
486        }
487
488        let ty = completion.rebase_ty(&ty);
489        item.set_relevance(CompletionRelevance {
490            type_match: compute_type_match(completion, &ty),
491            exact_name_match: compute_exact_name_match(completion, &name),
492            is_local: matches!(resolution, ScopeDef::Local(_)),
493            requires_import,
494            has_local_inherent_impl: compute_has_local_inherent_impl(db, path_ctx, &ty, module),
495            ..CompletionRelevance::default()
496        });
497
498        match resolution {
499            ScopeDef::Local(_)
500            | ScopeDef::ModuleDef(ModuleDef::Const(_) | ModuleDef::Static(_)) => {
501                path_ref_match(completion, path_ctx, &ty, &mut item)
502            }
503            _ => (),
504        }
505    };
506
507    match resolution {
508        ScopeDef::Local(local) => set_item_relevance(local.ty(db)),
509        ScopeDef::ModuleDef(ModuleDef::Adt(adt)) | ScopeDef::AdtSelfType(adt) => {
510            set_item_relevance(adt.ty(db))
511        }
512        // Filtered out above
513        ScopeDef::ModuleDef(
514            ModuleDef::Function(_) | ModuleDef::EnumVariant(_) | ModuleDef::Macro(_),
515        ) => (),
516        ScopeDef::ModuleDef(ModuleDef::Const(konst)) => set_item_relevance(konst.ty(db)),
517        ScopeDef::ModuleDef(ModuleDef::Static(stat)) => set_item_relevance(stat.ty(db)),
518        ScopeDef::ModuleDef(ModuleDef::BuiltinType(bt)) => set_item_relevance(bt.ty(db)),
519        ScopeDef::ImplSelfType(imp) => set_item_relevance(imp.self_ty(db)),
520        ScopeDef::GenericParam(_)
521        | ScopeDef::Label(_)
522        | ScopeDef::Unknown
523        | ScopeDef::ModuleDef(
524            ModuleDef::Trait(_) | ModuleDef::Module(_) | ModuleDef::TypeAlias(_),
525        ) => (),
526    };
527
528    item
529}
530
531fn render_resolution_simple_(
532    ctx: RenderContext<'_, '_>,
533    local_name: &hir::Name,
534    import_to_add: Option<LocatedImport>,
535    resolution: ScopeDef,
536) -> Builder {
537    let _p = tracing::info_span!("render_resolution_simple_").entered();
538
539    let db = ctx.db();
540    let ctx = ctx.import_to_add(import_to_add);
541    let kind = res_to_kind(resolution);
542
543    let mut item = CompletionItem::new(
544        kind,
545        ctx.source_range(),
546        local_name.as_str().to_smolstr(),
547        ctx.completion.edition,
548    );
549    item.set_relevance(ctx.completion_relevance())
550        .set_documentation(scope_def_docs(db, resolution))
551        .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
552
553    if let Some(import_to_add) = ctx.import_to_add {
554        item.add_import(import_to_add);
555    }
556
557    item.doc_aliases(ctx.doc_aliases);
558    item
559}
560
561fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
562    use hir::ModuleDef::*;
563    match resolution {
564        ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
565        ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
566        ScopeDef::ModuleDef(EnumVariant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
567        ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
568        ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
569        ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
570            hir::Adt::Struct(_) => SymbolKind::Struct,
571            hir::Adt::Union(_) => SymbolKind::Union,
572            hir::Adt::Enum(_) => SymbolKind::Enum,
573        }),
574        ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
575        ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
576        ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
577        ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
578        ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
579        ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
580            hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
581            hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
582            hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
583        }),
584        ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
585        ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
586        ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
587            CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
588        }
589    }
590}
591
592fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<Documentation<'_>> {
593    use hir::ModuleDef::*;
594    match resolution {
595        ScopeDef::ModuleDef(Module(it)) => it.docs(db),
596        ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
597        ScopeDef::ModuleDef(EnumVariant(it)) => it.docs(db),
598        ScopeDef::ModuleDef(Const(it)) => it.docs(db),
599        ScopeDef::ModuleDef(Static(it)) => it.docs(db),
600        ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
601        ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
602        _ => None,
603    }
604}
605
606fn scope_def_is_deprecated(ctx: &RenderContext<'_, '_>, resolution: ScopeDef) -> bool {
607    let db = ctx.db();
608    match resolution {
609        ScopeDef::ModuleDef(hir::ModuleDef::EnumVariant(it)) => ctx.is_variant_deprecated(it),
610        ScopeDef::ModuleDef(it) => ctx.is_deprecated(it, it.as_assoc_item(db)),
611        ScopeDef::GenericParam(it) => {
612            ctx.is_deprecated(it, None /* generic params can't be assoc items */)
613        }
614        ScopeDef::AdtSelfType(it) => {
615            ctx.is_deprecated(it, None /* `Self` can't be an assoc item */)
616        }
617        _ => false,
618    }
619}
620
621pub(crate) fn render_type_keyword_snippet(
622    ctx: &CompletionContext<'_, '_>,
623    path_ctx: &PathCompletionCtx<'_>,
624    label: &str,
625    snippet: &str,
626) -> Builder {
627    let source_range = ctx.source_range();
628    let mut item =
629        CompletionItem::new(CompletionItemKind::Keyword, source_range, label, ctx.edition);
630
631    let insert_text = if !snippet.contains('$') {
632        item.insert_text(snippet);
633        snippet
634    } else if let Some(cap) = ctx.config.snippet_cap {
635        item.insert_snippet(cap, snippet);
636        snippet
637    } else {
638        label
639    };
640
641    adds_ret_type_arrow(ctx, path_ctx, &mut item, insert_text.to_owned());
642    item
643}
644
645fn adds_ret_type_arrow(
646    ctx: &CompletionContext<'_, '_>,
647    path_ctx: &PathCompletionCtx<'_>,
648    item: &mut Builder,
649    insert_text: String,
650) {
651    if let Some((arrow, at)) = path_ctx.required_thin_arrow() {
652        let mut edit = TextEdit::builder();
653
654        edit.insert(at, arrow.to_owned());
655        edit.replace(ctx.source_range(), insert_text);
656
657        item.text_edit(edit.finish()).adds_text(SmolStr::new_static(arrow));
658    } else {
659        item.insert_text(insert_text);
660    }
661}
662
663// FIXME: This checks types without possible coercions which some completions might want to do
664fn match_types(
665    ctx: &CompletionContext<'_, '_>,
666    ty1: &hir::Type<'_>,
667    ty2: &hir::Type<'_>,
668) -> Option<CompletionRelevanceTypeMatch> {
669    if ty1 == ty2 {
670        Some(CompletionRelevanceTypeMatch::Exact)
671    } else if ty1.could_unify_with(ctx.db, ty2) {
672        Some(CompletionRelevanceTypeMatch::CouldUnify)
673    } else {
674        None
675    }
676}
677
678fn compute_type_match(
679    ctx: &CompletionContext<'_, '_>,
680    completion_ty: &hir::Type<'_>,
681) -> Option<CompletionRelevanceTypeMatch> {
682    let expected_type = ctx.expected_type.as_ref()?;
683
684    // We don't ever consider unit type to be an exact type match, since
685    // nearly always this is not meaningful to the user.
686    if expected_type.is_unit() {
687        return None;
688    }
689
690    // &mut ty -> &ty
691    if completion_ty.is_mutable_reference()
692        && let Some((expected_type, _)) = expected_type.as_reference()
693        && let Some((completion_ty, _)) = completion_ty.as_reference()
694    {
695        return match_types(ctx, &expected_type, &completion_ty);
696    }
697
698    match_types(ctx, expected_type, completion_ty)
699}
700
701fn compute_has_local_inherent_impl(
702    db: &RootDatabase,
703    path_ctx: &PathCompletionCtx<'_>,
704    completion_ty: &hir::Type<'_>,
705    curr_module: hir::Module,
706) -> bool {
707    matches!(path_ctx.kind, PathKind::Type { location: TypeLocation::ImplTarget })
708        && Impl::all_for_type(db, completion_ty.clone())
709            .iter()
710            .any(|imp| imp.trait_(db).is_none() && imp.module(db) == curr_module)
711}
712
713fn compute_exact_name_match(ctx: &CompletionContext<'_, '_>, completion_name: &str) -> bool {
714    ctx.expected_name.as_ref().is_some_and(|name| name.text() == completion_name)
715}
716
717fn compute_ref_match(
718    ctx: &CompletionContext<'_, '_>,
719    completion_ty: &hir::Type<'_>,
720) -> Option<CompletionItemRefMode> {
721    if compute_type_match(ctx, completion_ty).is_some() || completion_ty.is_unit() {
722        return None;
723    }
724    let expected_type = ctx.expected_type.as_ref()?;
725    let expected_without_ref = expected_type.as_reference();
726    let completion_without_ref = completion_ty.as_reference();
727
728    if let Some((expected_without_ref, _)) = &expected_without_ref
729        && (completion_without_ref.is_none()
730            || completion_ty.could_unify_with(ctx.db, expected_without_ref))
731        && completion_ty
732            .autoderef(ctx.db)
733            .any(|ty| !ty.is_unknown() && ty.could_unify_with(ctx.db, expected_without_ref))
734    {
735        cov_mark::hit!(suggest_ref);
736        let mutability = if expected_type.is_mutable_reference() {
737            hir::Mutability::Mut
738        } else {
739            hir::Mutability::Shared
740        };
741        return Some(CompletionItemRefMode::Reference(mutability));
742    }
743
744    if let Some((completion_without_ref, _)) = completion_without_ref
745        && completion_without_ref == *expected_type
746        && completion_without_ref.is_copy(ctx.db)
747    {
748        cov_mark::hit!(suggest_deref);
749        return Some(CompletionItemRefMode::Dereference);
750    }
751
752    None
753}
754
755fn path_ref_match(
756    completion: &CompletionContext<'_, '_>,
757    path_ctx: &PathCompletionCtx<'_>,
758    ty: &hir::Type<'_>,
759    item: &mut Builder,
760) {
761    if let Some(original_path) = &path_ctx.original_path {
762        // At least one char was typed by the user already, in that case look for the original path
763        if let Some(original_path) = completion.sema.original_range_opt(original_path.syntax())
764            && let Some(ref_mode) = compute_ref_match(completion, ty)
765        {
766            item.ref_match(ref_mode, original_path.range.start());
767        }
768    } else {
769        // completion requested on an empty identifier, there is no path here yet.
770        // FIXME: This might create inconsistent completions where we show a ref match in macro inputs
771        // as long as nothing was typed yet
772        if let Some(ref_mode) = compute_ref_match(completion, ty) {
773            item.ref_match(ref_mode, completion.source_range().start());
774        }
775    }
776}
777
778#[cfg(test)]
779mod tests {
780    use std::cmp;
781
782    use expect_test::{Expect, expect};
783    use ide_db::SymbolKind;
784    use itertools::Itertools;
785
786    use crate::{
787        CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
788        item::CompletionRelevanceTypeMatch,
789        tests::{TEST_CONFIG, check_edit, do_completion, get_all_items},
790    };
791
792    #[track_caller]
793    fn check(
794        #[rust_analyzer::rust_fixture] ra_fixture: &str,
795        kind: impl Into<CompletionItemKind>,
796        expect: Expect,
797    ) {
798        let actual = do_completion(ra_fixture, kind.into());
799        expect.assert_debug_eq(&actual);
800    }
801
802    #[track_caller]
803    fn check_kinds(
804        #[rust_analyzer::rust_fixture] ra_fixture: &str,
805        kinds: &[CompletionItemKind],
806        expect: Expect,
807    ) {
808        let actual: Vec<_> =
809            kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
810        expect.assert_debug_eq(&actual);
811    }
812
813    #[track_caller]
814    fn check_function_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
815        let actual: Vec<_> =
816            do_completion(ra_fixture, CompletionItemKind::SymbolKind(SymbolKind::Method))
817                .into_iter()
818                .map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
819                .collect();
820
821        expect.assert_debug_eq(&actual);
822    }
823
824    #[track_caller]
825    fn check_relevance_for_kinds(
826        #[rust_analyzer::rust_fixture] ra_fixture: &str,
827        kinds: &[CompletionItemKind],
828        expect: Expect,
829    ) {
830        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
831        actual.retain(|it| kinds.contains(&it.kind));
832        actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
833        check_relevance_(actual, expect);
834    }
835
836    #[track_caller]
837    fn check_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
838        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
839        actual.retain(|it| it.kind != CompletionItemKind::Snippet);
840        actual.retain(|it| it.kind != CompletionItemKind::Keyword);
841        actual.retain(|it| it.kind != CompletionItemKind::BuiltinType);
842        actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
843        check_relevance_(actual, expect);
844    }
845
846    #[track_caller]
847    fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
848        let actual = actual
849            .into_iter()
850            .flat_map(|it| {
851                let mut items = vec![];
852
853                let tag = it.kind.tag();
854                let relevance = display_relevance(it.relevance);
855                items.push(format!(
856                    "{tag} {} {} {relevance}\n",
857                    it.label.primary,
858                    it.label.detail_right.as_deref().unwrap_or_default(),
859                ));
860
861                if let Some((label, _indel, relevance)) = it.ref_match() {
862                    let relevance = display_relevance(relevance);
863
864                    items.push(format!("{tag} {label} {relevance}\n"));
865                }
866
867                items
868            })
869            .collect::<String>();
870
871        expect.assert_eq(&actual);
872
873        fn display_relevance(relevance: CompletionRelevance) -> String {
874            let CompletionRelevance {
875                exact_name_match,
876                type_match,
877                is_local,
878                is_missing,
879                trait_,
880                is_name_already_imported: _,
881                requires_import,
882                is_private_editable: _,
883                postfix_match,
884                function: _,
885                is_skipping_completion: _,
886                has_local_inherent_impl,
887                is_deprecated,
888            } = relevance;
889            let relevance_factors = [
890                (type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
891                (type_match == Some(CompletionRelevanceTypeMatch::CouldUnify), "type_could_unify"),
892                (exact_name_match, "name"),
893                (is_local, "local"),
894                (is_missing, "missing"),
895                (postfix_match == Some(CompletionRelevancePostfixMatch::Exact), "snippet"),
896                (trait_.is_some_and(|it| it.is_op_method), "op_method"),
897                (requires_import, "requires_import"),
898                (has_local_inherent_impl, "has_local_inherent_impl"),
899                (is_deprecated, "deprecated"),
900            ]
901            .into_iter()
902            .filter_map(|(cond, desc)| cond.then_some(desc))
903            .join("+");
904
905            format!("[{relevance_factors}]")
906        }
907    }
908
909    #[test]
910    fn trait_imported_as_underscore_should_not_appear_auto_import_again() {
911        // make sure there has no `requires_import`
912        // see https://github.com/rust-lang/rust-analyzer/issues/19767
913        check_relevance(
914            r#"
915//- /dep.rs crate:dep
916pub trait MyTrait {
917    fn my_method(&self);
918}
919
920//- /main.rs crate:main deps:dep
921use dep::MyTrait as _;
922struct MyStruct;
923impl dep::MyTrait for MyStruct {
924    fn my_method(&self) {}
925}
926fn main() {
927    MyStruct::my_method$0
928}
929"#,
930            expect![[r#"
931                me my_method(…) fn(&self) []
932            "#]],
933        );
934    }
935
936    #[test]
937    fn set_struct_type_completion_info() {
938        check_relevance(
939            r#"
940//- /lib.rs crate:dep
941
942pub mod test_mod_b {
943    pub struct Struct {}
944}
945
946pub mod test_mod_a {
947    pub struct Struct {}
948}
949
950//- /main.rs crate:main deps:dep
951
952fn test(input: dep::test_mod_b::Struct) { }
953
954fn main() {
955    test(Struct$0);
956}
957"#,
958            expect![[r#"
959                st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct {  } [type]
960                ex dep::test_mod_b::Struct {  }  [type]
961                st Struct Struct [type+requires_import]
962                md dep::  []
963                fn main() fn() []
964                fn test(…) fn(Struct) []
965                st Struct Struct [requires_import]
966            "#]],
967        );
968    }
969
970    #[test]
971    fn set_union_type_completion_info() {
972        check_relevance(
973            r#"
974//- /lib.rs crate:dep
975
976pub mod test_mod_b {
977    pub union Union {
978        a: i32,
979        b: i32
980    }
981}
982
983pub mod test_mod_a {
984    pub enum Union {
985        a: i32,
986        b: i32
987    }
988}
989
990//- /main.rs crate:main deps:dep
991
992fn test(input: dep::test_mod_b::Union) { }
993
994fn main() {
995    test(Union$0);
996}
997"#,
998            expect![[r#"
999                un Union Union [type+requires_import]
1000                md dep::  []
1001                fn main() fn() []
1002                fn test(…) fn(Union) []
1003                en Union Union [requires_import]
1004            "#]],
1005        );
1006    }
1007
1008    #[test]
1009    fn set_enum_type_completion_info() {
1010        check_relevance(
1011            r#"
1012//- /lib.rs crate:dep
1013
1014pub mod test_mod_b {
1015    pub enum Enum {
1016        variant
1017    }
1018}
1019
1020pub mod test_mod_a {
1021    pub enum Enum {
1022        variant
1023    }
1024}
1025
1026//- /main.rs crate:main deps:dep
1027
1028fn test(input: dep::test_mod_b::Enum) { }
1029
1030fn main() {
1031    test(Enum$0);
1032}
1033"#,
1034            expect![[r#"
1035                ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type]
1036                ex dep::test_mod_b::Enum::variant  [type]
1037                en Enum Enum [type+requires_import]
1038                md dep::  []
1039                fn main() fn() []
1040                fn test(…) fn(Enum) []
1041                en Enum Enum [requires_import]
1042            "#]],
1043        );
1044    }
1045
1046    #[test]
1047    fn set_enum_variant_type_completion_info() {
1048        check_relevance(
1049            r#"
1050//- /lib.rs crate:dep
1051
1052pub mod test_mod_b {
1053    pub enum Enum {
1054        Variant
1055    }
1056}
1057
1058pub mod test_mod_a {
1059    pub enum Enum {
1060        Variant
1061    }
1062}
1063
1064//- /main.rs crate:main deps:dep
1065
1066fn test(input: dep::test_mod_b::Enum) { }
1067
1068fn main() {
1069    test(Variant$0);
1070}
1071"#,
1072            expect![[r#"
1073                ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type]
1074                ex dep::test_mod_b::Enum::Variant  [type]
1075                ev Variant Variant [type+requires_import]
1076                md dep::  []
1077                fn main() fn() []
1078                fn test(…) fn(Enum) []
1079                ev Variant Variant [requires_import]
1080            "#]],
1081        );
1082    }
1083
1084    #[test]
1085    fn set_fn_type_completion_info() {
1086        check_relevance(
1087            r#"
1088//- /lib.rs crate:dep
1089
1090pub mod test_mod_b {
1091    pub fn function(j: isize) -> i32 {}
1092}
1093
1094pub mod test_mod_a {
1095    pub fn function(i: usize) -> i32 {}
1096}
1097
1098//- /main.rs crate:main deps:dep
1099
1100fn test(input: fn(usize) -> i32) { }
1101
1102fn main() {
1103    test(function$0);
1104}
1105"#,
1106            expect![[r#"
1107                md dep::  []
1108                fn main() fn() []
1109                fn test(…) fn(fn(usize) -> i32) []
1110                fn function fn(usize) -> i32 [requires_import]
1111                fn function(…) fn(isize) -> i32 [requires_import]
1112            "#]],
1113        );
1114    }
1115
1116    #[test]
1117    fn set_const_type_completion_info() {
1118        check_relevance(
1119            r#"
1120//- /lib.rs crate:dep
1121
1122pub mod test_mod_b {
1123    pub const CONST: i32 = 1;
1124}
1125
1126pub mod test_mod_a {
1127    pub const CONST: i64 = 2;
1128}
1129
1130//- /main.rs crate:main deps:dep
1131
1132fn test(input: i32) { }
1133
1134fn main() {
1135    test(CONST$0);
1136}
1137"#,
1138            expect![[r#"
1139                ct CONST i32 [type+requires_import]
1140                md dep::  []
1141                fn main() fn() []
1142                fn test(…) fn(i32) []
1143                ct CONST i64 [requires_import]
1144            "#]],
1145        );
1146    }
1147
1148    #[test]
1149    fn set_static_type_completion_info() {
1150        check_relevance(
1151            r#"
1152//- /lib.rs crate:dep
1153
1154pub mod test_mod_b {
1155    pub static STATIC: i32 = 5;
1156}
1157
1158pub mod test_mod_a {
1159    pub static STATIC: i64 = 5;
1160}
1161
1162//- /main.rs crate:main deps:dep
1163
1164fn test(input: i32) { }
1165
1166fn main() {
1167    test(STATIC$0);
1168}
1169"#,
1170            expect![[r#"
1171                sc STATIC i32 [type+requires_import]
1172                md dep::  []
1173                fn main() fn() []
1174                fn test(…) fn(i32) []
1175                sc STATIC i64 [requires_import]
1176            "#]],
1177        );
1178    }
1179
1180    #[test]
1181    fn set_self_type_completion_info_with_params() {
1182        check_relevance(
1183            r#"
1184//- /lib.rs crate:dep
1185pub struct Struct;
1186
1187impl Struct {
1188    pub fn Function(&self, input: i32) -> bool {
1189                false
1190    }
1191}
1192
1193
1194//- /main.rs crate:main deps:dep
1195
1196use dep::Struct;
1197
1198
1199fn test(input: fn(&dep::Struct, i32) -> bool) { }
1200
1201fn main() {
1202    test(Struct::Function$0);
1203}
1204
1205"#,
1206            expect![[r#"
1207                me Function fn(&self, i32) -> bool []
1208            "#]],
1209        );
1210    }
1211
1212    #[test]
1213    fn set_self_type_completion_info() {
1214        check_relevance(
1215            r#"
1216//- /main.rs crate:main
1217
1218struct Struct;
1219
1220impl Struct {
1221fn test(&self) {
1222        func(Self$0);
1223    }
1224}
1225
1226fn func(input: Struct) { }
1227
1228"#,
1229            expect![[r#"
1230                st Self Self [type]
1231                st Struct Struct [type]
1232                sp Self Struct [type]
1233                st Struct Struct [type]
1234                ex Struct  [type]
1235                lc self &Struct [local]
1236                fn func(…) fn(Struct) []
1237                me self.test() fn(&self) []
1238            "#]],
1239        );
1240    }
1241
1242    #[test]
1243    fn set_builtin_type_completion_info() {
1244        check_relevance(
1245            r#"
1246//- /main.rs crate:main
1247
1248fn test(input: bool) { }
1249    pub Input: bool = false;
1250
1251fn main() {
1252    let input = false;
1253    let inputbad = 3;
1254    test(inp$0);
1255}
1256"#,
1257            expect![[r#"
1258                lc input bool [type+name+local]
1259                ex false  [type]
1260                ex input  [type]
1261                ex true  [type]
1262                lc inputbad i32 [local]
1263                fn main() fn() []
1264                fn test(…) fn(bool) []
1265            "#]],
1266        );
1267    }
1268
1269    #[test]
1270    fn enum_detail_includes_record_fields() {
1271        check(
1272            r#"
1273enum Foo { Foo { x: i32, y: i32 } }
1274
1275fn main() { Foo::Fo$0 }
1276"#,
1277            SymbolKind::Variant,
1278            expect![[r#"
1279                [
1280                    CompletionItem {
1281                        label: "Foo {…}",
1282                        detail_left: None,
1283                        detail_right: Some(
1284                            "Foo { x: i32, y: i32 }",
1285                        ),
1286                        source_range: 54..56,
1287                        delete: 54..56,
1288                        insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
1289                        kind: SymbolKind(
1290                            Variant,
1291                        ),
1292                        lookup: "Foo{}",
1293                        detail: "Foo { x: i32, y: i32 }",
1294                        relevance: CompletionRelevance {
1295                            exact_name_match: false,
1296                            type_match: None,
1297                            is_local: false,
1298                            is_missing: false,
1299                            trait_: None,
1300                            is_name_already_imported: false,
1301                            requires_import: false,
1302                            is_private_editable: false,
1303                            postfix_match: None,
1304                            function: Some(
1305                                CompletionRelevanceFn {
1306                                    has_params: true,
1307                                    has_self_param: false,
1308                                    return_type: DirectConstructor,
1309                                },
1310                            ),
1311                            is_skipping_completion: false,
1312                            has_local_inherent_impl: false,
1313                            is_deprecated: false,
1314                        },
1315                        trigger_call_info: true,
1316                    },
1317                ]
1318            "#]],
1319        );
1320    }
1321
1322    #[test]
1323    fn enum_detail_includes_tuple_fields() {
1324        check(
1325            r#"
1326enum Foo { Foo (i32, i32) }
1327
1328fn main() { Foo::Fo$0 }
1329"#,
1330            SymbolKind::Variant,
1331            expect![[r#"
1332                [
1333                    CompletionItem {
1334                        label: "Foo(…)",
1335                        detail_left: None,
1336                        detail_right: Some(
1337                            "Foo(i32, i32)",
1338                        ),
1339                        source_range: 46..48,
1340                        delete: 46..48,
1341                        insert: "Foo(${1:()}, ${2:()})$0",
1342                        kind: SymbolKind(
1343                            Variant,
1344                        ),
1345                        lookup: "Foo()",
1346                        detail: "Foo(i32, i32)",
1347                        relevance: CompletionRelevance {
1348                            exact_name_match: false,
1349                            type_match: None,
1350                            is_local: false,
1351                            is_missing: false,
1352                            trait_: None,
1353                            is_name_already_imported: false,
1354                            requires_import: false,
1355                            is_private_editable: false,
1356                            postfix_match: None,
1357                            function: Some(
1358                                CompletionRelevanceFn {
1359                                    has_params: true,
1360                                    has_self_param: false,
1361                                    return_type: DirectConstructor,
1362                                },
1363                            ),
1364                            is_skipping_completion: false,
1365                            has_local_inherent_impl: false,
1366                            is_deprecated: false,
1367                        },
1368                        trigger_call_info: true,
1369                    },
1370                ]
1371            "#]],
1372        );
1373    }
1374
1375    #[test]
1376    fn fn_detail_includes_args_and_return_type() {
1377        check(
1378            r#"
1379fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
1380
1381fn main() { fo$0 }
1382"#,
1383            SymbolKind::Function,
1384            expect![[r#"
1385                [
1386                    CompletionItem {
1387                        label: "foo(…)",
1388                        detail_left: None,
1389                        detail_right: Some(
1390                            "fn(u32, u32, T) -> (u32, T)",
1391                        ),
1392                        source_range: 68..70,
1393                        delete: 68..70,
1394                        insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
1395                        kind: SymbolKind(
1396                            Function,
1397                        ),
1398                        lookup: "foo",
1399                        detail: "fn(u32, u32, T) -> (u32, T)",
1400                        trigger_call_info: true,
1401                    },
1402                    CompletionItem {
1403                        label: "main()",
1404                        detail_left: None,
1405                        detail_right: Some(
1406                            "fn()",
1407                        ),
1408                        source_range: 68..70,
1409                        delete: 68..70,
1410                        insert: "main();$0",
1411                        kind: SymbolKind(
1412                            Function,
1413                        ),
1414                        lookup: "main",
1415                        detail: "fn()",
1416                    },
1417                ]
1418            "#]],
1419        );
1420    }
1421
1422    #[test]
1423    fn fn_detail_includes_variadics() {
1424        check(
1425            r#"
1426unsafe extern "C" fn foo(a: u32, b: u32, ...) {}
1427
1428fn main() { fo$0 }
1429"#,
1430            SymbolKind::Function,
1431            expect![[r#"
1432                [
1433                    CompletionItem {
1434                        label: "foo(…)",
1435                        detail_left: None,
1436                        detail_right: Some(
1437                            "unsafe fn(u32, u32, ...)",
1438                        ),
1439                        source_range: 62..64,
1440                        delete: 62..64,
1441                        insert: "foo(${1:a}, ${2:b});$0",
1442                        kind: SymbolKind(
1443                            Function,
1444                        ),
1445                        lookup: "foo",
1446                        detail: "unsafe fn(u32, u32, ...)",
1447                        trigger_call_info: true,
1448                    },
1449                    CompletionItem {
1450                        label: "main()",
1451                        detail_left: None,
1452                        detail_right: Some(
1453                            "fn()",
1454                        ),
1455                        source_range: 62..64,
1456                        delete: 62..64,
1457                        insert: "main();$0",
1458                        kind: SymbolKind(
1459                            Function,
1460                        ),
1461                        lookup: "main",
1462                        detail: "fn()",
1463                    },
1464                ]
1465            "#]],
1466        );
1467    }
1468
1469    #[test]
1470    fn enum_detail_just_name_for_unit() {
1471        check(
1472            r#"
1473enum Foo { Foo }
1474
1475fn main() { Foo::Fo$0 }
1476"#,
1477            SymbolKind::Variant,
1478            expect![[r#"
1479                [
1480                    CompletionItem {
1481                        label: "Foo",
1482                        detail_left: None,
1483                        detail_right: Some(
1484                            "Foo",
1485                        ),
1486                        source_range: 35..37,
1487                        delete: 35..37,
1488                        insert: "Foo$0",
1489                        kind: SymbolKind(
1490                            Variant,
1491                        ),
1492                        detail: "Foo",
1493                        relevance: CompletionRelevance {
1494                            exact_name_match: false,
1495                            type_match: None,
1496                            is_local: false,
1497                            is_missing: false,
1498                            trait_: None,
1499                            is_name_already_imported: false,
1500                            requires_import: false,
1501                            is_private_editable: false,
1502                            postfix_match: None,
1503                            function: Some(
1504                                CompletionRelevanceFn {
1505                                    has_params: false,
1506                                    has_self_param: false,
1507                                    return_type: DirectConstructor,
1508                                },
1509                            ),
1510                            is_skipping_completion: false,
1511                            has_local_inherent_impl: false,
1512                            is_deprecated: false,
1513                        },
1514                        trigger_call_info: true,
1515                    },
1516                ]
1517            "#]],
1518        );
1519    }
1520
1521    #[test]
1522    fn lookup_enums_by_two_qualifiers() {
1523        check_kinds(
1524            r#"
1525mod m {
1526    pub enum Spam { Foo, Bar(i32) }
1527}
1528fn main() { let _: m::Spam = S$0 }
1529"#,
1530            &[
1531                CompletionItemKind::SymbolKind(SymbolKind::Function),
1532                CompletionItemKind::SymbolKind(SymbolKind::Module),
1533                CompletionItemKind::SymbolKind(SymbolKind::Variant),
1534            ],
1535            expect![[r#"
1536                [
1537                    CompletionItem {
1538                        label: "main()",
1539                        detail_left: None,
1540                        detail_right: Some(
1541                            "fn()",
1542                        ),
1543                        source_range: 75..76,
1544                        delete: 75..76,
1545                        insert: "main();$0",
1546                        kind: SymbolKind(
1547                            Function,
1548                        ),
1549                        lookup: "main",
1550                        detail: "fn()",
1551                    },
1552                    CompletionItem {
1553                        label: "m::",
1554                        detail_left: None,
1555                        detail_right: None,
1556                        source_range: 75..76,
1557                        delete: 75..76,
1558                        insert: "m::",
1559                        kind: SymbolKind(
1560                            Module,
1561                        ),
1562                        lookup: "m",
1563                    },
1564                    CompletionItem {
1565                        label: "m::Spam::Bar(…)",
1566                        detail_left: None,
1567                        detail_right: Some(
1568                            "m::Spam::Bar(i32)",
1569                        ),
1570                        source_range: 75..76,
1571                        delete: 75..76,
1572                        insert: "m::Spam::Bar(${1:()})$0",
1573                        kind: SymbolKind(
1574                            Variant,
1575                        ),
1576                        lookup: "Spam::Bar()",
1577                        detail: "m::Spam::Bar(i32)",
1578                        relevance: CompletionRelevance {
1579                            exact_name_match: false,
1580                            type_match: Some(
1581                                Exact,
1582                            ),
1583                            is_local: false,
1584                            is_missing: false,
1585                            trait_: None,
1586                            is_name_already_imported: false,
1587                            requires_import: false,
1588                            is_private_editable: false,
1589                            postfix_match: None,
1590                            function: Some(
1591                                CompletionRelevanceFn {
1592                                    has_params: true,
1593                                    has_self_param: false,
1594                                    return_type: DirectConstructor,
1595                                },
1596                            ),
1597                            is_skipping_completion: false,
1598                            has_local_inherent_impl: false,
1599                            is_deprecated: false,
1600                        },
1601                        trigger_call_info: true,
1602                    },
1603                    CompletionItem {
1604                        label: "m::Spam::Foo",
1605                        detail_left: None,
1606                        detail_right: Some(
1607                            "m::Spam::Foo",
1608                        ),
1609                        source_range: 75..76,
1610                        delete: 75..76,
1611                        insert: "m::Spam::Foo$0",
1612                        kind: SymbolKind(
1613                            Variant,
1614                        ),
1615                        lookup: "Spam::Foo",
1616                        detail: "m::Spam::Foo",
1617                        relevance: CompletionRelevance {
1618                            exact_name_match: false,
1619                            type_match: Some(
1620                                Exact,
1621                            ),
1622                            is_local: false,
1623                            is_missing: false,
1624                            trait_: None,
1625                            is_name_already_imported: false,
1626                            requires_import: false,
1627                            is_private_editable: false,
1628                            postfix_match: None,
1629                            function: Some(
1630                                CompletionRelevanceFn {
1631                                    has_params: false,
1632                                    has_self_param: false,
1633                                    return_type: DirectConstructor,
1634                                },
1635                            ),
1636                            is_skipping_completion: false,
1637                            has_local_inherent_impl: false,
1638                            is_deprecated: false,
1639                        },
1640                        trigger_call_info: true,
1641                    },
1642                ]
1643            "#]],
1644        )
1645    }
1646
1647    #[test]
1648    fn sets_deprecated_flag_in_items() {
1649        check(
1650            r#"
1651#[deprecated]
1652mod something_deprecated {}
1653
1654fn main() { som$0 }
1655"#,
1656            SymbolKind::Module,
1657            expect![[r#"
1658                [
1659                    CompletionItem {
1660                        label: "something_deprecated::",
1661                        detail_left: None,
1662                        detail_right: None,
1663                        source_range: 55..58,
1664                        delete: 55..58,
1665                        insert: "something_deprecated::",
1666                        kind: SymbolKind(
1667                            Module,
1668                        ),
1669                        lookup: "something_deprecated",
1670                        deprecated: true,
1671                        relevance: CompletionRelevance {
1672                            exact_name_match: false,
1673                            type_match: None,
1674                            is_local: false,
1675                            is_missing: false,
1676                            trait_: None,
1677                            is_name_already_imported: false,
1678                            requires_import: false,
1679                            is_private_editable: false,
1680                            postfix_match: None,
1681                            function: None,
1682                            is_skipping_completion: false,
1683                            has_local_inherent_impl: false,
1684                            is_deprecated: true,
1685                        },
1686                    },
1687                ]
1688            "#]],
1689        );
1690
1691        check(
1692            r#"
1693#[deprecated]
1694fn something_deprecated() {}
1695
1696fn main() { som$0 }
1697"#,
1698            SymbolKind::Function,
1699            expect![[r#"
1700                [
1701                    CompletionItem {
1702                        label: "main()",
1703                        detail_left: None,
1704                        detail_right: Some(
1705                            "fn()",
1706                        ),
1707                        source_range: 56..59,
1708                        delete: 56..59,
1709                        insert: "main();$0",
1710                        kind: SymbolKind(
1711                            Function,
1712                        ),
1713                        lookup: "main",
1714                        detail: "fn()",
1715                    },
1716                    CompletionItem {
1717                        label: "something_deprecated()",
1718                        detail_left: None,
1719                        detail_right: Some(
1720                            "fn()",
1721                        ),
1722                        source_range: 56..59,
1723                        delete: 56..59,
1724                        insert: "something_deprecated();$0",
1725                        kind: SymbolKind(
1726                            Function,
1727                        ),
1728                        lookup: "something_deprecated",
1729                        detail: "fn()",
1730                        deprecated: true,
1731                        relevance: CompletionRelevance {
1732                            exact_name_match: false,
1733                            type_match: None,
1734                            is_local: false,
1735                            is_missing: false,
1736                            trait_: None,
1737                            is_name_already_imported: false,
1738                            requires_import: false,
1739                            is_private_editable: false,
1740                            postfix_match: None,
1741                            function: None,
1742                            is_skipping_completion: false,
1743                            has_local_inherent_impl: false,
1744                            is_deprecated: true,
1745                        },
1746                    },
1747                ]
1748            "#]],
1749        );
1750
1751        check(
1752            r#"
1753#[deprecated]
1754struct A;
1755
1756fn main() { A$0 }
1757"#,
1758            SymbolKind::Struct,
1759            expect![[r#"
1760                [
1761                    CompletionItem {
1762                        label: "A",
1763                        detail_left: None,
1764                        detail_right: Some(
1765                            "A",
1766                        ),
1767                        source_range: 37..38,
1768                        delete: 37..38,
1769                        insert: "A",
1770                        kind: SymbolKind(
1771                            Struct,
1772                        ),
1773                        detail: "A",
1774                        deprecated: true,
1775                        relevance: CompletionRelevance {
1776                            exact_name_match: false,
1777                            type_match: None,
1778                            is_local: false,
1779                            is_missing: false,
1780                            trait_: None,
1781                            is_name_already_imported: false,
1782                            requires_import: false,
1783                            is_private_editable: false,
1784                            postfix_match: None,
1785                            function: None,
1786                            is_skipping_completion: false,
1787                            has_local_inherent_impl: false,
1788                            is_deprecated: true,
1789                        },
1790                    },
1791                ]
1792            "#]],
1793        );
1794
1795        check(
1796            r#"
1797#[deprecated]
1798enum A {}
1799
1800fn main() { A$0 }
1801"#,
1802            SymbolKind::Enum,
1803            expect![[r#"
1804                [
1805                    CompletionItem {
1806                        label: "A",
1807                        detail_left: None,
1808                        detail_right: Some(
1809                            "A",
1810                        ),
1811                        source_range: 37..38,
1812                        delete: 37..38,
1813                        insert: "A",
1814                        kind: SymbolKind(
1815                            Enum,
1816                        ),
1817                        detail: "A",
1818                        deprecated: true,
1819                        relevance: CompletionRelevance {
1820                            exact_name_match: false,
1821                            type_match: None,
1822                            is_local: false,
1823                            is_missing: false,
1824                            trait_: None,
1825                            is_name_already_imported: false,
1826                            requires_import: false,
1827                            is_private_editable: false,
1828                            postfix_match: None,
1829                            function: None,
1830                            is_skipping_completion: false,
1831                            has_local_inherent_impl: false,
1832                            is_deprecated: true,
1833                        },
1834                    },
1835                ]
1836            "#]],
1837        );
1838
1839        check(
1840            r#"
1841enum A {
1842    Okay,
1843    #[deprecated]
1844    Old,
1845}
1846
1847fn main() { A::$0 }
1848"#,
1849            SymbolKind::Variant,
1850            expect![[r#"
1851                [
1852                    CompletionItem {
1853                        label: "Okay",
1854                        detail_left: None,
1855                        detail_right: Some(
1856                            "Okay",
1857                        ),
1858                        source_range: 64..64,
1859                        delete: 64..64,
1860                        insert: "Okay$0",
1861                        kind: SymbolKind(
1862                            Variant,
1863                        ),
1864                        detail: "Okay",
1865                        relevance: CompletionRelevance {
1866                            exact_name_match: false,
1867                            type_match: None,
1868                            is_local: false,
1869                            is_missing: false,
1870                            trait_: None,
1871                            is_name_already_imported: false,
1872                            requires_import: false,
1873                            is_private_editable: false,
1874                            postfix_match: None,
1875                            function: Some(
1876                                CompletionRelevanceFn {
1877                                    has_params: false,
1878                                    has_self_param: false,
1879                                    return_type: DirectConstructor,
1880                                },
1881                            ),
1882                            is_skipping_completion: false,
1883                            has_local_inherent_impl: false,
1884                            is_deprecated: false,
1885                        },
1886                        trigger_call_info: true,
1887                    },
1888                    CompletionItem {
1889                        label: "Old",
1890                        detail_left: None,
1891                        detail_right: Some(
1892                            "Old",
1893                        ),
1894                        source_range: 64..64,
1895                        delete: 64..64,
1896                        insert: "Old$0",
1897                        kind: SymbolKind(
1898                            Variant,
1899                        ),
1900                        detail: "Old",
1901                        deprecated: true,
1902                        relevance: CompletionRelevance {
1903                            exact_name_match: false,
1904                            type_match: None,
1905                            is_local: false,
1906                            is_missing: false,
1907                            trait_: None,
1908                            is_name_already_imported: false,
1909                            requires_import: false,
1910                            is_private_editable: false,
1911                            postfix_match: None,
1912                            function: Some(
1913                                CompletionRelevanceFn {
1914                                    has_params: false,
1915                                    has_self_param: false,
1916                                    return_type: DirectConstructor,
1917                                },
1918                            ),
1919                            is_skipping_completion: false,
1920                            has_local_inherent_impl: false,
1921                            is_deprecated: true,
1922                        },
1923                        trigger_call_info: true,
1924                    },
1925                ]
1926            "#]],
1927        );
1928
1929        check(
1930            r#"
1931#[deprecated]
1932const A: i32 = 0;
1933
1934fn main() { A$0 }
1935"#,
1936            SymbolKind::Const,
1937            expect![[r#"
1938                [
1939                    CompletionItem {
1940                        label: "A",
1941                        detail_left: None,
1942                        detail_right: Some(
1943                            "i32",
1944                        ),
1945                        source_range: 45..46,
1946                        delete: 45..46,
1947                        insert: "A",
1948                        kind: SymbolKind(
1949                            Const,
1950                        ),
1951                        detail: "i32",
1952                        deprecated: true,
1953                        relevance: CompletionRelevance {
1954                            exact_name_match: false,
1955                            type_match: None,
1956                            is_local: false,
1957                            is_missing: false,
1958                            trait_: None,
1959                            is_name_already_imported: false,
1960                            requires_import: false,
1961                            is_private_editable: false,
1962                            postfix_match: None,
1963                            function: None,
1964                            is_skipping_completion: false,
1965                            has_local_inherent_impl: false,
1966                            is_deprecated: true,
1967                        },
1968                    },
1969                ]
1970            "#]],
1971        );
1972
1973        check(
1974            r#"
1975#[deprecated]
1976static A: i32 = 0;
1977
1978fn main() { A$0 }
1979"#,
1980            SymbolKind::Static,
1981            expect![[r#"
1982                [
1983                    CompletionItem {
1984                        label: "A",
1985                        detail_left: None,
1986                        detail_right: Some(
1987                            "i32",
1988                        ),
1989                        source_range: 46..47,
1990                        delete: 46..47,
1991                        insert: "A",
1992                        kind: SymbolKind(
1993                            Static,
1994                        ),
1995                        detail: "i32",
1996                        deprecated: true,
1997                        relevance: CompletionRelevance {
1998                            exact_name_match: false,
1999                            type_match: None,
2000                            is_local: false,
2001                            is_missing: false,
2002                            trait_: None,
2003                            is_name_already_imported: false,
2004                            requires_import: false,
2005                            is_private_editable: false,
2006                            postfix_match: None,
2007                            function: None,
2008                            is_skipping_completion: false,
2009                            has_local_inherent_impl: false,
2010                            is_deprecated: true,
2011                        },
2012                    },
2013                ]
2014            "#]],
2015        );
2016
2017        check(
2018            r#"
2019#[deprecated]
2020trait A {}
2021
2022impl A$0
2023"#,
2024            SymbolKind::Trait,
2025            expect![[r#"
2026                [
2027                    CompletionItem {
2028                        label: "A",
2029                        detail_left: None,
2030                        detail_right: None,
2031                        source_range: 31..32,
2032                        delete: 31..32,
2033                        insert: "A",
2034                        kind: SymbolKind(
2035                            Trait,
2036                        ),
2037                        deprecated: true,
2038                        relevance: CompletionRelevance {
2039                            exact_name_match: false,
2040                            type_match: None,
2041                            is_local: false,
2042                            is_missing: false,
2043                            trait_: None,
2044                            is_name_already_imported: false,
2045                            requires_import: false,
2046                            is_private_editable: false,
2047                            postfix_match: None,
2048                            function: None,
2049                            is_skipping_completion: false,
2050                            has_local_inherent_impl: false,
2051                            is_deprecated: true,
2052                        },
2053                    },
2054                ]
2055            "#]],
2056        );
2057
2058        check(
2059            r#"
2060#[deprecated]
2061type A = i32;
2062
2063fn main() { A$0 }
2064"#,
2065            SymbolKind::TypeAlias,
2066            expect![[r#"
2067                [
2068                    CompletionItem {
2069                        label: "A",
2070                        detail_left: None,
2071                        detail_right: None,
2072                        source_range: 41..42,
2073                        delete: 41..42,
2074                        insert: "A",
2075                        kind: SymbolKind(
2076                            TypeAlias,
2077                        ),
2078                        deprecated: true,
2079                        relevance: CompletionRelevance {
2080                            exact_name_match: false,
2081                            type_match: None,
2082                            is_local: false,
2083                            is_missing: false,
2084                            trait_: None,
2085                            is_name_already_imported: false,
2086                            requires_import: false,
2087                            is_private_editable: false,
2088                            postfix_match: None,
2089                            function: None,
2090                            is_skipping_completion: false,
2091                            has_local_inherent_impl: false,
2092                            is_deprecated: true,
2093                        },
2094                    },
2095                ]
2096            "#]],
2097        );
2098
2099        check(
2100            r#"
2101#[deprecated]
2102macro_rules! a { _ => {}}
2103
2104fn main() { a$0 }
2105"#,
2106            SymbolKind::Macro,
2107            expect![[r#"
2108                [
2109                    CompletionItem {
2110                        label: "a!(…)",
2111                        detail_left: None,
2112                        detail_right: Some(
2113                            "macro_rules! a",
2114                        ),
2115                        source_range: 53..54,
2116                        delete: 53..54,
2117                        insert: "a!($0)",
2118                        kind: SymbolKind(
2119                            Macro,
2120                        ),
2121                        lookup: "a!",
2122                        detail: "macro_rules! a",
2123                        deprecated: true,
2124                        relevance: CompletionRelevance {
2125                            exact_name_match: false,
2126                            type_match: None,
2127                            is_local: false,
2128                            is_missing: false,
2129                            trait_: None,
2130                            is_name_already_imported: false,
2131                            requires_import: false,
2132                            is_private_editable: false,
2133                            postfix_match: None,
2134                            function: None,
2135                            is_skipping_completion: false,
2136                            has_local_inherent_impl: false,
2137                            is_deprecated: true,
2138                        },
2139                    },
2140                ]
2141            "#]],
2142        );
2143
2144        check(
2145            r#"
2146struct A { #[deprecated] the_field: u32 }
2147
2148fn main() { A { the$0 } }
2149"#,
2150            SymbolKind::Field,
2151            expect![[r#"
2152                [
2153                    CompletionItem {
2154                        label: "the_field",
2155                        detail_left: None,
2156                        detail_right: Some(
2157                            "u32",
2158                        ),
2159                        source_range: 59..62,
2160                        delete: 59..62,
2161                        insert: "the_field",
2162                        kind: SymbolKind(
2163                            Field,
2164                        ),
2165                        detail: "u32",
2166                        deprecated: true,
2167                        relevance: CompletionRelevance {
2168                            exact_name_match: false,
2169                            type_match: Some(
2170                                CouldUnify,
2171                            ),
2172                            is_local: false,
2173                            is_missing: false,
2174                            trait_: None,
2175                            is_name_already_imported: false,
2176                            requires_import: false,
2177                            is_private_editable: false,
2178                            postfix_match: None,
2179                            function: None,
2180                            is_skipping_completion: false,
2181                            has_local_inherent_impl: false,
2182                            is_deprecated: true,
2183                        },
2184                    },
2185                ]
2186            "#]],
2187        );
2188    }
2189
2190    #[test]
2191    fn renders_docs() {
2192        check_kinds(
2193            r#"
2194struct S {
2195    /// Field docs
2196    foo:
2197}
2198impl S {
2199    /// Method docs
2200    fn bar(self) { self.$0 }
2201}"#,
2202            &[
2203                CompletionItemKind::SymbolKind(SymbolKind::Method),
2204                CompletionItemKind::SymbolKind(SymbolKind::Field),
2205            ],
2206            expect![[r#"
2207                [
2208                    CompletionItem {
2209                        label: "bar()",
2210                        detail_left: None,
2211                        detail_right: Some(
2212                            "fn(self)",
2213                        ),
2214                        source_range: 94..94,
2215                        delete: 94..94,
2216                        insert: "bar();$0",
2217                        kind: SymbolKind(
2218                            Method,
2219                        ),
2220                        lookup: "bar",
2221                        detail: "fn(self)",
2222                        documentation: Documentation(
2223                            "Method docs",
2224                        ),
2225                        relevance: CompletionRelevance {
2226                            exact_name_match: false,
2227                            type_match: None,
2228                            is_local: false,
2229                            is_missing: false,
2230                            trait_: None,
2231                            is_name_already_imported: false,
2232                            requires_import: false,
2233                            is_private_editable: false,
2234                            postfix_match: None,
2235                            function: Some(
2236                                CompletionRelevanceFn {
2237                                    has_params: true,
2238                                    has_self_param: true,
2239                                    return_type: Other,
2240                                },
2241                            ),
2242                            is_skipping_completion: false,
2243                            has_local_inherent_impl: false,
2244                            is_deprecated: false,
2245                        },
2246                    },
2247                    CompletionItem {
2248                        label: "foo",
2249                        detail_left: None,
2250                        detail_right: Some(
2251                            "{unknown}",
2252                        ),
2253                        source_range: 94..94,
2254                        delete: 94..94,
2255                        insert: "foo",
2256                        kind: SymbolKind(
2257                            Field,
2258                        ),
2259                        detail: "{unknown}",
2260                        documentation: Documentation(
2261                            "Field docs",
2262                        ),
2263                    },
2264                ]
2265            "#]],
2266        );
2267
2268        check_kinds(
2269            r#"
2270use self::my$0;
2271
2272/// mod docs
2273mod my { }
2274
2275/// enum docs
2276enum E {
2277    /// variant docs
2278    V
2279}
2280use self::E::*;
2281"#,
2282            &[
2283                CompletionItemKind::SymbolKind(SymbolKind::Module),
2284                CompletionItemKind::SymbolKind(SymbolKind::Variant),
2285                CompletionItemKind::SymbolKind(SymbolKind::Enum),
2286            ],
2287            expect![[r#"
2288                [
2289                    CompletionItem {
2290                        label: "my",
2291                        detail_left: None,
2292                        detail_right: None,
2293                        source_range: 10..12,
2294                        delete: 10..12,
2295                        insert: "my",
2296                        kind: SymbolKind(
2297                            Module,
2298                        ),
2299                        documentation: Documentation(
2300                            "mod docs",
2301                        ),
2302                    },
2303                    CompletionItem {
2304                        label: "V",
2305                        detail_left: None,
2306                        detail_right: Some(
2307                            "V",
2308                        ),
2309                        source_range: 10..12,
2310                        delete: 10..12,
2311                        insert: "V$0",
2312                        kind: SymbolKind(
2313                            Variant,
2314                        ),
2315                        detail: "V",
2316                        documentation: Documentation(
2317                            "variant docs",
2318                        ),
2319                        relevance: CompletionRelevance {
2320                            exact_name_match: false,
2321                            type_match: None,
2322                            is_local: false,
2323                            is_missing: false,
2324                            trait_: None,
2325                            is_name_already_imported: false,
2326                            requires_import: false,
2327                            is_private_editable: false,
2328                            postfix_match: None,
2329                            function: Some(
2330                                CompletionRelevanceFn {
2331                                    has_params: false,
2332                                    has_self_param: false,
2333                                    return_type: DirectConstructor,
2334                                },
2335                            ),
2336                            is_skipping_completion: false,
2337                            has_local_inherent_impl: false,
2338                            is_deprecated: false,
2339                        },
2340                        trigger_call_info: true,
2341                    },
2342                    CompletionItem {
2343                        label: "E",
2344                        detail_left: None,
2345                        detail_right: Some(
2346                            "E",
2347                        ),
2348                        source_range: 10..12,
2349                        delete: 10..12,
2350                        insert: "E",
2351                        kind: SymbolKind(
2352                            Enum,
2353                        ),
2354                        detail: "E",
2355                        documentation: Documentation(
2356                            "enum docs",
2357                        ),
2358                    },
2359                ]
2360            "#]],
2361        )
2362    }
2363
2364    #[test]
2365    fn dont_render_attrs() {
2366        check(
2367            r#"
2368struct S;
2369impl S {
2370    #[inline]
2371    fn the_method(&self) { }
2372}
2373fn foo(s: S) { s.$0 }
2374"#,
2375            CompletionItemKind::SymbolKind(SymbolKind::Method),
2376            expect![[r#"
2377                [
2378                    CompletionItem {
2379                        label: "the_method()",
2380                        detail_left: None,
2381                        detail_right: Some(
2382                            "fn(&self)",
2383                        ),
2384                        source_range: 81..81,
2385                        delete: 81..81,
2386                        insert: "the_method();$0",
2387                        kind: SymbolKind(
2388                            Method,
2389                        ),
2390                        lookup: "the_method",
2391                        detail: "fn(&self)",
2392                        relevance: CompletionRelevance {
2393                            exact_name_match: false,
2394                            type_match: None,
2395                            is_local: false,
2396                            is_missing: false,
2397                            trait_: None,
2398                            is_name_already_imported: false,
2399                            requires_import: false,
2400                            is_private_editable: false,
2401                            postfix_match: None,
2402                            function: Some(
2403                                CompletionRelevanceFn {
2404                                    has_params: true,
2405                                    has_self_param: true,
2406                                    return_type: Other,
2407                                },
2408                            ),
2409                            is_skipping_completion: false,
2410                            has_local_inherent_impl: false,
2411                            is_deprecated: false,
2412                        },
2413                    },
2414                ]
2415            "#]],
2416        )
2417    }
2418
2419    #[test]
2420    fn no_call_parens_if_fn_ptr_needed() {
2421        cov_mark::check!(no_call_parens_if_fn_ptr_needed);
2422        check_edit(
2423            "foo",
2424            r#"
2425fn foo(foo: u8, bar: u8) {}
2426struct ManualVtable { f: fn(u8, u8) }
2427
2428fn main() -> ManualVtable {
2429    ManualVtable { f: f$0 }
2430}
2431"#,
2432            r#"
2433fn foo(foo: u8, bar: u8) {}
2434struct ManualVtable { f: fn(u8, u8) }
2435
2436fn main() -> ManualVtable {
2437    ManualVtable { f: foo }
2438}
2439"#,
2440        );
2441        check_edit(
2442            "type",
2443            r#"
2444struct RawIdentTable { r#type: u32 }
2445
2446fn main() -> RawIdentTable {
2447    RawIdentTable { t$0: 42 }
2448}
2449"#,
2450            r#"
2451struct RawIdentTable { r#type: u32 }
2452
2453fn main() -> RawIdentTable {
2454    RawIdentTable { r#type: 42 }
2455}
2456"#,
2457        );
2458    }
2459
2460    #[test]
2461    fn no_parens_in_use_item() {
2462        check_edit(
2463            "foo",
2464            r#"
2465mod m { pub fn foo() {} }
2466use crate::m::f$0;
2467"#,
2468            r#"
2469mod m { pub fn foo() {} }
2470use crate::m::foo;
2471"#,
2472        );
2473    }
2474
2475    #[test]
2476    fn no_parens_in_call() {
2477        check_edit(
2478            "foo",
2479            r#"
2480fn foo(x: i32) {}
2481fn main() { f$0(); }
2482"#,
2483            r#"
2484fn foo(x: i32) {}
2485fn main() { foo(); }
2486"#,
2487        );
2488        check_edit(
2489            "foo",
2490            r#"
2491struct Foo;
2492impl Foo { fn foo(&self){} }
2493fn f(foo: &Foo) { foo.f$0(); }
2494"#,
2495            r#"
2496struct Foo;
2497impl Foo { fn foo(&self){} }
2498fn f(foo: &Foo) { foo.foo(); }
2499"#,
2500        );
2501    }
2502
2503    #[test]
2504    fn inserts_angle_brackets_for_generics() {
2505        cov_mark::check!(inserts_angle_brackets_for_generics);
2506        check_edit(
2507            "Vec",
2508            r#"
2509struct Vec<T> {}
2510fn foo(xs: Ve$0)
2511"#,
2512            r#"
2513struct Vec<T> {}
2514fn foo(xs: Vec<$0>)
2515"#,
2516        );
2517        check_edit(
2518            "Vec",
2519            r#"
2520type Vec<T> = (T,);
2521fn foo(xs: Ve$0)
2522"#,
2523            r#"
2524type Vec<T> = (T,);
2525fn foo(xs: Vec<$0>)
2526"#,
2527        );
2528        check_edit(
2529            "Vec",
2530            r#"
2531struct Vec<T = i128> {}
2532fn foo(xs: Ve$0)
2533"#,
2534            r#"
2535struct Vec<T = i128> {}
2536fn foo(xs: Vec)
2537"#,
2538        );
2539        check_edit(
2540            "Vec",
2541            r#"
2542struct Vec<T> {}
2543fn foo(xs: Ve$0<i128>)
2544"#,
2545            r#"
2546struct Vec<T> {}
2547fn foo(xs: Vec<i128>)
2548"#,
2549        );
2550    }
2551
2552    #[test]
2553    fn active_param_relevance() {
2554        check_relevance(
2555            r#"
2556struct S { foo: i64, bar: u32, baz: u32 }
2557fn test(bar: u32) { }
2558fn foo(s: S) { test(s.$0) }
2559"#,
2560            expect![[r#"
2561                fd bar u32 [type+name]
2562                fd baz u32 [type]
2563                fd foo i64 []
2564            "#]],
2565        );
2566    }
2567
2568    #[test]
2569    fn record_field_relevances() {
2570        check_relevance(
2571            r#"
2572struct A { foo: i64, bar: u32, baz: u32 }
2573struct B { x: (), y: f32, bar: u32 }
2574fn foo(a: A) { B { bar: a.$0 }; }
2575"#,
2576            expect![[r#"
2577                fd bar u32 [type+name]
2578                fd baz u32 [type]
2579                fd foo i64 []
2580            "#]],
2581        )
2582    }
2583
2584    #[test]
2585    fn tuple_field_detail() {
2586        check(
2587            r#"
2588struct S(i32);
2589
2590fn f() -> i32 {
2591    let s = S(0);
2592    s.0$0
2593}
2594"#,
2595            SymbolKind::Field,
2596            expect![[r#"
2597                [
2598                    CompletionItem {
2599                        label: "0",
2600                        detail_left: None,
2601                        detail_right: Some(
2602                            "i32",
2603                        ),
2604                        source_range: 56..57,
2605                        delete: 56..57,
2606                        insert: "0",
2607                        kind: SymbolKind(
2608                            Field,
2609                        ),
2610                        detail: "i32",
2611                        relevance: CompletionRelevance {
2612                            exact_name_match: false,
2613                            type_match: Some(
2614                                Exact,
2615                            ),
2616                            is_local: false,
2617                            is_missing: false,
2618                            trait_: None,
2619                            is_name_already_imported: false,
2620                            requires_import: false,
2621                            is_private_editable: false,
2622                            postfix_match: None,
2623                            function: None,
2624                            is_skipping_completion: false,
2625                            has_local_inherent_impl: false,
2626                            is_deprecated: false,
2627                        },
2628                    },
2629                ]
2630            "#]],
2631        );
2632    }
2633
2634    #[test]
2635    fn record_field_and_call_relevances() {
2636        check_relevance(
2637            r#"
2638struct A { foo: i64, bar: u32, baz: u32 }
2639struct B { x: (), y: f32, bar: u32 }
2640fn f(foo: i64) {  }
2641fn foo(a: A) { B { bar: f(a.$0) }; }
2642"#,
2643            expect![[r#"
2644                fd foo i64 [type+name]
2645                fd bar u32 []
2646                fd baz u32 []
2647            "#]],
2648        );
2649        check_relevance(
2650            r#"
2651struct A { foo: i64, bar: u32, baz: u32 }
2652struct B { x: (), y: f32, bar: u32 }
2653fn f(foo: i64) {  }
2654fn foo(a: A) { f(B { bar: a.$0 }); }
2655"#,
2656            expect![[r#"
2657                fd bar u32 [type+name]
2658                fd baz u32 [type]
2659                fd foo i64 []
2660            "#]],
2661        );
2662    }
2663
2664    #[test]
2665    fn prioritize_exact_ref_match() {
2666        check_relevance(
2667            r#"
2668struct WorldSnapshot { _f: () };
2669fn go(world: &WorldSnapshot) { go(w$0) }
2670"#,
2671            expect![[r#"
2672                lc world &WorldSnapshot [type+name+local]
2673                ex world  [type]
2674                st WorldSnapshot {…} WorldSnapshot { _f: () } []
2675                st &WorldSnapshot {…} [type]
2676                st WorldSnapshot WorldSnapshot []
2677                fn go(…) fn(&WorldSnapshot) []
2678            "#]],
2679        );
2680    }
2681
2682    #[test]
2683    fn prioritize_mutable_ref_as_immutable_ref_match() {
2684        check_relevance(
2685            r#"fn foo(r: &mut i32) -> &i32 { $0 }"#,
2686            expect![[r#"
2687                lc r &mut i32 [type+local]
2688                fn foo(…) fn(&mut i32) -> &i32 [type]
2689            "#]],
2690        );
2691    }
2692
2693    #[test]
2694    fn complete_ref_match_after_keyword_prefix() {
2695        // About https://github.com/rust-lang/rust-analyzer/issues/15139
2696        check_kinds(
2697            r#"
2698fn foo(data: &i32) {}
2699fn main() {
2700    let indent = 2i32;
2701    foo(in$0)
2702}
2703"#,
2704            &[CompletionItemKind::SymbolKind(SymbolKind::Local)],
2705            expect![[r#"
2706                [
2707                    CompletionItem {
2708                        label: "indent",
2709                        detail_left: None,
2710                        detail_right: Some(
2711                            "i32",
2712                        ),
2713                        source_range: 65..67,
2714                        delete: 65..67,
2715                        insert: "indent",
2716                        kind: SymbolKind(
2717                            Local,
2718                        ),
2719                        detail: "i32",
2720                        relevance: CompletionRelevance {
2721                            exact_name_match: false,
2722                            type_match: None,
2723                            is_local: true,
2724                            is_missing: false,
2725                            trait_: None,
2726                            is_name_already_imported: false,
2727                            requires_import: false,
2728                            is_private_editable: false,
2729                            postfix_match: None,
2730                            function: None,
2731                            is_skipping_completion: false,
2732                            has_local_inherent_impl: false,
2733                            is_deprecated: false,
2734                        },
2735                        ref_match: "&@65",
2736                    },
2737                ]
2738            "#]],
2739        );
2740    }
2741
2742    #[test]
2743    fn complete_ref_match_in_macro() {
2744        check_kinds(
2745            r#"
2746macro_rules! id { ($($t:tt)*) => ($($t)*); }
2747fn foo(data: &i32) {}
2748fn main() {
2749    let indent = 2i32;
2750    id!(foo(i$0))
2751}
2752"#,
2753            &[CompletionItemKind::SymbolKind(SymbolKind::Local)],
2754            expect![[r#"
2755                [
2756                    CompletionItem {
2757                        label: "indent",
2758                        detail_left: None,
2759                        detail_right: Some(
2760                            "i32",
2761                        ),
2762                        source_range: 114..115,
2763                        delete: 114..115,
2764                        insert: "indent",
2765                        kind: SymbolKind(
2766                            Local,
2767                        ),
2768                        detail: "i32",
2769                        relevance: CompletionRelevance {
2770                            exact_name_match: false,
2771                            type_match: None,
2772                            is_local: true,
2773                            is_missing: false,
2774                            trait_: None,
2775                            is_name_already_imported: false,
2776                            requires_import: false,
2777                            is_private_editable: false,
2778                            postfix_match: None,
2779                            function: None,
2780                            is_skipping_completion: false,
2781                            has_local_inherent_impl: false,
2782                            is_deprecated: false,
2783                        },
2784                        ref_match: "&@114",
2785                    },
2786                ]
2787            "#]],
2788        );
2789
2790        check_kinds(
2791            r#"
2792macro_rules! id { ($($t:tt)*) => ($($t)*); }
2793fn foo(data: &i32) {}
2794fn indent() -> i32 { i32 }
2795fn main() {
2796    id!(foo(i$0))
2797}
2798"#,
2799            &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
2800            expect![[r#"
2801                [
2802                    CompletionItem {
2803                        label: "foo(…)",
2804                        detail_left: None,
2805                        detail_right: Some(
2806                            "fn(&i32)",
2807                        ),
2808                        source_range: 118..119,
2809                        delete: 118..119,
2810                        insert: "foo(${1:data})$0",
2811                        kind: SymbolKind(
2812                            Function,
2813                        ),
2814                        lookup: "foo",
2815                        detail: "fn(&i32)",
2816                        trigger_call_info: true,
2817                    },
2818                    CompletionItem {
2819                        label: "indent()",
2820                        detail_left: None,
2821                        detail_right: Some(
2822                            "fn() -> i32",
2823                        ),
2824                        source_range: 118..119,
2825                        delete: 118..119,
2826                        insert: "indent()$0",
2827                        kind: SymbolKind(
2828                            Function,
2829                        ),
2830                        lookup: "indent",
2831                        detail: "fn() -> i32",
2832                        ref_match: "&@118",
2833                    },
2834                    CompletionItem {
2835                        label: "main()",
2836                        detail_left: None,
2837                        detail_right: Some(
2838                            "fn()",
2839                        ),
2840                        source_range: 118..119,
2841                        delete: 118..119,
2842                        insert: "main()$0",
2843                        kind: SymbolKind(
2844                            Function,
2845                        ),
2846                        lookup: "main",
2847                        detail: "fn()",
2848                    },
2849                ]
2850            "#]],
2851        );
2852
2853        // FIXME: It is best to test `S.in` if speculative execution is implemented
2854        check_kinds(
2855            r#"
2856macro_rules! id { ($($t:tt)*) => ($($t)*); }
2857fn foo(data: &i32) {}
2858struct S;
2859impl S {fn indent(&self) -> i32 { i32 }}
2860fn main() {
2861    id!(foo(S.i$0))
2862}
2863"#,
2864            &[CompletionItemKind::SymbolKind(SymbolKind::Method)],
2865            expect![[r#"
2866                [
2867                    CompletionItem {
2868                        label: "indent()",
2869                        detail_left: None,
2870                        detail_right: Some(
2871                            "fn(&self) -> i32",
2872                        ),
2873                        source_range: 144..145,
2874                        delete: 144..145,
2875                        insert: "indent()$0",
2876                        kind: SymbolKind(
2877                            Method,
2878                        ),
2879                        lookup: "indent",
2880                        detail: "fn(&self) -> i32",
2881                        relevance: CompletionRelevance {
2882                            exact_name_match: false,
2883                            type_match: None,
2884                            is_local: false,
2885                            is_missing: false,
2886                            trait_: None,
2887                            is_name_already_imported: false,
2888                            requires_import: false,
2889                            is_private_editable: false,
2890                            postfix_match: None,
2891                            function: Some(
2892                                CompletionRelevanceFn {
2893                                    has_params: true,
2894                                    has_self_param: true,
2895                                    return_type: Other,
2896                                },
2897                            ),
2898                            is_skipping_completion: false,
2899                            has_local_inherent_impl: false,
2900                            is_deprecated: false,
2901                        },
2902                        ref_match: "&@142",
2903                    },
2904                ]
2905            "#]],
2906        );
2907
2908        check_kinds(
2909            r#"
2910macro_rules! id { ($($t:tt)*) => ($($t)*); }
2911fn foo(data: &i32) {}
2912struct S { indent: i32 }
2913fn main(s: S) {
2914    id!(foo(s.i$0))
2915}
2916"#,
2917            &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
2918            expect![[r#"
2919                [
2920                    CompletionItem {
2921                        label: "indent",
2922                        detail_left: None,
2923                        detail_right: Some(
2924                            "i32",
2925                        ),
2926                        source_range: 122..123,
2927                        delete: 122..123,
2928                        insert: "indent",
2929                        kind: SymbolKind(
2930                            Field,
2931                        ),
2932                        detail: "i32",
2933                        ref_match: "&@120",
2934                    },
2935                ]
2936            "#]],
2937        );
2938    }
2939
2940    #[test]
2941    fn too_many_arguments() {
2942        cov_mark::check!(too_many_arguments);
2943        check_relevance(
2944            r#"
2945struct Foo;
2946fn f(foo: &Foo) { f(foo, w$0) }
2947"#,
2948            expect![[r#"
2949                lc foo &Foo [local]
2950                st Foo Foo []
2951                fn f(…) fn(&Foo) []
2952            "#]],
2953        );
2954    }
2955
2956    #[test]
2957    fn score_fn_type_and_name_match() {
2958        check_relevance(
2959            r#"
2960struct A { bar: u8 }
2961fn baz() -> u8 { 0 }
2962fn bar() -> u8 { 0 }
2963fn f() { A { bar: b$0 }; }
2964"#,
2965            expect![[r#"
2966                fn bar() fn() -> u8 [type+name]
2967                ex bar()  [type]
2968                fn baz() fn() -> u8 [type]
2969                ex baz()  [type]
2970                st A A []
2971                fn f() fn() []
2972            "#]],
2973        );
2974    }
2975
2976    #[test]
2977    fn score_method_type_and_name_match() {
2978        check_relevance(
2979            r#"
2980fn baz(aaa: u32){}
2981struct Foo;
2982impl Foo {
2983fn aaa(&self) -> u32 { 0 }
2984fn bbb(&self) -> u32 { 0 }
2985fn ccc(&self) -> u64 { 0 }
2986}
2987fn f() {
2988    baz(Foo.$0
2989}
2990"#,
2991            expect![[r#"
2992                me aaa() fn(&self) -> u32 [type+name]
2993                me bbb() fn(&self) -> u32 [type]
2994                me ccc() fn(&self) -> u64 []
2995            "#]],
2996        );
2997    }
2998
2999    #[test]
3000    fn score_method_name_match_only() {
3001        check_relevance(
3002            r#"
3003fn baz(aaa: u32){}
3004struct Foo;
3005impl Foo {
3006fn aaa(&self) -> u64 { 0 }
3007}
3008fn f() {
3009    baz(Foo.$0
3010}
3011"#,
3012            expect![[r#"
3013                me aaa() fn(&self) -> u64 [name]
3014            "#]],
3015        );
3016    }
3017
3018    #[test]
3019    fn score_has_local_inherent_impl() {
3020        check_relevance(
3021            r#"
3022trait Foob {}
3023struct Fooa {}
3024impl Fooa {}
3025
3026impl Foo$0
3027"#,
3028            expect![[r#"
3029                tt Foob  []
3030                st Fooa Fooa [has_local_inherent_impl]
3031            "#]],
3032        );
3033
3034        // inherent impl in different modules, not trigger `has_local_inherent_impl`
3035        check_relevance(
3036            r#"
3037trait Foob {}
3038struct Fooa {}
3039
3040mod a {
3041    use super::*;
3042    impl Fooa {}
3043}
3044
3045mod b {
3046    use super::*;
3047    impl Foo$0
3048}
3049
3050"#,
3051            expect![[r#"
3052                st Fooa Fooa []
3053                tt Foob  []
3054                md a::  []
3055                md b::  []
3056            "#]],
3057        );
3058    }
3059
3060    #[test]
3061    fn score_patterns() {
3062        check_relevance(
3063            r#"
3064struct Foo(Bar);
3065struct Bar { field: i32 }
3066fn go(Foo($0): Foo) {}
3067"#,
3068            expect![[r#"
3069                bn Bar {…} Bar { field$1 }$0 [type]
3070                st Bar  []
3071                st Foo  []
3072                bn Foo(…) Foo($1)$0 []
3073            "#]],
3074        );
3075
3076        check_relevance(
3077            r#"
3078struct Foo(Bar);
3079enum Bar { Variant { field: i32 } }
3080fn go(foo: Foo) { match foo { Foo($0) } }
3081"#,
3082            expect![[r#"
3083                bn Bar::Variant {…} Bar::Variant { field$1 }$0 [type]
3084                en Bar  []
3085                st Foo  []
3086                bn Foo(…) Foo($1)$0 []
3087            "#]],
3088        );
3089    }
3090
3091    #[test]
3092    fn test_avoid_redundant_suggestion() {
3093        check_relevance(
3094            r#"
3095struct aa([u8]);
3096
3097impl aa {
3098    fn from_bytes(bytes: &[u8]) -> &Self {
3099        unsafe { &*(bytes as *const [u8] as *const aa) }
3100    }
3101}
3102
3103fn bb()-> &'static aa {
3104    let bytes = b"hello";
3105    aa::$0
3106}
3107"#,
3108            expect![[r#"
3109                fn from_bytes(…) fn(&[u8]) -> &aa [type_could_unify]
3110            "#]],
3111        );
3112    }
3113
3114    #[test]
3115    fn suggest_ref_mut() {
3116        cov_mark::check!(suggest_ref);
3117        check_relevance(
3118            r#"
3119struct S;
3120fn foo(s: &mut S) {}
3121fn main() {
3122    let mut s = S;
3123    foo($0);
3124}
3125            "#,
3126            expect![[r#"
3127                lc s S [name+local]
3128                lc &mut s [type+name+local]
3129                st S S []
3130                st &mut S [type]
3131                st S S []
3132                fn foo(…) fn(&mut S) []
3133                fn main() fn() []
3134            "#]],
3135        );
3136        check_relevance(
3137            r#"
3138struct S;
3139fn foo(s: &mut S) {}
3140fn main() {
3141    let mut s = S;
3142    foo(&mut $0);
3143}
3144            "#,
3145            // FIXME: There are many `S` here
3146            expect![[r#"
3147                lc s S [type+name+local]
3148                st S S [type]
3149                st S S [type]
3150                ex S  [type]
3151                ex s  [type]
3152                fn foo(…) fn(&mut S) []
3153                fn main() fn() []
3154            "#]],
3155        );
3156        check_relevance(
3157            r#"
3158struct S;
3159fn foo(s: &mut S) {}
3160fn main() {
3161    let mut ssss = S;
3162    foo(&mut s$0);
3163}
3164            "#,
3165            expect![[r#"
3166                st S S [type]
3167                lc ssss S [type+local]
3168                st S S [type]
3169                ex S  [type]
3170                ex ssss  [type]
3171                fn foo(…) fn(&mut S) []
3172                fn main() fn() []
3173            "#]],
3174        );
3175        check_relevance(
3176            r#"
3177struct S;
3178fn foo(s: &&S) {}
3179fn main() {
3180    let mut ssss = &S;
3181    foo($0);
3182}
3183            "#,
3184            expect![[r#"
3185                st S S []
3186                lc ssss &S [local]
3187                lc &ssss [type+local]
3188                st S S []
3189                fn foo(…) fn(&&S) []
3190                fn main() fn() []
3191            "#]],
3192        );
3193        check_relevance(
3194            r#"
3195struct S<T>(T);
3196fn foo<T>(s: &mut S<T>) {}
3197fn main() {
3198    let mut ssss = S(2u32);
3199    foo($0);
3200}
3201            "#,
3202            expect![[r#"
3203                st S(…) S(T) []
3204                st &mut S(…) [type]
3205                lc ssss S<u32> [local]
3206                lc &mut ssss [type+local]
3207                st S S<T> []
3208                fn foo(…) fn(&mut S<T>) []
3209                fn main() fn() []
3210            "#]],
3211        );
3212        // Regression test https://github.com/rust-lang/rust-analyzer/issues/22324
3213        check_relevance(
3214            r#"
3215//- minicore: deref
3216struct S<T>(T);
3217impl<T> core::ops::Deref for S<T> {
3218    type Target = T;
3219}
3220fn foo<T>(s: &u32) {}
3221fn main() {
3222    let ssss = S();
3223    foo($0);
3224}
3225            "#,
3226            // FIXME: term_search exclude ssss.0 (field.ty().is_unknown())
3227            expect![[r#"
3228                ex ssss.0  [type_could_unify]
3229                lc ssss S<{unknown}> [local]
3230                st S S<T> []
3231                md core::  []
3232                fn foo(…) fn(&u32) []
3233                fn main() fn() []
3234            "#]],
3235        );
3236        check_relevance(
3237            r#"
3238//- minicore: deref
3239fn foo<T>(s: &T) {}
3240fn main() {
3241    let ssss = &mut 2i32;
3242    foo($0);
3243}
3244            "#,
3245            expect![[r#"
3246                lc ssss &mut i32 [type_could_unify+local]
3247                md core::  []
3248                fn foo(…) fn(&T) []
3249                fn main() fn() []
3250            "#]],
3251        );
3252    }
3253
3254    #[test]
3255    fn suggest_deref_copy() {
3256        cov_mark::check!(suggest_deref);
3257        check_relevance(
3258            r#"
3259//- minicore: copy
3260struct Foo;
3261
3262impl Copy for Foo {}
3263impl Clone for Foo {
3264    fn clone(&self) -> Self { *self }
3265}
3266
3267fn bar(x: Foo) {}
3268
3269fn main() {
3270    let foo = &Foo;
3271    bar($0);
3272}
3273"#,
3274            expect![[r#"
3275                st Foo Foo [type]
3276                st Foo Foo [type]
3277                ex Foo  [type]
3278                lc foo &Foo [local]
3279                lc *foo [type+local]
3280                tt Clone  []
3281                tt Copy  []
3282                fn bar(…) fn(Foo) []
3283                md core::  []
3284                fn main() fn() []
3285            "#]],
3286        );
3287    }
3288
3289    #[test]
3290    fn suggest_deref_trait() {
3291        check_relevance(
3292            r#"
3293//- minicore: deref
3294struct S;
3295struct T(S);
3296
3297impl core::ops::Deref for T {
3298    type Target = S;
3299
3300    fn deref(&self) -> &Self::Target {
3301        &self.0
3302    }
3303}
3304
3305fn foo(s: &S) {}
3306
3307fn main() {
3308    let t = T(S);
3309    let m = 123;
3310
3311    foo($0);
3312}
3313            "#,
3314            expect![[r#"
3315                st S S []
3316                st &S [type]
3317                ex core::ops::Deref::deref(&t)  [type_could_unify]
3318                lc m i32 [local]
3319                lc t T [local]
3320                lc &t [type+local]
3321                st S S []
3322                st T T []
3323                md core::  []
3324                fn foo(…) fn(&S) []
3325                fn main() fn() []
3326            "#]],
3327        )
3328    }
3329
3330    #[test]
3331    fn suggest_deref_mut() {
3332        check_relevance(
3333            r#"
3334//- minicore: deref_mut
3335struct S;
3336struct T(S);
3337
3338impl core::ops::Deref for T {
3339    type Target = S;
3340
3341    fn deref(&self) -> &Self::Target {
3342        &self.0
3343    }
3344}
3345
3346impl core::ops::DerefMut for T {
3347    fn deref_mut(&mut self) -> &mut Self::Target {
3348        &mut self.0
3349    }
3350}
3351
3352fn foo(s: &mut S) {}
3353
3354fn main() {
3355    let t = T(S);
3356    let m = 123;
3357
3358    foo($0);
3359}
3360            "#,
3361            expect![[r#"
3362                st S S []
3363                st &mut S [type]
3364                ex core::ops::DerefMut::deref_mut(&mut t)  [type_could_unify]
3365                lc m i32 [local]
3366                lc t T [local]
3367                lc &mut t [type+local]
3368                st S S []
3369                st T T []
3370                md core::  []
3371                fn foo(…) fn(&mut S) []
3372                fn main() fn() []
3373            "#]],
3374        )
3375    }
3376
3377    #[test]
3378    fn locals() {
3379        check_relevance(
3380            r#"
3381fn foo(bar: u32) {
3382    let baz = 0;
3383
3384    f$0
3385}
3386"#,
3387            expect![[r#"
3388                lc bar u32 [local]
3389                lc baz i32 [local]
3390                fn foo(…) fn(u32) []
3391            "#]],
3392        );
3393    }
3394
3395    #[test]
3396    fn enum_owned() {
3397        check_relevance(
3398            r#"
3399enum Foo { A, B }
3400fn foo() {
3401    bar($0);
3402}
3403fn bar(t: Foo) {}
3404"#,
3405            expect![[r#"
3406                ev Foo::A Foo::A [type]
3407                ev Foo::B Foo::B [type]
3408                en Foo Foo [type]
3409                ex Foo::A  [type]
3410                ex Foo::B  [type]
3411                fn bar(…) fn(Foo) []
3412                fn foo() fn() []
3413            "#]],
3414        );
3415    }
3416
3417    #[test]
3418    fn enum_ref() {
3419        check_relevance(
3420            r#"
3421enum Foo { A, B }
3422fn foo() {
3423    bar($0);
3424}
3425fn bar(t: &Foo) {}
3426"#,
3427            expect![[r#"
3428                ev Foo::A Foo::A []
3429                ev &Foo::A [type]
3430                ev Foo::B Foo::B []
3431                ev &Foo::B [type]
3432                en Foo Foo []
3433                fn bar(…) fn(&Foo) []
3434                fn foo() fn() []
3435            "#]],
3436        );
3437    }
3438
3439    #[test]
3440    fn suggest_deref_fn_ret() {
3441        check_relevance(
3442            r#"
3443//- minicore: deref
3444struct S;
3445struct T(S);
3446
3447impl core::ops::Deref for T {
3448    type Target = S;
3449
3450    fn deref(&self) -> &Self::Target {
3451        &self.0
3452    }
3453}
3454
3455fn foo(s: &S) {}
3456fn bar() -> T {}
3457
3458fn main() {
3459    foo($0);
3460}
3461"#,
3462            expect![[r#"
3463                st S S []
3464                st &S [type]
3465                ex core::ops::Deref::deref(&bar())  [type_could_unify]
3466                st S S []
3467                st T T []
3468                fn bar() fn() -> T []
3469                fn &bar() [type]
3470                md core::  []
3471                fn foo(…) fn(&S) []
3472                fn main() fn() []
3473            "#]],
3474        )
3475    }
3476
3477    #[test]
3478    fn op_function_relevances() {
3479        check_relevance(
3480            r#"
3481#[lang = "sub"]
3482trait Sub {
3483    fn sub(self, other: Self) -> Self { self }
3484}
3485impl Sub for u32 {}
3486fn foo(a: u32) { a.$0 }
3487"#,
3488            expect![[r#"
3489                me sub(…) fn(self, Self) -> Self [op_method]
3490            "#]],
3491        );
3492        check_relevance(
3493            r#"
3494struct Foo;
3495impl Foo {
3496    fn new() -> Self {}
3497}
3498#[lang = "eq"]
3499pub trait PartialEq<Rhs: ?Sized = Self> {
3500    fn eq(&self, other: &Rhs) -> bool;
3501    fn ne(&self, other: &Rhs) -> bool;
3502}
3503
3504impl PartialEq for Foo {}
3505fn main() {
3506    Foo::$0
3507}
3508"#,
3509            expect![[r#"
3510                fn new() fn() -> Foo []
3511                me eq(…) fn(&self, &Rhs) -> bool [op_method]
3512                me ne(…) fn(&self, &Rhs) -> bool [op_method]
3513            "#]],
3514        );
3515    }
3516
3517    #[test]
3518    fn constructor_order_simple() {
3519        check_relevance(
3520            r#"
3521struct Foo;
3522struct Other;
3523struct Option<T>(T);
3524
3525impl Foo {
3526    fn fn_ctr() -> Foo { unimplemented!() }
3527    fn fn_another(n: u32) -> Other { unimplemented!() }
3528    fn fn_ctr_self() -> Option<Self> { unimplemented!() }
3529}
3530
3531fn test() {
3532    let a = Foo::$0;
3533}
3534"#,
3535            expect![[r#"
3536                fn fn_ctr() fn() -> Foo [type_could_unify]
3537                fn fn_ctr_self() fn() -> Option<Foo> [type_could_unify]
3538                fn fn_another(…) fn(u32) -> Other [type_could_unify]
3539            "#]],
3540        );
3541    }
3542
3543    #[test]
3544    fn constructor_order_kind() {
3545        check_function_relevance(
3546            r#"
3547struct Foo;
3548struct Bar;
3549struct Option<T>(T);
3550enum Result<T, E> { Ok(T), Err(E) };
3551
3552impl Foo {
3553    fn fn_ctr(&self) -> Foo { unimplemented!() }
3554    fn fn_ctr_with_args(&self, n: u32) -> Foo { unimplemented!() }
3555    fn fn_another(&self, n: u32) -> Bar { unimplemented!() }
3556    fn fn_ctr_wrapped(&self, ) -> Option<Self> { unimplemented!() }
3557    fn fn_ctr_wrapped_2(&self, ) -> Result<Self, Bar> { unimplemented!() }
3558    fn fn_ctr_wrapped_3(&self, ) -> Result<Bar, Self> { unimplemented!() } // Self is not the first type
3559    fn fn_ctr_wrapped_with_args(&self, m: u32) -> Option<Self> { unimplemented!() }
3560    fn fn_another_unit(&self) { unimplemented!() }
3561}
3562
3563fn test() {
3564    let a = self::Foo::$0;
3565}
3566"#,
3567            expect![[r#"
3568                [
3569                    (
3570                        "fn(&self, u32) -> Bar",
3571                        Some(
3572                            CompletionRelevanceFn {
3573                                has_params: true,
3574                                has_self_param: true,
3575                                return_type: Other,
3576                            },
3577                        ),
3578                    ),
3579                    (
3580                        "fn(&self)",
3581                        Some(
3582                            CompletionRelevanceFn {
3583                                has_params: true,
3584                                has_self_param: true,
3585                                return_type: Other,
3586                            },
3587                        ),
3588                    ),
3589                    (
3590                        "fn(&self) -> Foo",
3591                        Some(
3592                            CompletionRelevanceFn {
3593                                has_params: true,
3594                                has_self_param: true,
3595                                return_type: DirectConstructor,
3596                            },
3597                        ),
3598                    ),
3599                    (
3600                        "fn(&self, u32) -> Foo",
3601                        Some(
3602                            CompletionRelevanceFn {
3603                                has_params: true,
3604                                has_self_param: true,
3605                                return_type: DirectConstructor,
3606                            },
3607                        ),
3608                    ),
3609                    (
3610                        "fn(&self) -> Option<Foo>",
3611                        Some(
3612                            CompletionRelevanceFn {
3613                                has_params: true,
3614                                has_self_param: true,
3615                                return_type: Constructor,
3616                            },
3617                        ),
3618                    ),
3619                    (
3620                        "fn(&self) -> Result<Foo, Bar>",
3621                        Some(
3622                            CompletionRelevanceFn {
3623                                has_params: true,
3624                                has_self_param: true,
3625                                return_type: Constructor,
3626                            },
3627                        ),
3628                    ),
3629                    (
3630                        "fn(&self) -> Result<Bar, Foo>",
3631                        Some(
3632                            CompletionRelevanceFn {
3633                                has_params: true,
3634                                has_self_param: true,
3635                                return_type: Constructor,
3636                            },
3637                        ),
3638                    ),
3639                    (
3640                        "fn(&self, u32) -> Option<Foo>",
3641                        Some(
3642                            CompletionRelevanceFn {
3643                                has_params: true,
3644                                has_self_param: true,
3645                                return_type: Constructor,
3646                            },
3647                        ),
3648                    ),
3649                ]
3650            "#]],
3651        );
3652    }
3653
3654    #[test]
3655    fn constructor_order_relevance() {
3656        check_relevance(
3657            r#"
3658struct Foo;
3659struct FooBuilder;
3660struct Result<T>(T);
3661
3662impl Foo {
3663    fn fn_no_ret(&self) {}
3664    fn fn_ctr_with_args(input: u32) -> Foo { unimplemented!() }
3665    fn fn_direct_ctr() -> Self { unimplemented!() }
3666    fn fn_ctr() -> Result<Self> { unimplemented!() }
3667    fn fn_other() -> Result<u32> { unimplemented!() }
3668    fn fn_builder() -> FooBuilder { unimplemented!() }
3669}
3670
3671fn test() {
3672    let a = self::Foo::$0;
3673}
3674"#,
3675            // preference:
3676            // Direct Constructor
3677            // Direct Constructor with args
3678            // Builder
3679            // Constructor
3680            // Others
3681            expect![[r#"
3682                fn fn_direct_ctr() fn() -> Foo [type_could_unify]
3683                fn fn_ctr_with_args(…) fn(u32) -> Foo [type_could_unify]
3684                fn fn_builder() fn() -> FooBuilder [type_could_unify]
3685                fn fn_ctr() fn() -> Result<Foo> [type_could_unify]
3686                me fn_no_ret(…) fn(&self) [type_could_unify]
3687                fn fn_other() fn() -> Result<u32> [type_could_unify]
3688            "#]],
3689        );
3690
3691        //
3692    }
3693
3694    #[test]
3695    fn function_relevance_generic_1() {
3696        check_relevance(
3697            r#"
3698struct Foo<T: Default>(T);
3699struct FooBuilder;
3700struct Option<T>(T);
3701enum Result<T, E>{Ok(T), Err(E)};
3702
3703impl<T: Default> Foo<T> {
3704    fn fn_returns_unit(&self) {}
3705    fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
3706    fn fn_direct_ctr() -> Self { unimplemented!() }
3707    fn fn_ctr_wrapped() -> Option<Self> { unimplemented!() }
3708    fn fn_ctr_wrapped_2() -> Result<Self, u32> { unimplemented!() }
3709    fn fn_other() -> Option<u32> { unimplemented!() }
3710    fn fn_builder() -> FooBuilder { unimplemented!() }
3711}
3712
3713fn test() {
3714    let a = self::Foo::<u32>::$0;
3715}
3716                "#,
3717            expect![[r#"
3718                fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
3719                fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
3720                fn fn_builder() fn() -> FooBuilder [type_could_unify]
3721                fn fn_ctr_wrapped() fn() -> Option<Foo<T>> [type_could_unify]
3722                fn fn_ctr_wrapped_2() fn() -> Result<Foo<T>, u32> [type_could_unify]
3723                fn fn_other() fn() -> Option<u32> [type_could_unify]
3724                me fn_returns_unit(…) fn(&self) [type_could_unify]
3725            "#]],
3726        );
3727    }
3728
3729    #[test]
3730    fn function_relevance_generic_2() {
3731        // Generic 2
3732        check_relevance(
3733            r#"
3734struct Foo<T: Default>(T);
3735struct FooBuilder;
3736struct Option<T>(T);
3737enum Result<T, E>{Ok(T), Err(E)};
3738
3739impl<T: Default> Foo<T> {
3740    fn fn_no_ret(&self) {}
3741    fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
3742    fn fn_direct_ctr() -> Self { unimplemented!() }
3743    fn fn_ctr() -> Option<Self> { unimplemented!() }
3744    fn fn_ctr2() -> Result<Self, u32> { unimplemented!() }
3745    fn fn_other() -> Option<u32> { unimplemented!() }
3746    fn fn_builder() -> FooBuilder { unimplemented!() }
3747}
3748
3749fn test() {
3750    let a : Res<Foo<u32>> = Foo::$0;
3751}
3752                "#,
3753            expect![[r#"
3754                fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
3755                fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
3756                fn fn_builder() fn() -> FooBuilder [type_could_unify]
3757                fn fn_ctr() fn() -> Option<Foo<T>> [type_could_unify]
3758                fn fn_ctr2() fn() -> Result<Foo<T>, u32> [type_could_unify]
3759                me fn_no_ret(…) fn(&self) [type_could_unify]
3760                fn fn_other() fn() -> Option<u32> [type_could_unify]
3761            "#]],
3762        );
3763    }
3764
3765    #[test]
3766    fn struct_field_method_ref() {
3767        check_kinds(
3768            r#"
3769struct Foo { bar: u32, qux: fn() }
3770impl Foo { fn baz(&self) -> u32 { 0 } }
3771
3772fn foo(f: Foo) { let _: &u32 = f.b$0 }
3773"#,
3774            &[
3775                CompletionItemKind::SymbolKind(SymbolKind::Method),
3776                CompletionItemKind::SymbolKind(SymbolKind::Field),
3777            ],
3778            expect![[r#"
3779                [
3780                    CompletionItem {
3781                        label: "baz()",
3782                        detail_left: None,
3783                        detail_right: Some(
3784                            "fn(&self) -> u32",
3785                        ),
3786                        source_range: 109..110,
3787                        delete: 109..110,
3788                        insert: "baz()$0",
3789                        kind: SymbolKind(
3790                            Method,
3791                        ),
3792                        lookup: "baz",
3793                        detail: "fn(&self) -> u32",
3794                        relevance: CompletionRelevance {
3795                            exact_name_match: false,
3796                            type_match: None,
3797                            is_local: false,
3798                            is_missing: false,
3799                            trait_: None,
3800                            is_name_already_imported: false,
3801                            requires_import: false,
3802                            is_private_editable: false,
3803                            postfix_match: None,
3804                            function: Some(
3805                                CompletionRelevanceFn {
3806                                    has_params: true,
3807                                    has_self_param: true,
3808                                    return_type: Other,
3809                                },
3810                            ),
3811                            is_skipping_completion: false,
3812                            has_local_inherent_impl: false,
3813                            is_deprecated: false,
3814                        },
3815                        ref_match: "&@107",
3816                    },
3817                    CompletionItem {
3818                        label: "bar",
3819                        detail_left: None,
3820                        detail_right: Some(
3821                            "u32",
3822                        ),
3823                        source_range: 109..110,
3824                        delete: 109..110,
3825                        insert: "bar",
3826                        kind: SymbolKind(
3827                            Field,
3828                        ),
3829                        detail: "u32",
3830                        ref_match: "&@107",
3831                    },
3832                    CompletionItem {
3833                        label: "qux",
3834                        detail_left: None,
3835                        detail_right: Some(
3836                            "fn()",
3837                        ),
3838                        source_range: 109..110,
3839                        text_edit: TextEdit {
3840                            indels: [
3841                                Indel {
3842                                    insert: "(",
3843                                    delete: 107..107,
3844                                },
3845                                Indel {
3846                                    insert: "qux)()",
3847                                    delete: 109..110,
3848                                },
3849                            ],
3850                            annotation: None,
3851                        },
3852                        kind: SymbolKind(
3853                            Field,
3854                        ),
3855                        detail: "fn()",
3856                    },
3857                ]
3858            "#]],
3859        );
3860    }
3861
3862    #[test]
3863    fn expected_fn_type_ref() {
3864        check_kinds(
3865            r#"
3866struct S { field: fn() }
3867
3868fn foo() {
3869    let foo: fn() = S { fields: || {}}.fi$0;
3870}
3871"#,
3872            &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
3873            expect![[r#"
3874                [
3875                    CompletionItem {
3876                        label: "field",
3877                        detail_left: None,
3878                        detail_right: Some(
3879                            "fn()",
3880                        ),
3881                        source_range: 76..78,
3882                        delete: 76..78,
3883                        insert: "field",
3884                        kind: SymbolKind(
3885                            Field,
3886                        ),
3887                        detail: "fn()",
3888                        relevance: CompletionRelevance {
3889                            exact_name_match: false,
3890                            type_match: Some(
3891                                Exact,
3892                            ),
3893                            is_local: false,
3894                            is_missing: false,
3895                            trait_: None,
3896                            is_name_already_imported: false,
3897                            requires_import: false,
3898                            is_private_editable: false,
3899                            postfix_match: None,
3900                            function: None,
3901                            is_skipping_completion: false,
3902                            has_local_inherent_impl: false,
3903                            is_deprecated: false,
3904                        },
3905                    },
3906                ]
3907            "#]],
3908        )
3909    }
3910
3911    #[test]
3912    fn qualified_path_ref() {
3913        check_kinds(
3914            r#"
3915struct S;
3916
3917struct T;
3918impl T {
3919    fn foo() -> S {}
3920}
3921
3922fn bar(s: &S) {}
3923
3924fn main() {
3925    bar(T::$0);
3926}
3927"#,
3928            &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
3929            expect![[r#"
3930                [
3931                    CompletionItem {
3932                        label: "foo()",
3933                        detail_left: None,
3934                        detail_right: Some(
3935                            "fn() -> S",
3936                        ),
3937                        source_range: 95..95,
3938                        delete: 95..95,
3939                        insert: "foo()$0",
3940                        kind: SymbolKind(
3941                            Function,
3942                        ),
3943                        lookup: "foo",
3944                        detail: "fn() -> S",
3945                        relevance: CompletionRelevance {
3946                            exact_name_match: false,
3947                            type_match: None,
3948                            is_local: false,
3949                            is_missing: false,
3950                            trait_: None,
3951                            is_name_already_imported: false,
3952                            requires_import: false,
3953                            is_private_editable: false,
3954                            postfix_match: None,
3955                            function: Some(
3956                                CompletionRelevanceFn {
3957                                    has_params: false,
3958                                    has_self_param: false,
3959                                    return_type: Other,
3960                                },
3961                            ),
3962                            is_skipping_completion: false,
3963                            has_local_inherent_impl: false,
3964                            is_deprecated: false,
3965                        },
3966                        ref_match: "&@92",
3967                    },
3968                ]
3969            "#]],
3970        );
3971    }
3972
3973    #[test]
3974    fn generic_enum() {
3975        check_relevance(
3976            r#"
3977enum Foo<T> { A(T), B }
3978// bar() should not be an exact type match
3979// because the generic parameters are different
3980fn bar() -> Foo<u8> { Foo::B }
3981// FIXME baz() should be an exact type match
3982// because the types could unify, but it currently
3983// is not. This is due to the T here being
3984// TyKind::Placeholder rather than TyKind::Missing.
3985fn baz<T>() -> Foo<T> { Foo::B }
3986fn foo() {
3987    let foo: Foo<u32> = Foo::B;
3988    let _: Foo<u32> = f$0;
3989}
3990"#,
3991            expect![[r#"
3992                lc foo Foo<u32> [type+local]
3993                ex Foo::B  [type]
3994                ex foo  [type]
3995                ev Foo::B Foo::B [type_could_unify]
3996                ev Foo::A(…) Foo::A(T) [type_could_unify]
3997                en Foo Foo<T> [type_could_unify]
3998                fn baz() fn() -> Foo<T> [type_could_unify]
3999                fn bar() fn() -> Foo<u8> []
4000                fn foo() fn() []
4001            "#]],
4002        );
4003    }
4004
4005    #[test]
4006    fn postfix_exact_match_is_high_priority() {
4007        cov_mark::check!(postfix_exact_match_is_high_priority);
4008        check_relevance_for_kinds(
4009            r#"
4010mod ops {
4011    pub trait Not {
4012        type Output;
4013        fn not(self) -> Self::Output;
4014    }
4015
4016    impl Not for bool {
4017        type Output = bool;
4018        fn not(self) -> bool { if self { false } else { true }}
4019    }
4020}
4021
4022fn main() {
4023    let _: bool = (9 > 2).not$0;
4024}
4025    "#,
4026            &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
4027            expect![[r#"
4028                sn not !expr [snippet]
4029                me not() fn(self) -> <Self as Not>::Output [type_could_unify+requires_import]
4030                sn box Box::new(expr) []
4031                sn call function(expr) []
4032                sn const const {} []
4033                sn dbg dbg!(expr) []
4034                sn dbgr dbg!(&expr) []
4035                sn deref *expr []
4036                sn if if expr {} []
4037                sn match match expr {} []
4038                sn ref &expr []
4039                sn refm &mut expr []
4040                sn return return expr []
4041                sn unsafe unsafe {} []
4042                sn while while expr {} []
4043            "#]],
4044        );
4045    }
4046
4047    #[test]
4048    fn enum_variant_name_exact_match_is_high_priority() {
4049        check_relevance(
4050            r#"
4051struct Other;
4052struct String;
4053enum Foo {
4054    String($0)
4055}
4056    "#,
4057            expect![[r#"
4058                st String String [name]
4059                en Foo Foo []
4060                st Other Other []
4061                sp Self Foo []
4062            "#]],
4063        );
4064
4065        check_relevance(
4066            r#"
4067struct Other;
4068struct String;
4069enum Foo {
4070    String(String, $0)
4071}
4072    "#,
4073            expect![[r#"
4074                en Foo Foo []
4075                st Other Other []
4076                sp Self Foo []
4077                st String String []
4078            "#]],
4079        );
4080
4081        check_relevance(
4082            r#"
4083struct Other;
4084struct Vec<T>(T);
4085enum Foo {
4086    Vec(Vec<$0>)
4087}
4088    "#,
4089            expect![[r#"
4090                en Foo Foo []
4091                st Other Other []
4092                sp Self Foo []
4093                st Vec<…> Vec<T> []
4094            "#]],
4095        );
4096    }
4097
4098    #[test]
4099    fn postfix_inexact_match_is_low_priority() {
4100        cov_mark::check!(postfix_inexact_match_is_low_priority);
4101        check_relevance_for_kinds(
4102            r#"
4103struct S;
4104impl S {
4105    fn f(&self) {}
4106}
4107fn main() {
4108    S.$0
4109}
4110    "#,
4111            &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
4112            expect![[r#"
4113                me f() fn(&self) []
4114                sn box Box::new(expr) []
4115                sn call function(expr) []
4116                sn const const {} []
4117                sn dbg dbg!(expr) []
4118                sn dbgr dbg!(&expr) []
4119                sn deref *expr []
4120                sn let let []
4121                sn letm let mut []
4122                sn match match expr {} []
4123                sn ref &expr []
4124                sn refm &mut expr []
4125                sn return return expr []
4126                sn unsafe unsafe {} []
4127            "#]],
4128        );
4129    }
4130
4131    #[test]
4132    fn flyimport_reduced_relevance() {
4133        check_relevance(
4134            r#"
4135mod std {
4136    pub mod io {
4137        pub trait BufRead {}
4138        pub struct BufReader;
4139        pub struct BufWriter;
4140    }
4141}
4142struct Buffer;
4143
4144fn f() {
4145    Buf$0
4146}
4147"#,
4148            expect![[r#"
4149                st Buffer Buffer []
4150                fn f() fn() []
4151                md std::  []
4152                tt BufRead  [requires_import]
4153                st BufReader BufReader [requires_import]
4154                st BufWriter BufWriter [requires_import]
4155            "#]],
4156        );
4157    }
4158
4159    #[test]
4160    /// Issue: https://github.com/rust-lang/rust-analyzer/issues/18554
4161    fn float_consts_relevance() {
4162        check_relevance(
4163            r#"
4164//- minicore: float_consts
4165fn main() {
4166    let x = f32::INF$0
4167}
4168"#,
4169            expect![[r#"
4170                ct INFINITY pub const INFINITY: f32 []
4171                ct NEG_INFINITY pub const NEG_INFINITY: f32 []
4172                ct INFINITY f32 [type_could_unify+requires_import+deprecated]
4173                ct NEG_INFINITY f32 [type_could_unify+requires_import+deprecated]
4174            "#]],
4175        );
4176    }
4177
4178    #[test]
4179    fn completes_struct_with_raw_identifier() {
4180        check_edit(
4181            "type",
4182            r#"
4183mod m { pub struct r#type {} }
4184fn main() {
4185    let r#type = m::t$0;
4186}
4187"#,
4188            r#"
4189mod m { pub struct r#type {} }
4190fn main() {
4191    let r#type = m::r#type;
4192}
4193"#,
4194        )
4195    }
4196
4197    #[test]
4198    fn completes_fn_with_raw_identifier() {
4199        check_edit(
4200            "type",
4201            r#"
4202mod m { pub fn r#type {} }
4203fn main() {
4204    m::t$0
4205}
4206"#,
4207            r#"
4208mod m { pub fn r#type {} }
4209fn main() {
4210    m::r#type();$0
4211}
4212"#,
4213        )
4214    }
4215
4216    #[test]
4217    fn completes_macro_with_raw_identifier() {
4218        check_edit(
4219            "let!",
4220            r#"
4221macro_rules! r#let { () => {} }
4222fn main() {
4223    $0
4224}
4225"#,
4226            r#"
4227macro_rules! r#let { () => {} }
4228fn main() {
4229    r#let!($0)
4230}
4231"#,
4232        )
4233    }
4234
4235    #[test]
4236    fn completes_variant_with_raw_identifier() {
4237        check_edit(
4238            "type",
4239            r#"
4240enum A { r#type }
4241fn main() {
4242    let a = A::t$0
4243}
4244"#,
4245            r#"
4246enum A { r#type }
4247fn main() {
4248    let a = A::r#type$0
4249}
4250"#,
4251        )
4252    }
4253
4254    #[test]
4255    fn completes_field_with_raw_identifier() {
4256        check_edit(
4257            "fn",
4258            r#"
4259mod r#type {
4260    pub struct r#struct {
4261        pub r#fn: u32
4262    }
4263}
4264
4265fn main() {
4266    let a = r#type::r#struct {};
4267    a.$0
4268}
4269"#,
4270            r#"
4271mod r#type {
4272    pub struct r#struct {
4273        pub r#fn: u32
4274    }
4275}
4276
4277fn main() {
4278    let a = r#type::r#struct {};
4279    a.r#fn
4280}
4281"#,
4282        )
4283    }
4284
4285    #[test]
4286    fn completes_const_with_raw_identifier() {
4287        check_edit(
4288            "type",
4289            r#"
4290struct r#struct {}
4291impl r#struct { pub const r#type: u8 = 1; }
4292fn main() {
4293    r#struct::t$0
4294}
4295"#,
4296            r#"
4297struct r#struct {}
4298impl r#struct { pub const r#type: u8 = 1; }
4299fn main() {
4300    r#struct::r#type
4301}
4302"#,
4303        )
4304    }
4305
4306    #[test]
4307    fn completes_type_alias_with_raw_identifier() {
4308        check_edit(
4309            "type type",
4310            r#"
4311struct r#struct {}
4312trait r#trait { type r#type; }
4313impl r#trait for r#struct { type t$0 }
4314"#,
4315            r#"
4316struct r#struct {}
4317trait r#trait { type r#type; }
4318impl r#trait for r#struct { type r#type = $0; }
4319"#,
4320        )
4321    }
4322
4323    #[test]
4324    fn field_access_includes_self() {
4325        check_edit(
4326            "length",
4327            r#"
4328struct S {
4329    length: i32
4330}
4331
4332impl S {
4333    fn some_fn(&self) {
4334        let l = len$0
4335    }
4336}
4337"#,
4338            r#"
4339struct S {
4340    length: i32
4341}
4342
4343impl S {
4344    fn some_fn(&self) {
4345        let l = self.length
4346    }
4347}
4348"#,
4349        )
4350    }
4351
4352    #[test]
4353    fn field_access_includes_closure_this_param() {
4354        check_edit(
4355            "length",
4356            r#"
4357//- minicore: fn
4358struct S {
4359    length: i32
4360}
4361
4362impl S {
4363    fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
4364        self.length += 1;
4365        f(self, 3);
4366        self.length -= 1;
4367    }
4368
4369    fn some_fn(&mut self) {
4370        self.pack(|this, n| len$0);
4371    }
4372}
4373"#,
4374            r#"
4375struct S {
4376    length: i32
4377}
4378
4379impl S {
4380    fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
4381        self.length += 1;
4382        f(self, 3);
4383        self.length -= 1;
4384    }
4385
4386    fn some_fn(&mut self) {
4387        self.pack(|this, n| this.length);
4388    }
4389}
4390"#,
4391        )
4392    }
4393
4394    #[test]
4395    fn notable_traits_method_relevance() {
4396        check_kinds(
4397            r#"
4398#[doc(notable_trait)]
4399trait Write {
4400    fn write(&self);
4401    fn flush(&self);
4402}
4403
4404struct Writer;
4405
4406impl Write for Writer {
4407    fn write(&self) {}
4408    fn flush(&self) {}
4409}
4410
4411fn main() {
4412    Writer.$0
4413}
4414"#,
4415            &[
4416                CompletionItemKind::SymbolKind(SymbolKind::Method),
4417                CompletionItemKind::SymbolKind(SymbolKind::Field),
4418                CompletionItemKind::SymbolKind(SymbolKind::Function),
4419            ],
4420            expect![[r#"
4421                [
4422                    CompletionItem {
4423                        label: "flush()",
4424                        detail_left: Some(
4425                            "(as Write)",
4426                        ),
4427                        detail_right: Some(
4428                            "fn(&self)",
4429                        ),
4430                        source_range: 193..193,
4431                        delete: 193..193,
4432                        insert: "flush();$0",
4433                        kind: SymbolKind(
4434                            Method,
4435                        ),
4436                        lookup: "flush",
4437                        detail: "fn(&self)",
4438                        relevance: CompletionRelevance {
4439                            exact_name_match: false,
4440                            type_match: None,
4441                            is_local: false,
4442                            is_missing: false,
4443                            trait_: Some(
4444                                CompletionRelevanceTraitInfo {
4445                                    notable_trait: true,
4446                                    is_op_method: false,
4447                                },
4448                            ),
4449                            is_name_already_imported: false,
4450                            requires_import: false,
4451                            is_private_editable: false,
4452                            postfix_match: None,
4453                            function: None,
4454                            is_skipping_completion: false,
4455                            has_local_inherent_impl: false,
4456                            is_deprecated: false,
4457                        },
4458                    },
4459                    CompletionItem {
4460                        label: "write()",
4461                        detail_left: Some(
4462                            "(as Write)",
4463                        ),
4464                        detail_right: Some(
4465                            "fn(&self)",
4466                        ),
4467                        source_range: 193..193,
4468                        delete: 193..193,
4469                        insert: "write();$0",
4470                        kind: SymbolKind(
4471                            Method,
4472                        ),
4473                        lookup: "write",
4474                        detail: "fn(&self)",
4475                        relevance: CompletionRelevance {
4476                            exact_name_match: false,
4477                            type_match: None,
4478                            is_local: false,
4479                            is_missing: false,
4480                            trait_: Some(
4481                                CompletionRelevanceTraitInfo {
4482                                    notable_trait: true,
4483                                    is_op_method: false,
4484                                },
4485                            ),
4486                            is_name_already_imported: false,
4487                            requires_import: false,
4488                            is_private_editable: false,
4489                            postfix_match: None,
4490                            function: None,
4491                            is_skipping_completion: false,
4492                            has_local_inherent_impl: false,
4493                            is_deprecated: false,
4494                        },
4495                    },
4496                ]
4497            "#]],
4498        );
4499    }
4500}