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