Skip to main content

ide_completion/
render.rs

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