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