Skip to main content

ide_completion/
render.rs

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