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, 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::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext},
27    item::{Builder, CompletionRelevanceTypeMatch},
28    render::{
29        function::render_fn,
30        literal::render_variant_lit,
31        macro_::{render_macro, render_macro_pat},
32    },
33};
34/// Interface for data and methods required for items rendering.
35#[derive(Debug, Clone)]
36pub(crate) struct RenderContext<'a> {
37    completion: &'a CompletionContext<'a>,
38    is_private_editable: bool,
39    import_to_add: Option<LocatedImport>,
40    doc_aliases: Vec<SmolStr>,
41}
42
43impl<'a> RenderContext<'a> {
44    pub(crate) fn new(completion: &'a CompletionContext<'a>) -> RenderContext<'a> {
45        RenderContext {
46            completion,
47            is_private_editable: false,
48            import_to_add: None,
49            doc_aliases: vec![],
50        }
51    }
52
53    pub(crate) fn private_editable(mut self, private_editable: bool) -> Self {
54        self.is_private_editable = private_editable;
55        self
56    }
57
58    pub(crate) fn import_to_add(mut self, import_to_add: Option<LocatedImport>) -> Self {
59        self.import_to_add = import_to_add;
60        self
61    }
62
63    pub(crate) fn doc_aliases(mut self, doc_aliases: Vec<SmolStr>) -> Self {
64        self.doc_aliases = doc_aliases;
65        self
66    }
67
68    fn snippet_cap(&self) -> Option<SnippetCap> {
69        self.completion.config.snippet_cap
70    }
71
72    fn db(&self) -> &'a RootDatabase {
73        self.completion.db
74    }
75
76    fn source_range(&self) -> TextRange {
77        self.completion.source_range()
78    }
79
80    fn completion_relevance(&self) -> CompletionRelevance {
81        CompletionRelevance {
82            is_private_editable: self.is_private_editable,
83            requires_import: self.import_to_add.is_some(),
84            ..Default::default()
85        }
86    }
87
88    fn is_immediately_after_macro_bang(&self) -> bool {
89        self.completion.token.kind() == SyntaxKind::BANG
90            && self.completion.token.parent().is_some_and(|it| it.kind() == SyntaxKind::MACRO_CALL)
91    }
92
93    fn is_deprecated(&self, def: impl HasAttrs) -> bool {
94        def.attrs(self.db()).is_deprecated()
95    }
96
97    fn is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool {
98        let db = self.db();
99        let assoc = match as_assoc_item.as_assoc_item(db) {
100            Some(assoc) => assoc,
101            None => return false,
102        };
103
104        let is_assoc_deprecated = match assoc {
105            hir::AssocItem::Function(it) => self.is_deprecated(it),
106            hir::AssocItem::Const(it) => self.is_deprecated(it),
107            hir::AssocItem::TypeAlias(it) => self.is_deprecated(it),
108        };
109        is_assoc_deprecated
110            || assoc
111                .container_or_implemented_trait(db)
112                .map(|trait_| self.is_deprecated(trait_))
113                .unwrap_or(false)
114    }
115
116    // FIXME: remove this
117    fn docs(&self, def: impl HasDocs) -> Option<Documentation<'a>> {
118        def.docs(self.db())
119    }
120}
121
122pub(crate) fn render_field(
123    ctx: RenderContext<'_>,
124    dot_access: &DotAccess<'_>,
125    receiver: Option<SmolStr>,
126    field: hir::Field,
127    ty: &hir::Type<'_>,
128) -> CompletionItem {
129    let db = ctx.db();
130    let is_deprecated = ctx.is_deprecated(field);
131    let name = field.name(db);
132    let (name, escaped_name) =
133        (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr());
134    let mut item = CompletionItem::new(
135        SymbolKind::Field,
136        ctx.source_range(),
137        field_with_receiver(receiver.as_deref(), &name),
138        ctx.completion.edition,
139    );
140    item.set_relevance(CompletionRelevance {
141        type_match: compute_type_match(ctx.completion, ty),
142        exact_name_match: compute_exact_name_match(ctx.completion, &name),
143        is_skipping_completion: receiver.is_some(),
144        ..CompletionRelevance::default()
145    });
146    item.detail(ty.display(db, ctx.completion.display_target).to_string())
147        .set_documentation(field.docs(db))
148        .set_deprecated(is_deprecated)
149        .lookup_by(name);
150
151    let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
152    if !is_field_access || ty.is_fn() || ty.is_closure() {
153        let mut builder = TextEdit::builder();
154        // Using TextEdit, insert '(' before the struct name and ')' before the
155        // dot access, then comes the field name and optionally insert function
156        // call parens.
157
158        builder.replace(
159            ctx.source_range(),
160            field_with_receiver(receiver.as_deref(), &escaped_name).into(),
161        );
162
163        let expected_fn_type =
164            ctx.completion.expected_type.as_ref().is_some_and(|ty| ty.is_fn() || ty.is_closure());
165
166        if !expected_fn_type
167            && let Some(receiver) = &dot_access.receiver
168            && let Some(receiver) = ctx.completion.sema.original_ast_node(receiver.clone())
169        {
170            builder.insert(receiver.syntax().text_range().start(), "(".to_owned());
171            builder.insert(ctx.source_range().end(), ")".to_owned());
172
173            let is_parens_needed = !matches!(dot_access.kind, DotAccessKind::Method);
174
175            if is_parens_needed {
176                builder.insert(ctx.source_range().end(), "()".to_owned());
177            }
178        }
179
180        item.text_edit(builder.finish());
181    } else {
182        item.insert_text(field_with_receiver(receiver.as_deref(), &escaped_name));
183    }
184    if let Some(receiver) = &dot_access.receiver
185        && let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone())
186        && let Some(ref_mode) = compute_ref_match(ctx.completion, ty)
187    {
188        item.ref_match(ref_mode, original.syntax().text_range().start());
189    }
190    item.doc_aliases(ctx.doc_aliases);
191    item.build(db)
192}
193
194fn field_with_receiver(receiver: Option<&str>, field_name: &str) -> SmolStr {
195    receiver
196        .map_or_else(|| field_name.into(), |receiver| format_smolstr!("{}.{field_name}", receiver))
197}
198
199pub(crate) fn render_tuple_field(
200    ctx: RenderContext<'_>,
201    receiver: Option<SmolStr>,
202    field: usize,
203    ty: &hir::Type<'_>,
204) -> CompletionItem {
205    let mut item = CompletionItem::new(
206        SymbolKind::Field,
207        ctx.source_range(),
208        field_with_receiver(receiver.as_deref(), &field.to_string()),
209        ctx.completion.edition,
210    );
211    item.detail(ty.display(ctx.db(), ctx.completion.display_target).to_string())
212        .lookup_by(field.to_string());
213    item.set_relevance(CompletionRelevance {
214        is_skipping_completion: receiver.is_some(),
215        ..ctx.completion_relevance()
216    });
217    item.build(ctx.db())
218}
219
220pub(crate) fn render_type_inference(
221    ty_string: String,
222    ctx: &CompletionContext<'_>,
223) -> CompletionItem {
224    let mut builder = CompletionItem::new(
225        CompletionItemKind::InferredType,
226        ctx.source_range(),
227        ty_string,
228        ctx.edition,
229    );
230    builder.set_relevance(CompletionRelevance {
231        type_match: Some(CompletionRelevanceTypeMatch::Exact),
232        exact_name_match: true,
233        ..Default::default()
234    });
235    builder.build(ctx.db)
236}
237
238pub(crate) fn render_path_resolution(
239    ctx: RenderContext<'_>,
240    path_ctx: &PathCompletionCtx<'_>,
241    local_name: hir::Name,
242    resolution: ScopeDef,
243) -> Builder {
244    render_resolution_path(ctx, path_ctx, local_name, None, resolution)
245}
246
247pub(crate) fn render_pattern_resolution(
248    ctx: RenderContext<'_>,
249    pattern_ctx: &PatternContext,
250    local_name: hir::Name,
251    resolution: ScopeDef,
252) -> Builder {
253    render_resolution_pat(ctx, pattern_ctx, local_name, None, resolution)
254}
255
256pub(crate) fn render_resolution_with_import(
257    ctx: RenderContext<'_>,
258    path_ctx: &PathCompletionCtx<'_>,
259    import_edit: LocatedImport,
260) -> Option<Builder> {
261    let resolution = ScopeDef::from(import_edit.original_item);
262    let local_name = get_import_name(resolution, &ctx, &import_edit)?;
263    // This now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead.
264    let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution);
265    let ctx = ctx.doc_aliases(doc_aliases);
266    Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
267}
268
269pub(crate) fn render_resolution_with_import_pat(
270    ctx: RenderContext<'_>,
271    pattern_ctx: &PatternContext,
272    import_edit: LocatedImport,
273) -> Option<Builder> {
274    let resolution = ScopeDef::from(import_edit.original_item);
275    let local_name = get_import_name(resolution, &ctx, &import_edit)?;
276    Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
277}
278
279pub(crate) fn render_expr(
280    ctx: &CompletionContext<'_>,
281    expr: &hir::term_search::Expr<'_>,
282) -> Option<Builder> {
283    let mut i = 1;
284    let mut snippet_formatter = |ty: &hir::Type<'_>| {
285        let arg_name = ty
286            .as_adt()
287            .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
288            .unwrap_or_else(|| String::from("_"));
289        let res = format!("${{{i}:{arg_name}}}");
290        i += 1;
291        res
292    };
293
294    let mut label_formatter = |ty: &hir::Type<'_>| {
295        ty.as_adt()
296            .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
297            .unwrap_or_else(|| String::from("..."))
298    };
299
300    let cfg = ctx.config.find_path_config(ctx.is_nightly);
301
302    let label =
303        expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.display_target).ok()?;
304
305    let source_range = match ctx.original_token.parent() {
306        Some(node) => match node.ancestors().find_map(ast::Path::cast) {
307            Some(path) => path.syntax().text_range(),
308            None => node.text_range(),
309        },
310        None => ctx.source_range(),
311    };
312
313    let mut item =
314        CompletionItem::new(CompletionItemKind::Expression, source_range, label, ctx.edition);
315
316    let snippet = format!(
317        "{}$0",
318        expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.display_target).ok()?
319    );
320    let edit = TextEdit::replace(source_range, snippet);
321    item.snippet_edit(ctx.config.snippet_cap?, edit);
322    item.documentation(Documentation::new_owned(String::from(
323        "Autogenerated expression by term search",
324    )));
325    item.set_relevance(crate::CompletionRelevance {
326        type_match: compute_type_match(ctx, &expr.ty(ctx.db)),
327        ..Default::default()
328    });
329    for trait_ in expr.traits_used(ctx.db) {
330        let trait_item = hir::ItemInNs::from(hir::ModuleDef::from(trait_));
331        let Some(path) = ctx.module.find_path(ctx.db, trait_item, cfg) else {
332            continue;
333        };
334
335        item.add_import(LocatedImport::new_no_completion(path, trait_item, trait_item));
336    }
337
338    Some(item)
339}
340
341fn get_import_name(
342    resolution: ScopeDef,
343    ctx: &RenderContext<'_>,
344    import_edit: &LocatedImport,
345) -> Option<hir::Name> {
346    // FIXME: Temporary workaround for handling aliased import.
347    // This should be removed after we have proper support for importing alias.
348    // <https://github.com/rust-lang/rust-analyzer/issues/14079>
349
350    // If `item_to_import` matches `original_item`, we are importing the item itself (not its parent module).
351    // In this case, we can use the last segment of `import_path`, as it accounts for the aliased name.
352    if import_edit.item_to_import == import_edit.original_item {
353        import_edit.import_path.segments().last().cloned()
354    } else {
355        scope_def_to_name(resolution, ctx, import_edit)
356    }
357}
358
359fn scope_def_to_name(
360    resolution: ScopeDef,
361    ctx: &RenderContext<'_>,
362    import_edit: &LocatedImport,
363) -> Option<hir::Name> {
364    Some(match resolution {
365        ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
366        ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
367        ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
368        _ => item_name(ctx.db(), import_edit.original_item)?,
369    })
370}
371
372fn render_resolution_pat(
373    ctx: RenderContext<'_>,
374    pattern_ctx: &PatternContext,
375    local_name: hir::Name,
376    import_to_add: Option<LocatedImport>,
377    resolution: ScopeDef,
378) -> Builder {
379    let _p = tracing::info_span!("render_resolution_pat").entered();
380    use hir::ModuleDef::*;
381
382    if let ScopeDef::ModuleDef(Macro(mac)) = resolution {
383        let ctx = ctx.import_to_add(import_to_add);
384        render_macro_pat(ctx, pattern_ctx, local_name, mac)
385    } else {
386        render_resolution_simple_(ctx, &local_name, import_to_add, resolution)
387    }
388}
389
390fn render_resolution_path(
391    ctx: RenderContext<'_>,
392    path_ctx: &PathCompletionCtx<'_>,
393    local_name: hir::Name,
394    import_to_add: Option<LocatedImport>,
395    resolution: ScopeDef,
396) -> Builder {
397    let _p = tracing::info_span!("render_resolution_path").entered();
398    use hir::ModuleDef::*;
399
400    let krate = ctx.completion.display_target;
401
402    match resolution {
403        ScopeDef::ModuleDef(Macro(mac)) => {
404            let ctx = ctx.import_to_add(import_to_add);
405            return render_macro(ctx, path_ctx, local_name, mac);
406        }
407        ScopeDef::ModuleDef(Function(func)) => {
408            let ctx = ctx.import_to_add(import_to_add);
409            return render_fn(ctx, path_ctx, Some(local_name), func);
410        }
411        ScopeDef::ModuleDef(Variant(var)) => {
412            let ctx = ctx.clone().import_to_add(import_to_add.clone());
413            if let Some(item) =
414                render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
415            {
416                return item;
417            }
418        }
419        _ => (),
420    }
421
422    let completion = ctx.completion;
423    let cap = ctx.snippet_cap();
424    let db = completion.db;
425    let config = completion.config;
426    let requires_import = import_to_add.is_some();
427
428    let name = local_name.display_no_db(ctx.completion.edition).to_smolstr();
429    let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
430    if local_name.needs_escape(completion.edition) {
431        item.insert_text(local_name.display_no_db(completion.edition).to_smolstr());
432    }
433    // Add `<>` for generic types
434    let type_path_no_ty_args = matches!(
435        path_ctx,
436        PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
437    ) && config.callable.is_some();
438    if type_path_no_ty_args && let Some(cap) = cap {
439        let has_non_default_type_params = match resolution {
440            ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
441            ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
442                it.has_non_default_type_params(db)
443            }
444            _ => false,
445        };
446
447        if has_non_default_type_params {
448            cov_mark::hit!(inserts_angle_brackets_for_generics);
449            item.lookup_by(name.clone())
450                .label(SmolStr::from_iter([&name, "<…>"]))
451                .trigger_call_info()
452                .insert_snippet(cap, format!("{}<$0>", local_name.display(db, completion.edition)));
453        }
454    }
455
456    let mut set_item_relevance = |ty: Type<'_>| {
457        if !ty.is_unknown() {
458            item.detail(ty.display(db, krate).to_string());
459        }
460
461        item.set_relevance(CompletionRelevance {
462            type_match: compute_type_match(completion, &ty),
463            exact_name_match: compute_exact_name_match(completion, &name),
464            is_local: matches!(resolution, ScopeDef::Local(_)),
465            requires_import,
466            ..CompletionRelevance::default()
467        });
468
469        path_ref_match(completion, path_ctx, &ty, &mut item);
470    };
471
472    match resolution {
473        ScopeDef::Local(local) => set_item_relevance(local.ty(db)),
474        ScopeDef::ModuleDef(ModuleDef::Adt(adt)) | ScopeDef::AdtSelfType(adt) => {
475            set_item_relevance(adt.ty(db))
476        }
477        // Filtered out above
478        ScopeDef::ModuleDef(
479            ModuleDef::Function(_) | ModuleDef::Variant(_) | ModuleDef::Macro(_),
480        ) => (),
481        ScopeDef::ModuleDef(ModuleDef::Const(konst)) => set_item_relevance(konst.ty(db)),
482        ScopeDef::ModuleDef(ModuleDef::Static(stat)) => set_item_relevance(stat.ty(db)),
483        ScopeDef::ModuleDef(ModuleDef::BuiltinType(bt)) => set_item_relevance(bt.ty(db)),
484        ScopeDef::ImplSelfType(imp) => set_item_relevance(imp.self_ty(db)),
485        ScopeDef::GenericParam(_)
486        | ScopeDef::Label(_)
487        | ScopeDef::Unknown
488        | ScopeDef::ModuleDef(
489            ModuleDef::Trait(_) | ModuleDef::Module(_) | ModuleDef::TypeAlias(_),
490        ) => (),
491    };
492
493    item
494}
495
496fn render_resolution_simple_(
497    ctx: RenderContext<'_>,
498    local_name: &hir::Name,
499    import_to_add: Option<LocatedImport>,
500    resolution: ScopeDef,
501) -> Builder {
502    let _p = tracing::info_span!("render_resolution_simple_").entered();
503
504    let db = ctx.db();
505    let ctx = ctx.import_to_add(import_to_add);
506    let kind = res_to_kind(resolution);
507
508    let mut item = CompletionItem::new(
509        kind,
510        ctx.source_range(),
511        local_name.as_str().to_smolstr(),
512        ctx.completion.edition,
513    );
514    item.set_relevance(ctx.completion_relevance())
515        .set_documentation(scope_def_docs(db, resolution))
516        .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
517
518    if let Some(import_to_add) = ctx.import_to_add {
519        item.add_import(import_to_add);
520    }
521
522    item.doc_aliases(ctx.doc_aliases);
523    item
524}
525
526fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
527    use hir::ModuleDef::*;
528    match resolution {
529        ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
530        ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
531        ScopeDef::ModuleDef(Variant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
532        ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
533        ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
534        ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
535            hir::Adt::Struct(_) => SymbolKind::Struct,
536            hir::Adt::Union(_) => SymbolKind::Union,
537            hir::Adt::Enum(_) => SymbolKind::Enum,
538        }),
539        ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
540        ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
541        ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
542        ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
543        ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
544        ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
545            hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
546            hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
547            hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
548        }),
549        ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
550        ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
551        ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
552            CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
553        }
554    }
555}
556
557fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<Documentation<'_>> {
558    use hir::ModuleDef::*;
559    match resolution {
560        ScopeDef::ModuleDef(Module(it)) => it.docs(db),
561        ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
562        ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
563        ScopeDef::ModuleDef(Const(it)) => it.docs(db),
564        ScopeDef::ModuleDef(Static(it)) => it.docs(db),
565        ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
566        ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
567        _ => None,
568    }
569}
570
571fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> bool {
572    match resolution {
573        ScopeDef::ModuleDef(it) => ctx.is_deprecated_assoc_item(it),
574        ScopeDef::GenericParam(it) => ctx.is_deprecated(it),
575        ScopeDef::AdtSelfType(it) => ctx.is_deprecated(it),
576        _ => false,
577    }
578}
579
580// FIXME: This checks types without possible coercions which some completions might want to do
581fn match_types(
582    ctx: &CompletionContext<'_>,
583    ty1: &hir::Type<'_>,
584    ty2: &hir::Type<'_>,
585) -> Option<CompletionRelevanceTypeMatch> {
586    if ty1 == ty2 {
587        Some(CompletionRelevanceTypeMatch::Exact)
588    } else if ty1.could_unify_with(ctx.db, ty2) {
589        Some(CompletionRelevanceTypeMatch::CouldUnify)
590    } else {
591        None
592    }
593}
594
595fn compute_type_match(
596    ctx: &CompletionContext<'_>,
597    completion_ty: &hir::Type<'_>,
598) -> Option<CompletionRelevanceTypeMatch> {
599    let expected_type = ctx.expected_type.as_ref()?;
600
601    // We don't ever consider unit type to be an exact type match, since
602    // nearly always this is not meaningful to the user.
603    if expected_type.is_unit() {
604        return None;
605    }
606
607    // &mut ty -> &ty
608    if completion_ty.is_mutable_reference()
609        && let Some(expected_type) = expected_type.remove_ref()
610        && let Some(completion_ty) = completion_ty.remove_ref()
611    {
612        return match_types(ctx, &expected_type, &completion_ty);
613    }
614
615    match_types(ctx, expected_type, completion_ty)
616}
617
618fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool {
619    ctx.expected_name.as_ref().is_some_and(|name| name.text() == completion_name)
620}
621
622fn compute_ref_match(
623    ctx: &CompletionContext<'_>,
624    completion_ty: &hir::Type<'_>,
625) -> Option<CompletionItemRefMode> {
626    let expected_type = ctx.expected_type.as_ref()?;
627    let expected_without_ref = expected_type.remove_ref();
628    let completion_without_ref = completion_ty.remove_ref();
629    if expected_type.could_unify_with(ctx.db, completion_ty) {
630        return None;
631    }
632    if let Some(expected_without_ref) = &expected_without_ref
633        && completion_without_ref.is_none()
634        && completion_ty.autoderef(ctx.db).any(|ty| ty == *expected_without_ref)
635    {
636        cov_mark::hit!(suggest_ref);
637        let mutability = if expected_type.is_mutable_reference() {
638            hir::Mutability::Mut
639        } else {
640            hir::Mutability::Shared
641        };
642        return Some(CompletionItemRefMode::Reference(mutability));
643    }
644
645    if let Some(completion_without_ref) = completion_without_ref
646        && completion_without_ref == *expected_type
647        && completion_without_ref.is_copy(ctx.db)
648    {
649        cov_mark::hit!(suggest_deref);
650        return Some(CompletionItemRefMode::Dereference);
651    }
652
653    None
654}
655
656fn path_ref_match(
657    completion: &CompletionContext<'_>,
658    path_ctx: &PathCompletionCtx<'_>,
659    ty: &hir::Type<'_>,
660    item: &mut Builder,
661) {
662    if let Some(original_path) = &path_ctx.original_path {
663        // At least one char was typed by the user already, in that case look for the original path
664        if let Some(original_path) = completion.sema.original_ast_node(original_path.clone())
665            && let Some(ref_mode) = compute_ref_match(completion, ty)
666        {
667            item.ref_match(ref_mode, original_path.syntax().text_range().start());
668        }
669    } else {
670        // completion requested on an empty identifier, there is no path here yet.
671        // FIXME: This might create inconsistent completions where we show a ref match in macro inputs
672        // as long as nothing was typed yet
673        if let Some(ref_mode) = compute_ref_match(completion, ty) {
674            item.ref_match(ref_mode, completion.position.offset);
675        }
676    }
677}
678
679#[cfg(test)]
680mod tests {
681    use std::cmp;
682
683    use expect_test::{Expect, expect};
684    use ide_db::SymbolKind;
685    use itertools::Itertools;
686
687    use crate::{
688        CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
689        item::CompletionRelevanceTypeMatch,
690        tests::{TEST_CONFIG, check_edit, do_completion, get_all_items},
691    };
692
693    #[track_caller]
694    fn check(
695        #[rust_analyzer::rust_fixture] ra_fixture: &str,
696        kind: impl Into<CompletionItemKind>,
697        expect: Expect,
698    ) {
699        let actual = do_completion(ra_fixture, kind.into());
700        expect.assert_debug_eq(&actual);
701    }
702
703    #[track_caller]
704    fn check_kinds(
705        #[rust_analyzer::rust_fixture] ra_fixture: &str,
706        kinds: &[CompletionItemKind],
707        expect: Expect,
708    ) {
709        let actual: Vec<_> =
710            kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
711        expect.assert_debug_eq(&actual);
712    }
713
714    #[track_caller]
715    fn check_function_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
716        let actual: Vec<_> =
717            do_completion(ra_fixture, CompletionItemKind::SymbolKind(SymbolKind::Method))
718                .into_iter()
719                .map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
720                .collect();
721
722        expect.assert_debug_eq(&actual);
723    }
724
725    #[track_caller]
726    fn check_relevance_for_kinds(
727        #[rust_analyzer::rust_fixture] ra_fixture: &str,
728        kinds: &[CompletionItemKind],
729        expect: Expect,
730    ) {
731        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
732        actual.retain(|it| kinds.contains(&it.kind));
733        actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
734        check_relevance_(actual, expect);
735    }
736
737    #[track_caller]
738    fn check_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
739        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
740        actual.retain(|it| it.kind != CompletionItemKind::Snippet);
741        actual.retain(|it| it.kind != CompletionItemKind::Keyword);
742        actual.retain(|it| it.kind != CompletionItemKind::BuiltinType);
743        actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
744        check_relevance_(actual, expect);
745    }
746
747    #[track_caller]
748    fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
749        let actual = actual
750            .into_iter()
751            .flat_map(|it| {
752                let mut items = vec![];
753
754                let tag = it.kind.tag();
755                let relevance = display_relevance(it.relevance);
756                items.push(format!(
757                    "{tag} {} {} {relevance}\n",
758                    it.label.primary,
759                    it.label.detail_right.clone().unwrap_or_default(),
760                ));
761
762                if let Some((label, _indel, relevance)) = it.ref_match() {
763                    let relevance = display_relevance(relevance);
764
765                    items.push(format!("{tag} {label} {relevance}\n"));
766                }
767
768                items
769            })
770            .collect::<String>();
771
772        expect.assert_eq(&actual);
773
774        fn display_relevance(relevance: CompletionRelevance) -> String {
775            let relevance_factors = vec![
776                (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
777                (
778                    relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
779                    "type_could_unify",
780                ),
781                (relevance.exact_name_match, "name"),
782                (relevance.is_local, "local"),
783                (
784                    relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
785                    "snippet",
786                ),
787                (relevance.trait_.is_some_and(|it| it.is_op_method), "op_method"),
788                (relevance.requires_import, "requires_import"),
789            ]
790            .into_iter()
791            .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
792            .join("+");
793
794            format!("[{relevance_factors}]")
795        }
796    }
797
798    #[test]
799    fn set_struct_type_completion_info() {
800        check_relevance(
801            r#"
802//- /lib.rs crate:dep
803
804pub mod test_mod_b {
805    pub struct Struct {}
806}
807
808pub mod test_mod_a {
809    pub struct Struct {}
810}
811
812//- /main.rs crate:main deps:dep
813
814fn test(input: dep::test_mod_b::Struct) { }
815
816fn main() {
817    test(Struct$0);
818}
819"#,
820            expect![[r#"
821                st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct {  } [type_could_unify]
822                ex dep::test_mod_b::Struct {  }  [type_could_unify]
823                st Struct Struct [type_could_unify+requires_import]
824                md dep  []
825                fn main() fn() []
826                fn test(…) fn(Struct) []
827                st Struct Struct [requires_import]
828            "#]],
829        );
830    }
831
832    #[test]
833    fn set_union_type_completion_info() {
834        check_relevance(
835            r#"
836//- /lib.rs crate:dep
837
838pub mod test_mod_b {
839    pub union Union {
840        a: i32,
841        b: i32
842    }
843}
844
845pub mod test_mod_a {
846    pub enum Union {
847        a: i32,
848        b: i32
849    }
850}
851
852//- /main.rs crate:main deps:dep
853
854fn test(input: dep::test_mod_b::Union) { }
855
856fn main() {
857    test(Union$0);
858}
859"#,
860            expect![[r#"
861                un Union Union [type_could_unify+requires_import]
862                md dep  []
863                fn main() fn() []
864                fn test(…) fn(Union) []
865                en Union Union [requires_import]
866            "#]],
867        );
868    }
869
870    #[test]
871    fn set_enum_type_completion_info() {
872        check_relevance(
873            r#"
874//- /lib.rs crate:dep
875
876pub mod test_mod_b {
877    pub enum Enum {
878        variant
879    }
880}
881
882pub mod test_mod_a {
883    pub enum Enum {
884        variant
885    }
886}
887
888//- /main.rs crate:main deps:dep
889
890fn test(input: dep::test_mod_b::Enum) { }
891
892fn main() {
893    test(Enum$0);
894}
895"#,
896            expect![[r#"
897                ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type_could_unify]
898                ex dep::test_mod_b::Enum::variant  [type_could_unify]
899                en Enum Enum [type_could_unify+requires_import]
900                md dep  []
901                fn main() fn() []
902                fn test(…) fn(Enum) []
903                en Enum Enum [requires_import]
904            "#]],
905        );
906    }
907
908    #[test]
909    fn set_enum_variant_type_completion_info() {
910        check_relevance(
911            r#"
912//- /lib.rs crate:dep
913
914pub mod test_mod_b {
915    pub enum Enum {
916        Variant
917    }
918}
919
920pub mod test_mod_a {
921    pub enum Enum {
922        Variant
923    }
924}
925
926//- /main.rs crate:main deps:dep
927
928fn test(input: dep::test_mod_b::Enum) { }
929
930fn main() {
931    test(Variant$0);
932}
933"#,
934            expect![[r#"
935                ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type_could_unify]
936                ex dep::test_mod_b::Enum::Variant  [type_could_unify]
937                md dep  []
938                fn main() fn() []
939                fn test(…) fn(Enum) []
940            "#]],
941        );
942    }
943
944    #[test]
945    fn set_fn_type_completion_info() {
946        check_relevance(
947            r#"
948//- /lib.rs crate:dep
949
950pub mod test_mod_b {
951    pub fn function(j: isize) -> i32 {}
952}
953
954pub mod test_mod_a {
955    pub fn function(i: usize) -> i32 {}
956}
957
958//- /main.rs crate:main deps:dep
959
960fn test(input: fn(usize) -> i32) { }
961
962fn main() {
963    test(function$0);
964}
965"#,
966            expect![[r#"
967                md dep  []
968                fn main() fn() []
969                fn test(…) fn(fn(usize) -> i32) []
970                fn function fn(usize) -> i32 [requires_import]
971                fn function(…) fn(isize) -> i32 [requires_import]
972            "#]],
973        );
974    }
975
976    #[test]
977    fn set_const_type_completion_info() {
978        check_relevance(
979            r#"
980//- /lib.rs crate:dep
981
982pub mod test_mod_b {
983    pub const CONST: i32 = 1;
984}
985
986pub mod test_mod_a {
987    pub const CONST: i64 = 2;
988}
989
990//- /main.rs crate:main deps:dep
991
992fn test(input: i32) { }
993
994fn main() {
995    test(CONST$0);
996}
997"#,
998            expect![[r#"
999                ct CONST i32 [type_could_unify+requires_import]
1000                md dep  []
1001                fn main() fn() []
1002                fn test(…) fn(i32) []
1003                ct CONST i64 [requires_import]
1004            "#]],
1005        );
1006    }
1007
1008    #[test]
1009    fn set_static_type_completion_info() {
1010        check_relevance(
1011            r#"
1012//- /lib.rs crate:dep
1013
1014pub mod test_mod_b {
1015    pub static STATIC: i32 = 5;
1016}
1017
1018pub mod test_mod_a {
1019    pub static STATIC: i64 = 5;
1020}
1021
1022//- /main.rs crate:main deps:dep
1023
1024fn test(input: i32) { }
1025
1026fn main() {
1027    test(STATIC$0);
1028}
1029"#,
1030            expect![[r#"
1031                sc STATIC i32 [type_could_unify+requires_import]
1032                md dep  []
1033                fn main() fn() []
1034                fn test(…) fn(i32) []
1035                sc STATIC i64 [requires_import]
1036            "#]],
1037        );
1038    }
1039
1040    #[test]
1041    fn set_self_type_completion_info_with_params() {
1042        check_relevance(
1043            r#"
1044//- /lib.rs crate:dep
1045pub struct Struct;
1046
1047impl Struct {
1048    pub fn Function(&self, input: i32) -> bool {
1049                false
1050    }
1051}
1052
1053
1054//- /main.rs crate:main deps:dep
1055
1056use dep::Struct;
1057
1058
1059fn test(input: fn(&dep::Struct, i32) -> bool) { }
1060
1061fn main() {
1062    test(Struct::Function$0);
1063}
1064
1065"#,
1066            expect![[r#"
1067                me Function fn(&self, i32) -> bool []
1068            "#]],
1069        );
1070    }
1071
1072    #[test]
1073    fn set_self_type_completion_info() {
1074        check_relevance(
1075            r#"
1076//- /main.rs crate:main
1077
1078struct Struct;
1079
1080impl Struct {
1081fn test(&self) {
1082        func(Self$0);
1083    }
1084}
1085
1086fn func(input: Struct) { }
1087
1088"#,
1089            expect![[r#"
1090                st Self Self [type]
1091                st Struct Struct [type]
1092                sp Self Struct [type]
1093                st Struct Struct [type]
1094                ex Struct  [type]
1095                lc self &Struct [local]
1096                fn func(…) fn(Struct) []
1097                me self.test() fn(&self) []
1098            "#]],
1099        );
1100    }
1101
1102    #[test]
1103    fn set_builtin_type_completion_info() {
1104        check_relevance(
1105            r#"
1106//- /main.rs crate:main
1107
1108fn test(input: bool) { }
1109    pub Input: bool = false;
1110
1111fn main() {
1112    let input = false;
1113    let inputbad = 3;
1114    test(inp$0);
1115}
1116"#,
1117            expect![[r#"
1118                lc input bool [type+name+local]
1119                ex false  [type]
1120                ex input  [type]
1121                ex true  [type]
1122                lc inputbad i32 [local]
1123                fn main() fn() []
1124                fn test(…) fn(bool) []
1125            "#]],
1126        );
1127    }
1128
1129    #[test]
1130    fn enum_detail_includes_record_fields() {
1131        check(
1132            r#"
1133enum Foo { Foo { x: i32, y: i32 } }
1134
1135fn main() { Foo::Fo$0 }
1136"#,
1137            SymbolKind::Variant,
1138            expect![[r#"
1139                [
1140                    CompletionItem {
1141                        label: "Foo {…}",
1142                        detail_left: None,
1143                        detail_right: Some(
1144                            "Foo { x: i32, y: i32 }",
1145                        ),
1146                        source_range: 54..56,
1147                        delete: 54..56,
1148                        insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
1149                        kind: SymbolKind(
1150                            Variant,
1151                        ),
1152                        lookup: "Foo{}",
1153                        detail: "Foo { x: i32, y: i32 }",
1154                        relevance: CompletionRelevance {
1155                            exact_name_match: false,
1156                            type_match: None,
1157                            is_local: false,
1158                            trait_: None,
1159                            is_name_already_imported: false,
1160                            requires_import: false,
1161                            is_private_editable: false,
1162                            postfix_match: None,
1163                            function: Some(
1164                                CompletionRelevanceFn {
1165                                    has_params: true,
1166                                    has_self_param: false,
1167                                    return_type: DirectConstructor,
1168                                },
1169                            ),
1170                            is_skipping_completion: false,
1171                        },
1172                        trigger_call_info: true,
1173                    },
1174                ]
1175            "#]],
1176        );
1177    }
1178
1179    #[test]
1180    fn enum_detail_includes_tuple_fields() {
1181        check(
1182            r#"
1183enum Foo { Foo (i32, i32) }
1184
1185fn main() { Foo::Fo$0 }
1186"#,
1187            SymbolKind::Variant,
1188            expect![[r#"
1189                [
1190                    CompletionItem {
1191                        label: "Foo(…)",
1192                        detail_left: None,
1193                        detail_right: Some(
1194                            "Foo(i32, i32)",
1195                        ),
1196                        source_range: 46..48,
1197                        delete: 46..48,
1198                        insert: "Foo(${1:()}, ${2:()})$0",
1199                        kind: SymbolKind(
1200                            Variant,
1201                        ),
1202                        lookup: "Foo()",
1203                        detail: "Foo(i32, i32)",
1204                        relevance: CompletionRelevance {
1205                            exact_name_match: false,
1206                            type_match: None,
1207                            is_local: false,
1208                            trait_: None,
1209                            is_name_already_imported: false,
1210                            requires_import: false,
1211                            is_private_editable: false,
1212                            postfix_match: None,
1213                            function: Some(
1214                                CompletionRelevanceFn {
1215                                    has_params: true,
1216                                    has_self_param: false,
1217                                    return_type: DirectConstructor,
1218                                },
1219                            ),
1220                            is_skipping_completion: false,
1221                        },
1222                        trigger_call_info: true,
1223                    },
1224                ]
1225            "#]],
1226        );
1227    }
1228
1229    #[test]
1230    fn fn_detail_includes_args_and_return_type() {
1231        check(
1232            r#"
1233fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
1234
1235fn main() { fo$0 }
1236"#,
1237            SymbolKind::Function,
1238            expect![[r#"
1239                [
1240                    CompletionItem {
1241                        label: "foo(…)",
1242                        detail_left: None,
1243                        detail_right: Some(
1244                            "fn(u32, u32, T) -> (u32, T)",
1245                        ),
1246                        source_range: 68..70,
1247                        delete: 68..70,
1248                        insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
1249                        kind: SymbolKind(
1250                            Function,
1251                        ),
1252                        lookup: "foo",
1253                        detail: "fn(u32, u32, T) -> (u32, T)",
1254                        trigger_call_info: true,
1255                    },
1256                    CompletionItem {
1257                        label: "main()",
1258                        detail_left: None,
1259                        detail_right: Some(
1260                            "fn()",
1261                        ),
1262                        source_range: 68..70,
1263                        delete: 68..70,
1264                        insert: "main();$0",
1265                        kind: SymbolKind(
1266                            Function,
1267                        ),
1268                        lookup: "main",
1269                        detail: "fn()",
1270                    },
1271                ]
1272            "#]],
1273        );
1274    }
1275
1276    #[test]
1277    fn fn_detail_includes_variadics() {
1278        check(
1279            r#"
1280unsafe extern "C" fn foo(a: u32, b: u32, ...) {}
1281
1282fn main() { fo$0 }
1283"#,
1284            SymbolKind::Function,
1285            expect![[r#"
1286                [
1287                    CompletionItem {
1288                        label: "foo(…)",
1289                        detail_left: None,
1290                        detail_right: Some(
1291                            "unsafe fn(u32, u32, ...)",
1292                        ),
1293                        source_range: 62..64,
1294                        delete: 62..64,
1295                        insert: "foo(${1:a}, ${2:b});$0",
1296                        kind: SymbolKind(
1297                            Function,
1298                        ),
1299                        lookup: "foo",
1300                        detail: "unsafe fn(u32, u32, ...)",
1301                        trigger_call_info: true,
1302                    },
1303                    CompletionItem {
1304                        label: "main()",
1305                        detail_left: None,
1306                        detail_right: Some(
1307                            "fn()",
1308                        ),
1309                        source_range: 62..64,
1310                        delete: 62..64,
1311                        insert: "main();$0",
1312                        kind: SymbolKind(
1313                            Function,
1314                        ),
1315                        lookup: "main",
1316                        detail: "fn()",
1317                    },
1318                ]
1319            "#]],
1320        );
1321    }
1322
1323    #[test]
1324    fn enum_detail_just_name_for_unit() {
1325        check(
1326            r#"
1327enum Foo { Foo }
1328
1329fn main() { Foo::Fo$0 }
1330"#,
1331            SymbolKind::Variant,
1332            expect![[r#"
1333                [
1334                    CompletionItem {
1335                        label: "Foo",
1336                        detail_left: None,
1337                        detail_right: Some(
1338                            "Foo",
1339                        ),
1340                        source_range: 35..37,
1341                        delete: 35..37,
1342                        insert: "Foo$0",
1343                        kind: SymbolKind(
1344                            Variant,
1345                        ),
1346                        detail: "Foo",
1347                        relevance: CompletionRelevance {
1348                            exact_name_match: false,
1349                            type_match: None,
1350                            is_local: false,
1351                            trait_: None,
1352                            is_name_already_imported: false,
1353                            requires_import: false,
1354                            is_private_editable: false,
1355                            postfix_match: None,
1356                            function: Some(
1357                                CompletionRelevanceFn {
1358                                    has_params: false,
1359                                    has_self_param: false,
1360                                    return_type: DirectConstructor,
1361                                },
1362                            ),
1363                            is_skipping_completion: false,
1364                        },
1365                        trigger_call_info: true,
1366                    },
1367                ]
1368            "#]],
1369        );
1370    }
1371
1372    #[test]
1373    fn lookup_enums_by_two_qualifiers() {
1374        check_kinds(
1375            r#"
1376mod m {
1377    pub enum Spam { Foo, Bar(i32) }
1378}
1379fn main() { let _: m::Spam = S$0 }
1380"#,
1381            &[
1382                CompletionItemKind::SymbolKind(SymbolKind::Function),
1383                CompletionItemKind::SymbolKind(SymbolKind::Module),
1384                CompletionItemKind::SymbolKind(SymbolKind::Variant),
1385            ],
1386            expect![[r#"
1387                [
1388                    CompletionItem {
1389                        label: "main()",
1390                        detail_left: None,
1391                        detail_right: Some(
1392                            "fn()",
1393                        ),
1394                        source_range: 75..76,
1395                        delete: 75..76,
1396                        insert: "main();$0",
1397                        kind: SymbolKind(
1398                            Function,
1399                        ),
1400                        lookup: "main",
1401                        detail: "fn()",
1402                    },
1403                    CompletionItem {
1404                        label: "m",
1405                        detail_left: None,
1406                        detail_right: None,
1407                        source_range: 75..76,
1408                        delete: 75..76,
1409                        insert: "m",
1410                        kind: SymbolKind(
1411                            Module,
1412                        ),
1413                    },
1414                    CompletionItem {
1415                        label: "m::Spam::Bar(…)",
1416                        detail_left: None,
1417                        detail_right: Some(
1418                            "m::Spam::Bar(i32)",
1419                        ),
1420                        source_range: 75..76,
1421                        delete: 75..76,
1422                        insert: "m::Spam::Bar(${1:()})$0",
1423                        kind: SymbolKind(
1424                            Variant,
1425                        ),
1426                        lookup: "Spam::Bar()",
1427                        detail: "m::Spam::Bar(i32)",
1428                        relevance: CompletionRelevance {
1429                            exact_name_match: false,
1430                            type_match: Some(
1431                                Exact,
1432                            ),
1433                            is_local: false,
1434                            trait_: None,
1435                            is_name_already_imported: false,
1436                            requires_import: false,
1437                            is_private_editable: false,
1438                            postfix_match: None,
1439                            function: Some(
1440                                CompletionRelevanceFn {
1441                                    has_params: true,
1442                                    has_self_param: false,
1443                                    return_type: DirectConstructor,
1444                                },
1445                            ),
1446                            is_skipping_completion: false,
1447                        },
1448                        trigger_call_info: true,
1449                    },
1450                    CompletionItem {
1451                        label: "m::Spam::Foo",
1452                        detail_left: None,
1453                        detail_right: Some(
1454                            "m::Spam::Foo",
1455                        ),
1456                        source_range: 75..76,
1457                        delete: 75..76,
1458                        insert: "m::Spam::Foo$0",
1459                        kind: SymbolKind(
1460                            Variant,
1461                        ),
1462                        lookup: "Spam::Foo",
1463                        detail: "m::Spam::Foo",
1464                        relevance: CompletionRelevance {
1465                            exact_name_match: false,
1466                            type_match: Some(
1467                                Exact,
1468                            ),
1469                            is_local: false,
1470                            trait_: None,
1471                            is_name_already_imported: false,
1472                            requires_import: false,
1473                            is_private_editable: false,
1474                            postfix_match: None,
1475                            function: Some(
1476                                CompletionRelevanceFn {
1477                                    has_params: false,
1478                                    has_self_param: false,
1479                                    return_type: DirectConstructor,
1480                                },
1481                            ),
1482                            is_skipping_completion: false,
1483                        },
1484                        trigger_call_info: true,
1485                    },
1486                ]
1487            "#]],
1488        )
1489    }
1490
1491    #[test]
1492    fn sets_deprecated_flag_in_items() {
1493        check(
1494            r#"
1495#[deprecated]
1496fn something_deprecated() {}
1497
1498fn main() { som$0 }
1499"#,
1500            SymbolKind::Function,
1501            expect![[r#"
1502                [
1503                    CompletionItem {
1504                        label: "main()",
1505                        detail_left: None,
1506                        detail_right: Some(
1507                            "fn()",
1508                        ),
1509                        source_range: 56..59,
1510                        delete: 56..59,
1511                        insert: "main();$0",
1512                        kind: SymbolKind(
1513                            Function,
1514                        ),
1515                        lookup: "main",
1516                        detail: "fn()",
1517                    },
1518                    CompletionItem {
1519                        label: "something_deprecated()",
1520                        detail_left: None,
1521                        detail_right: Some(
1522                            "fn()",
1523                        ),
1524                        source_range: 56..59,
1525                        delete: 56..59,
1526                        insert: "something_deprecated();$0",
1527                        kind: SymbolKind(
1528                            Function,
1529                        ),
1530                        lookup: "something_deprecated",
1531                        detail: "fn()",
1532                        deprecated: true,
1533                    },
1534                ]
1535            "#]],
1536        );
1537
1538        check(
1539            r#"
1540struct A { #[deprecated] the_field: u32 }
1541fn foo() { A { the$0 } }
1542"#,
1543            SymbolKind::Field,
1544            expect![[r#"
1545                [
1546                    CompletionItem {
1547                        label: "the_field",
1548                        detail_left: None,
1549                        detail_right: Some(
1550                            "u32",
1551                        ),
1552                        source_range: 57..60,
1553                        delete: 57..60,
1554                        insert: "the_field",
1555                        kind: SymbolKind(
1556                            Field,
1557                        ),
1558                        detail: "u32",
1559                        deprecated: true,
1560                        relevance: CompletionRelevance {
1561                            exact_name_match: false,
1562                            type_match: Some(
1563                                CouldUnify,
1564                            ),
1565                            is_local: false,
1566                            trait_: None,
1567                            is_name_already_imported: false,
1568                            requires_import: false,
1569                            is_private_editable: false,
1570                            postfix_match: None,
1571                            function: None,
1572                            is_skipping_completion: false,
1573                        },
1574                    },
1575                ]
1576            "#]],
1577        );
1578    }
1579
1580    #[test]
1581    fn renders_docs() {
1582        check_kinds(
1583            r#"
1584struct S {
1585    /// Field docs
1586    foo:
1587}
1588impl S {
1589    /// Method docs
1590    fn bar(self) { self.$0 }
1591}"#,
1592            &[
1593                CompletionItemKind::SymbolKind(SymbolKind::Method),
1594                CompletionItemKind::SymbolKind(SymbolKind::Field),
1595            ],
1596            expect![[r#"
1597                [
1598                    CompletionItem {
1599                        label: "bar()",
1600                        detail_left: None,
1601                        detail_right: Some(
1602                            "fn(self)",
1603                        ),
1604                        source_range: 94..94,
1605                        delete: 94..94,
1606                        insert: "bar();$0",
1607                        kind: SymbolKind(
1608                            Method,
1609                        ),
1610                        lookup: "bar",
1611                        detail: "fn(self)",
1612                        documentation: Documentation(
1613                            "Method docs",
1614                        ),
1615                        relevance: CompletionRelevance {
1616                            exact_name_match: false,
1617                            type_match: None,
1618                            is_local: false,
1619                            trait_: None,
1620                            is_name_already_imported: false,
1621                            requires_import: false,
1622                            is_private_editable: false,
1623                            postfix_match: None,
1624                            function: Some(
1625                                CompletionRelevanceFn {
1626                                    has_params: true,
1627                                    has_self_param: true,
1628                                    return_type: Other,
1629                                },
1630                            ),
1631                            is_skipping_completion: false,
1632                        },
1633                    },
1634                    CompletionItem {
1635                        label: "foo",
1636                        detail_left: None,
1637                        detail_right: Some(
1638                            "{unknown}",
1639                        ),
1640                        source_range: 94..94,
1641                        delete: 94..94,
1642                        insert: "foo",
1643                        kind: SymbolKind(
1644                            Field,
1645                        ),
1646                        detail: "{unknown}",
1647                        documentation: Documentation(
1648                            "Field docs",
1649                        ),
1650                    },
1651                ]
1652            "#]],
1653        );
1654
1655        check_kinds(
1656            r#"
1657use self::my$0;
1658
1659/// mod docs
1660mod my { }
1661
1662/// enum docs
1663enum E {
1664    /// variant docs
1665    V
1666}
1667use self::E::*;
1668"#,
1669            &[
1670                CompletionItemKind::SymbolKind(SymbolKind::Module),
1671                CompletionItemKind::SymbolKind(SymbolKind::Variant),
1672                CompletionItemKind::SymbolKind(SymbolKind::Enum),
1673            ],
1674            expect![[r#"
1675                [
1676                    CompletionItem {
1677                        label: "my",
1678                        detail_left: None,
1679                        detail_right: None,
1680                        source_range: 10..12,
1681                        delete: 10..12,
1682                        insert: "my",
1683                        kind: SymbolKind(
1684                            Module,
1685                        ),
1686                        documentation: Documentation(
1687                            "mod docs",
1688                        ),
1689                    },
1690                    CompletionItem {
1691                        label: "V",
1692                        detail_left: None,
1693                        detail_right: Some(
1694                            "V",
1695                        ),
1696                        source_range: 10..12,
1697                        delete: 10..12,
1698                        insert: "V$0",
1699                        kind: SymbolKind(
1700                            Variant,
1701                        ),
1702                        detail: "V",
1703                        documentation: Documentation(
1704                            "variant docs",
1705                        ),
1706                        relevance: CompletionRelevance {
1707                            exact_name_match: false,
1708                            type_match: None,
1709                            is_local: false,
1710                            trait_: None,
1711                            is_name_already_imported: false,
1712                            requires_import: false,
1713                            is_private_editable: false,
1714                            postfix_match: None,
1715                            function: Some(
1716                                CompletionRelevanceFn {
1717                                    has_params: false,
1718                                    has_self_param: false,
1719                                    return_type: DirectConstructor,
1720                                },
1721                            ),
1722                            is_skipping_completion: false,
1723                        },
1724                        trigger_call_info: true,
1725                    },
1726                    CompletionItem {
1727                        label: "E",
1728                        detail_left: None,
1729                        detail_right: Some(
1730                            "E",
1731                        ),
1732                        source_range: 10..12,
1733                        delete: 10..12,
1734                        insert: "E",
1735                        kind: SymbolKind(
1736                            Enum,
1737                        ),
1738                        detail: "E",
1739                        documentation: Documentation(
1740                            "enum docs",
1741                        ),
1742                    },
1743                ]
1744            "#]],
1745        )
1746    }
1747
1748    #[test]
1749    fn dont_render_attrs() {
1750        check(
1751            r#"
1752struct S;
1753impl S {
1754    #[inline]
1755    fn the_method(&self) { }
1756}
1757fn foo(s: S) { s.$0 }
1758"#,
1759            CompletionItemKind::SymbolKind(SymbolKind::Method),
1760            expect![[r#"
1761                [
1762                    CompletionItem {
1763                        label: "the_method()",
1764                        detail_left: None,
1765                        detail_right: Some(
1766                            "fn(&self)",
1767                        ),
1768                        source_range: 81..81,
1769                        delete: 81..81,
1770                        insert: "the_method();$0",
1771                        kind: SymbolKind(
1772                            Method,
1773                        ),
1774                        lookup: "the_method",
1775                        detail: "fn(&self)",
1776                        relevance: CompletionRelevance {
1777                            exact_name_match: false,
1778                            type_match: None,
1779                            is_local: false,
1780                            trait_: None,
1781                            is_name_already_imported: false,
1782                            requires_import: false,
1783                            is_private_editable: false,
1784                            postfix_match: None,
1785                            function: Some(
1786                                CompletionRelevanceFn {
1787                                    has_params: true,
1788                                    has_self_param: true,
1789                                    return_type: Other,
1790                                },
1791                            ),
1792                            is_skipping_completion: false,
1793                        },
1794                    },
1795                ]
1796            "#]],
1797        )
1798    }
1799
1800    #[test]
1801    fn no_call_parens_if_fn_ptr_needed() {
1802        cov_mark::check!(no_call_parens_if_fn_ptr_needed);
1803        check_edit(
1804            "foo",
1805            r#"
1806fn foo(foo: u8, bar: u8) {}
1807struct ManualVtable { f: fn(u8, u8) }
1808
1809fn main() -> ManualVtable {
1810    ManualVtable { f: f$0 }
1811}
1812"#,
1813            r#"
1814fn foo(foo: u8, bar: u8) {}
1815struct ManualVtable { f: fn(u8, u8) }
1816
1817fn main() -> ManualVtable {
1818    ManualVtable { f: foo }
1819}
1820"#,
1821        );
1822        check_edit(
1823            "type",
1824            r#"
1825struct RawIdentTable { r#type: u32 }
1826
1827fn main() -> RawIdentTable {
1828    RawIdentTable { t$0: 42 }
1829}
1830"#,
1831            r#"
1832struct RawIdentTable { r#type: u32 }
1833
1834fn main() -> RawIdentTable {
1835    RawIdentTable { r#type: 42 }
1836}
1837"#,
1838        );
1839    }
1840
1841    #[test]
1842    fn no_parens_in_use_item() {
1843        check_edit(
1844            "foo",
1845            r#"
1846mod m { pub fn foo() {} }
1847use crate::m::f$0;
1848"#,
1849            r#"
1850mod m { pub fn foo() {} }
1851use crate::m::foo;
1852"#,
1853        );
1854    }
1855
1856    #[test]
1857    fn no_parens_in_call() {
1858        check_edit(
1859            "foo",
1860            r#"
1861fn foo(x: i32) {}
1862fn main() { f$0(); }
1863"#,
1864            r#"
1865fn foo(x: i32) {}
1866fn main() { foo(); }
1867"#,
1868        );
1869        check_edit(
1870            "foo",
1871            r#"
1872struct Foo;
1873impl Foo { fn foo(&self){} }
1874fn f(foo: &Foo) { foo.f$0(); }
1875"#,
1876            r#"
1877struct Foo;
1878impl Foo { fn foo(&self){} }
1879fn f(foo: &Foo) { foo.foo(); }
1880"#,
1881        );
1882    }
1883
1884    #[test]
1885    fn inserts_angle_brackets_for_generics() {
1886        cov_mark::check!(inserts_angle_brackets_for_generics);
1887        check_edit(
1888            "Vec",
1889            r#"
1890struct Vec<T> {}
1891fn foo(xs: Ve$0)
1892"#,
1893            r#"
1894struct Vec<T> {}
1895fn foo(xs: Vec<$0>)
1896"#,
1897        );
1898        check_edit(
1899            "Vec",
1900            r#"
1901type Vec<T> = (T,);
1902fn foo(xs: Ve$0)
1903"#,
1904            r#"
1905type Vec<T> = (T,);
1906fn foo(xs: Vec<$0>)
1907"#,
1908        );
1909        check_edit(
1910            "Vec",
1911            r#"
1912struct Vec<T = i128> {}
1913fn foo(xs: Ve$0)
1914"#,
1915            r#"
1916struct Vec<T = i128> {}
1917fn foo(xs: Vec)
1918"#,
1919        );
1920        check_edit(
1921            "Vec",
1922            r#"
1923struct Vec<T> {}
1924fn foo(xs: Ve$0<i128>)
1925"#,
1926            r#"
1927struct Vec<T> {}
1928fn foo(xs: Vec<i128>)
1929"#,
1930        );
1931    }
1932
1933    #[test]
1934    fn active_param_relevance() {
1935        check_relevance(
1936            r#"
1937struct S { foo: i64, bar: u32, baz: u32 }
1938fn test(bar: u32) { }
1939fn foo(s: S) { test(s.$0) }
1940"#,
1941            expect![[r#"
1942                fd bar u32 [type+name]
1943                fd baz u32 [type]
1944                fd foo i64 []
1945            "#]],
1946        );
1947    }
1948
1949    #[test]
1950    fn record_field_relevances() {
1951        check_relevance(
1952            r#"
1953struct A { foo: i64, bar: u32, baz: u32 }
1954struct B { x: (), y: f32, bar: u32 }
1955fn foo(a: A) { B { bar: a.$0 }; }
1956"#,
1957            expect![[r#"
1958                fd bar u32 [type+name]
1959                fd baz u32 [type]
1960                fd foo i64 []
1961            "#]],
1962        )
1963    }
1964
1965    #[test]
1966    fn tuple_field_detail() {
1967        check(
1968            r#"
1969struct S(i32);
1970
1971fn f() -> i32 {
1972    let s = S(0);
1973    s.0$0
1974}
1975"#,
1976            SymbolKind::Field,
1977            expect![[r#"
1978                [
1979                    CompletionItem {
1980                        label: "0",
1981                        detail_left: None,
1982                        detail_right: Some(
1983                            "i32",
1984                        ),
1985                        source_range: 56..57,
1986                        delete: 56..57,
1987                        insert: "0",
1988                        kind: SymbolKind(
1989                            Field,
1990                        ),
1991                        detail: "i32",
1992                        relevance: CompletionRelevance {
1993                            exact_name_match: false,
1994                            type_match: Some(
1995                                Exact,
1996                            ),
1997                            is_local: false,
1998                            trait_: None,
1999                            is_name_already_imported: false,
2000                            requires_import: false,
2001                            is_private_editable: false,
2002                            postfix_match: None,
2003                            function: None,
2004                            is_skipping_completion: false,
2005                        },
2006                    },
2007                ]
2008            "#]],
2009        );
2010    }
2011
2012    #[test]
2013    fn record_field_and_call_relevances() {
2014        check_relevance(
2015            r#"
2016struct A { foo: i64, bar: u32, baz: u32 }
2017struct B { x: (), y: f32, bar: u32 }
2018fn f(foo: i64) {  }
2019fn foo(a: A) { B { bar: f(a.$0) }; }
2020"#,
2021            expect![[r#"
2022                fd foo i64 [type+name]
2023                fd bar u32 []
2024                fd baz u32 []
2025            "#]],
2026        );
2027        check_relevance(
2028            r#"
2029struct A { foo: i64, bar: u32, baz: u32 }
2030struct B { x: (), y: f32, bar: u32 }
2031fn f(foo: i64) {  }
2032fn foo(a: A) { f(B { bar: a.$0 }); }
2033"#,
2034            expect![[r#"
2035                fd bar u32 [type+name]
2036                fd baz u32 [type]
2037                fd foo i64 []
2038            "#]],
2039        );
2040    }
2041
2042    #[test]
2043    fn prioritize_exact_ref_match() {
2044        check_relevance(
2045            r#"
2046struct WorldSnapshot { _f: () };
2047fn go(world: &WorldSnapshot) { go(w$0) }
2048"#,
2049            expect![[r#"
2050                lc world &WorldSnapshot [type+name+local]
2051                ex world  [type]
2052                st WorldSnapshot {…} WorldSnapshot { _f: () } []
2053                st &WorldSnapshot {…} [type]
2054                st WorldSnapshot WorldSnapshot []
2055                st &WorldSnapshot [type]
2056                fn go(…) fn(&WorldSnapshot) []
2057            "#]],
2058        );
2059    }
2060
2061    #[test]
2062    fn prioritize_mutable_ref_as_immutable_ref_match() {
2063        check_relevance(
2064            r#"fn foo(r: &mut i32) -> &i32 { $0 }"#,
2065            expect![[r#"
2066                lc r &mut i32 [type+local]
2067                fn foo(…) fn(&mut i32) -> &i32 [type]
2068            "#]],
2069        );
2070    }
2071
2072    #[test]
2073    fn too_many_arguments() {
2074        cov_mark::check!(too_many_arguments);
2075        check_relevance(
2076            r#"
2077struct Foo;
2078fn f(foo: &Foo) { f(foo, w$0) }
2079"#,
2080            expect![[r#"
2081                lc foo &Foo [local]
2082                st Foo Foo []
2083                fn f(…) fn(&Foo) []
2084            "#]],
2085        );
2086    }
2087
2088    #[test]
2089    fn score_fn_type_and_name_match() {
2090        check_relevance(
2091            r#"
2092struct A { bar: u8 }
2093fn baz() -> u8 { 0 }
2094fn bar() -> u8 { 0 }
2095fn f() { A { bar: b$0 }; }
2096"#,
2097            expect![[r#"
2098                fn bar() fn() -> u8 [type+name]
2099                ex bar()  [type]
2100                fn baz() fn() -> u8 [type]
2101                ex baz()  [type]
2102                st A A []
2103                fn f() fn() []
2104            "#]],
2105        );
2106    }
2107
2108    #[test]
2109    fn score_method_type_and_name_match() {
2110        check_relevance(
2111            r#"
2112fn baz(aaa: u32){}
2113struct Foo;
2114impl Foo {
2115fn aaa(&self) -> u32 { 0 }
2116fn bbb(&self) -> u32 { 0 }
2117fn ccc(&self) -> u64 { 0 }
2118}
2119fn f() {
2120    baz(Foo.$0
2121}
2122"#,
2123            expect![[r#"
2124                me aaa() fn(&self) -> u32 [type+name]
2125                me bbb() fn(&self) -> u32 [type]
2126                me ccc() fn(&self) -> u64 []
2127            "#]],
2128        );
2129    }
2130
2131    #[test]
2132    fn score_method_name_match_only() {
2133        check_relevance(
2134            r#"
2135fn baz(aaa: u32){}
2136struct Foo;
2137impl Foo {
2138fn aaa(&self) -> u64 { 0 }
2139}
2140fn f() {
2141    baz(Foo.$0
2142}
2143"#,
2144            expect![[r#"
2145                me aaa() fn(&self) -> u64 [name]
2146            "#]],
2147        );
2148    }
2149
2150    #[test]
2151    fn test_avoid_redundant_suggestion() {
2152        check_relevance(
2153            r#"
2154struct aa([u8]);
2155
2156impl aa {
2157    fn from_bytes(bytes: &[u8]) -> &Self {
2158        unsafe { &*(bytes as *const [u8] as *const aa) }
2159    }
2160}
2161
2162fn bb()-> &'static aa {
2163    let bytes = b"hello";
2164    aa::$0
2165}
2166"#,
2167            expect![[r#"
2168                ex bb()  [type]
2169                fn from_bytes(…) fn(&[u8]) -> &aa [type_could_unify]
2170            "#]],
2171        );
2172    }
2173
2174    #[test]
2175    fn suggest_ref_mut() {
2176        cov_mark::check!(suggest_ref);
2177        check_relevance(
2178            r#"
2179struct S;
2180fn foo(s: &mut S) {}
2181fn main() {
2182    let mut s = S;
2183    foo($0);
2184}
2185            "#,
2186            expect![[r#"
2187                lc s S [name+local]
2188                lc &mut s [type+name+local]
2189                st S S []
2190                st &mut S [type]
2191                st S S []
2192                st &mut S [type]
2193                fn foo(…) fn(&mut S) []
2194                fn main() fn() []
2195            "#]],
2196        );
2197        check_relevance(
2198            r#"
2199struct S;
2200fn foo(s: &mut S) {}
2201fn main() {
2202    let mut s = S;
2203    foo(&mut $0);
2204}
2205            "#,
2206            expect![[r#"
2207                lc s S [type+name+local]
2208                st S S [type]
2209                st S S [type]
2210                ex S  [type]
2211                ex s  [type]
2212                fn foo(…) fn(&mut S) []
2213                fn main() fn() []
2214            "#]],
2215        );
2216        check_relevance(
2217            r#"
2218struct S;
2219fn foo(s: &mut S) {}
2220fn main() {
2221    let mut ssss = S;
2222    foo(&mut s$0);
2223}
2224            "#,
2225            expect![[r#"
2226                st S S [type]
2227                lc ssss S [type+local]
2228                st S S [type]
2229                ex S  [type]
2230                ex ssss  [type]
2231                fn foo(…) fn(&mut S) []
2232                fn main() fn() []
2233            "#]],
2234        );
2235    }
2236
2237    #[test]
2238    fn suggest_deref_copy() {
2239        cov_mark::check!(suggest_deref);
2240        check_relevance(
2241            r#"
2242//- minicore: copy
2243struct Foo;
2244
2245impl Copy for Foo {}
2246impl Clone for Foo {
2247    fn clone(&self) -> Self { *self }
2248}
2249
2250fn bar(x: Foo) {}
2251
2252fn main() {
2253    let foo = &Foo;
2254    bar($0);
2255}
2256"#,
2257            expect![[r#"
2258                st Foo Foo [type]
2259                st Foo Foo [type]
2260                ex Foo  [type]
2261                lc foo &Foo [local]
2262                lc *foo [type+local]
2263                tt Clone  []
2264                tt Copy  []
2265                fn bar(…) fn(Foo) []
2266                md core  []
2267                fn main() fn() []
2268            "#]],
2269        );
2270    }
2271
2272    #[test]
2273    fn suggest_deref_trait() {
2274        check_relevance(
2275            r#"
2276//- minicore: deref
2277struct S;
2278struct T(S);
2279
2280impl core::ops::Deref for T {
2281    type Target = S;
2282
2283    fn deref(&self) -> &Self::Target {
2284        &self.0
2285    }
2286}
2287
2288fn foo(s: &S) {}
2289
2290fn main() {
2291    let t = T(S);
2292    let m = 123;
2293
2294    foo($0);
2295}
2296            "#,
2297            expect![[r#"
2298                st S S []
2299                st &S [type]
2300                ex core::ops::Deref::deref(&t)  [type_could_unify]
2301                lc m i32 [local]
2302                lc t T [local]
2303                lc &t [type+local]
2304                st S S []
2305                st &S [type]
2306                st T T []
2307                st &T [type]
2308                md core  []
2309                fn foo(…) fn(&S) []
2310                fn main() fn() []
2311            "#]],
2312        )
2313    }
2314
2315    #[test]
2316    fn suggest_deref_mut() {
2317        check_relevance(
2318            r#"
2319//- minicore: deref_mut
2320struct S;
2321struct T(S);
2322
2323impl core::ops::Deref for T {
2324    type Target = S;
2325
2326    fn deref(&self) -> &Self::Target {
2327        &self.0
2328    }
2329}
2330
2331impl core::ops::DerefMut for T {
2332    fn deref_mut(&mut self) -> &mut Self::Target {
2333        &mut self.0
2334    }
2335}
2336
2337fn foo(s: &mut S) {}
2338
2339fn main() {
2340    let t = T(S);
2341    let m = 123;
2342
2343    foo($0);
2344}
2345            "#,
2346            expect![[r#"
2347                st S S []
2348                st &mut S [type]
2349                ex core::ops::DerefMut::deref_mut(&mut t)  [type_could_unify]
2350                lc m i32 [local]
2351                lc t T [local]
2352                lc &mut t [type+local]
2353                st S S []
2354                st &mut S [type]
2355                st T T []
2356                st &mut T [type]
2357                md core  []
2358                fn foo(…) fn(&mut S) []
2359                fn main() fn() []
2360            "#]],
2361        )
2362    }
2363
2364    #[test]
2365    fn locals() {
2366        check_relevance(
2367            r#"
2368fn foo(bar: u32) {
2369    let baz = 0;
2370
2371    f$0
2372}
2373"#,
2374            expect![[r#"
2375                lc bar u32 [local]
2376                lc baz i32 [local]
2377                fn foo(…) fn(u32) []
2378            "#]],
2379        );
2380    }
2381
2382    #[test]
2383    fn enum_owned() {
2384        check_relevance(
2385            r#"
2386enum Foo { A, B }
2387fn foo() {
2388    bar($0);
2389}
2390fn bar(t: Foo) {}
2391"#,
2392            expect![[r#"
2393                ev Foo::A Foo::A [type]
2394                ev Foo::B Foo::B [type]
2395                en Foo Foo [type]
2396                ex Foo::A  [type]
2397                ex Foo::B  [type]
2398                fn bar(…) fn(Foo) []
2399                fn foo() fn() []
2400            "#]],
2401        );
2402    }
2403
2404    #[test]
2405    fn enum_ref() {
2406        check_relevance(
2407            r#"
2408enum Foo { A, B }
2409fn foo() {
2410    bar($0);
2411}
2412fn bar(t: &Foo) {}
2413"#,
2414            expect![[r#"
2415                ev Foo::A Foo::A []
2416                ev &Foo::A [type]
2417                ev Foo::B Foo::B []
2418                ev &Foo::B [type]
2419                en Foo Foo []
2420                en &Foo [type]
2421                fn bar(…) fn(&Foo) []
2422                fn foo() fn() []
2423            "#]],
2424        );
2425    }
2426
2427    #[test]
2428    fn suggest_deref_fn_ret() {
2429        check_relevance(
2430            r#"
2431//- minicore: deref
2432struct S;
2433struct T(S);
2434
2435impl core::ops::Deref for T {
2436    type Target = S;
2437
2438    fn deref(&self) -> &Self::Target {
2439        &self.0
2440    }
2441}
2442
2443fn foo(s: &S) {}
2444fn bar() -> T {}
2445
2446fn main() {
2447    foo($0);
2448}
2449"#,
2450            expect![[r#"
2451                st S S []
2452                st &S [type]
2453                ex core::ops::Deref::deref(&bar())  [type_could_unify]
2454                st S S []
2455                st &S [type]
2456                st T T []
2457                st &T [type]
2458                fn bar() fn() -> T []
2459                fn &bar() [type]
2460                md core  []
2461                fn foo(…) fn(&S) []
2462                fn main() fn() []
2463            "#]],
2464        )
2465    }
2466
2467    #[test]
2468    fn op_function_relevances() {
2469        check_relevance(
2470            r#"
2471#[lang = "sub"]
2472trait Sub {
2473    fn sub(self, other: Self) -> Self { self }
2474}
2475impl Sub for u32 {}
2476fn foo(a: u32) { a.$0 }
2477"#,
2478            expect![[r#"
2479                me sub(…) fn(self, Self) -> Self [op_method]
2480            "#]],
2481        );
2482        check_relevance(
2483            r#"
2484struct Foo;
2485impl Foo {
2486    fn new() -> Self {}
2487}
2488#[lang = "eq"]
2489pub trait PartialEq<Rhs: ?Sized = Self> {
2490    fn eq(&self, other: &Rhs) -> bool;
2491    fn ne(&self, other: &Rhs) -> bool;
2492}
2493
2494impl PartialEq for Foo {}
2495fn main() {
2496    Foo::$0
2497}
2498"#,
2499            expect![[r#"
2500                fn new() fn() -> Foo []
2501                me eq(…) fn(&self, &Rhs) -> bool [op_method]
2502                me ne(…) fn(&self, &Rhs) -> bool [op_method]
2503            "#]],
2504        );
2505    }
2506
2507    #[test]
2508    fn constructor_order_simple() {
2509        check_relevance(
2510            r#"
2511struct Foo;
2512struct Other;
2513struct Option<T>(T);
2514
2515impl Foo {
2516    fn fn_ctr() -> Foo { unimplemented!() }
2517    fn fn_another(n: u32) -> Other { unimplemented!() }
2518    fn fn_ctr_self() -> Option<Self> { unimplemented!() }
2519}
2520
2521fn test() {
2522    let a = Foo::$0;
2523}
2524"#,
2525            expect![[r#"
2526                fn fn_ctr() fn() -> Foo [type_could_unify]
2527                fn fn_ctr_self() fn() -> Option<Foo> [type_could_unify]
2528                fn fn_another(…) fn(u32) -> Other [type_could_unify]
2529            "#]],
2530        );
2531    }
2532
2533    #[test]
2534    fn constructor_order_kind() {
2535        check_function_relevance(
2536            r#"
2537struct Foo;
2538struct Bar;
2539struct Option<T>(T);
2540enum Result<T, E> { Ok(T), Err(E) };
2541
2542impl Foo {
2543    fn fn_ctr(&self) -> Foo { unimplemented!() }
2544    fn fn_ctr_with_args(&self, n: u32) -> Foo { unimplemented!() }
2545    fn fn_another(&self, n: u32) -> Bar { unimplemented!() }
2546    fn fn_ctr_wrapped(&self, ) -> Option<Self> { unimplemented!() }
2547    fn fn_ctr_wrapped_2(&self, ) -> Result<Self, Bar> { unimplemented!() }
2548    fn fn_ctr_wrapped_3(&self, ) -> Result<Bar, Self> { unimplemented!() } // Self is not the first type
2549    fn fn_ctr_wrapped_with_args(&self, m: u32) -> Option<Self> { unimplemented!() }
2550    fn fn_another_unit(&self) { unimplemented!() }
2551}
2552
2553fn test() {
2554    let a = self::Foo::$0;
2555}
2556"#,
2557            expect![[r#"
2558                [
2559                    (
2560                        "fn(&self, u32) -> Bar",
2561                        Some(
2562                            CompletionRelevanceFn {
2563                                has_params: true,
2564                                has_self_param: true,
2565                                return_type: Other,
2566                            },
2567                        ),
2568                    ),
2569                    (
2570                        "fn(&self)",
2571                        Some(
2572                            CompletionRelevanceFn {
2573                                has_params: true,
2574                                has_self_param: true,
2575                                return_type: Other,
2576                            },
2577                        ),
2578                    ),
2579                    (
2580                        "fn(&self) -> Foo",
2581                        Some(
2582                            CompletionRelevanceFn {
2583                                has_params: true,
2584                                has_self_param: true,
2585                                return_type: DirectConstructor,
2586                            },
2587                        ),
2588                    ),
2589                    (
2590                        "fn(&self, u32) -> Foo",
2591                        Some(
2592                            CompletionRelevanceFn {
2593                                has_params: true,
2594                                has_self_param: true,
2595                                return_type: DirectConstructor,
2596                            },
2597                        ),
2598                    ),
2599                    (
2600                        "fn(&self) -> Option<Foo>",
2601                        Some(
2602                            CompletionRelevanceFn {
2603                                has_params: true,
2604                                has_self_param: true,
2605                                return_type: Constructor,
2606                            },
2607                        ),
2608                    ),
2609                    (
2610                        "fn(&self) -> Result<Foo, Bar>",
2611                        Some(
2612                            CompletionRelevanceFn {
2613                                has_params: true,
2614                                has_self_param: true,
2615                                return_type: Constructor,
2616                            },
2617                        ),
2618                    ),
2619                    (
2620                        "fn(&self) -> Result<Bar, Foo>",
2621                        Some(
2622                            CompletionRelevanceFn {
2623                                has_params: true,
2624                                has_self_param: true,
2625                                return_type: Constructor,
2626                            },
2627                        ),
2628                    ),
2629                    (
2630                        "fn(&self, u32) -> Option<Foo>",
2631                        Some(
2632                            CompletionRelevanceFn {
2633                                has_params: true,
2634                                has_self_param: true,
2635                                return_type: Constructor,
2636                            },
2637                        ),
2638                    ),
2639                ]
2640            "#]],
2641        );
2642    }
2643
2644    #[test]
2645    fn constructor_order_relevance() {
2646        check_relevance(
2647            r#"
2648struct Foo;
2649struct FooBuilder;
2650struct Result<T>(T);
2651
2652impl Foo {
2653    fn fn_no_ret(&self) {}
2654    fn fn_ctr_with_args(input: u32) -> Foo { unimplemented!() }
2655    fn fn_direct_ctr() -> Self { unimplemented!() }
2656    fn fn_ctr() -> Result<Self> { unimplemented!() }
2657    fn fn_other() -> Result<u32> { unimplemented!() }
2658    fn fn_builder() -> FooBuilder { unimplemented!() }
2659}
2660
2661fn test() {
2662    let a = self::Foo::$0;
2663}
2664"#,
2665            // preference:
2666            // Direct Constructor
2667            // Direct Constructor with args
2668            // Builder
2669            // Constructor
2670            // Others
2671            expect![[r#"
2672                fn fn_direct_ctr() fn() -> Foo [type_could_unify]
2673                fn fn_ctr_with_args(…) fn(u32) -> Foo [type_could_unify]
2674                fn fn_builder() fn() -> FooBuilder [type_could_unify]
2675                fn fn_ctr() fn() -> Result<Foo> [type_could_unify]
2676                me fn_no_ret(…) fn(&self) [type_could_unify]
2677                fn fn_other() fn() -> Result<u32> [type_could_unify]
2678            "#]],
2679        );
2680
2681        //
2682    }
2683
2684    #[test]
2685    fn function_relevance_generic_1() {
2686        check_relevance(
2687            r#"
2688struct Foo<T: Default>(T);
2689struct FooBuilder;
2690struct Option<T>(T);
2691enum Result<T, E>{Ok(T), Err(E)};
2692
2693impl<T: Default> Foo<T> {
2694    fn fn_returns_unit(&self) {}
2695    fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
2696    fn fn_direct_ctr() -> Self { unimplemented!() }
2697    fn fn_ctr_wrapped() -> Option<Self> { unimplemented!() }
2698    fn fn_ctr_wrapped_2() -> Result<Self, u32> { unimplemented!() }
2699    fn fn_other() -> Option<u32> { unimplemented!() }
2700    fn fn_builder() -> FooBuilder { unimplemented!() }
2701}
2702
2703fn test() {
2704    let a = self::Foo::<u32>::$0;
2705}
2706                "#,
2707            expect![[r#"
2708                fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
2709                fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
2710                fn fn_builder() fn() -> FooBuilder [type_could_unify]
2711                fn fn_ctr_wrapped() fn() -> Option<Foo<T>> [type_could_unify]
2712                fn fn_ctr_wrapped_2() fn() -> Result<Foo<T>, u32> [type_could_unify]
2713                fn fn_other() fn() -> Option<u32> [type_could_unify]
2714                me fn_returns_unit(…) fn(&self) [type_could_unify]
2715            "#]],
2716        );
2717    }
2718
2719    #[test]
2720    fn function_relevance_generic_2() {
2721        // Generic 2
2722        check_relevance(
2723            r#"
2724struct Foo<T: Default>(T);
2725struct FooBuilder;
2726struct Option<T>(T);
2727enum Result<T, E>{Ok(T), Err(E)};
2728
2729impl<T: Default> Foo<T> {
2730    fn fn_no_ret(&self) {}
2731    fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
2732    fn fn_direct_ctr() -> Self { unimplemented!() }
2733    fn fn_ctr() -> Option<Self> { unimplemented!() }
2734    fn fn_ctr2() -> Result<Self, u32> { unimplemented!() }
2735    fn fn_other() -> Option<u32> { unimplemented!() }
2736    fn fn_builder() -> FooBuilder { unimplemented!() }
2737}
2738
2739fn test() {
2740    let a : Res<Foo<u32>> = Foo::$0;
2741}
2742                "#,
2743            expect![[r#"
2744                fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
2745                fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
2746                fn fn_builder() fn() -> FooBuilder [type_could_unify]
2747                fn fn_ctr() fn() -> Option<Foo<T>> [type_could_unify]
2748                fn fn_ctr2() fn() -> Result<Foo<T>, u32> [type_could_unify]
2749                me fn_no_ret(…) fn(&self) [type_could_unify]
2750                fn fn_other() fn() -> Option<u32> [type_could_unify]
2751            "#]],
2752        );
2753    }
2754
2755    #[test]
2756    fn struct_field_method_ref() {
2757        check_kinds(
2758            r#"
2759struct Foo { bar: u32, qux: fn() }
2760impl Foo { fn baz(&self) -> u32 { 0 } }
2761
2762fn foo(f: Foo) { let _: &u32 = f.b$0 }
2763"#,
2764            &[
2765                CompletionItemKind::SymbolKind(SymbolKind::Method),
2766                CompletionItemKind::SymbolKind(SymbolKind::Field),
2767            ],
2768            expect![[r#"
2769                [
2770                    CompletionItem {
2771                        label: "baz()",
2772                        detail_left: None,
2773                        detail_right: Some(
2774                            "fn(&self) -> u32",
2775                        ),
2776                        source_range: 109..110,
2777                        delete: 109..110,
2778                        insert: "baz()$0",
2779                        kind: SymbolKind(
2780                            Method,
2781                        ),
2782                        lookup: "baz",
2783                        detail: "fn(&self) -> u32",
2784                        relevance: CompletionRelevance {
2785                            exact_name_match: false,
2786                            type_match: None,
2787                            is_local: false,
2788                            trait_: None,
2789                            is_name_already_imported: false,
2790                            requires_import: false,
2791                            is_private_editable: false,
2792                            postfix_match: None,
2793                            function: Some(
2794                                CompletionRelevanceFn {
2795                                    has_params: true,
2796                                    has_self_param: true,
2797                                    return_type: Other,
2798                                },
2799                            ),
2800                            is_skipping_completion: false,
2801                        },
2802                        ref_match: "&@107",
2803                    },
2804                    CompletionItem {
2805                        label: "bar",
2806                        detail_left: None,
2807                        detail_right: Some(
2808                            "u32",
2809                        ),
2810                        source_range: 109..110,
2811                        delete: 109..110,
2812                        insert: "bar",
2813                        kind: SymbolKind(
2814                            Field,
2815                        ),
2816                        detail: "u32",
2817                        ref_match: "&@107",
2818                    },
2819                    CompletionItem {
2820                        label: "qux",
2821                        detail_left: None,
2822                        detail_right: Some(
2823                            "fn()",
2824                        ),
2825                        source_range: 109..110,
2826                        text_edit: TextEdit {
2827                            indels: [
2828                                Indel {
2829                                    insert: "(",
2830                                    delete: 107..107,
2831                                },
2832                                Indel {
2833                                    insert: "qux)()",
2834                                    delete: 109..110,
2835                                },
2836                            ],
2837                            annotation: None,
2838                        },
2839                        kind: SymbolKind(
2840                            Field,
2841                        ),
2842                        detail: "fn()",
2843                    },
2844                ]
2845            "#]],
2846        );
2847    }
2848
2849    #[test]
2850    fn expected_fn_type_ref() {
2851        check_kinds(
2852            r#"
2853struct S { field: fn() }
2854
2855fn foo() {
2856    let foo: fn() = S { fields: || {}}.fi$0;
2857}
2858"#,
2859            &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
2860            expect![[r#"
2861                [
2862                    CompletionItem {
2863                        label: "field",
2864                        detail_left: None,
2865                        detail_right: Some(
2866                            "fn()",
2867                        ),
2868                        source_range: 76..78,
2869                        delete: 76..78,
2870                        insert: "field",
2871                        kind: SymbolKind(
2872                            Field,
2873                        ),
2874                        detail: "fn()",
2875                        relevance: CompletionRelevance {
2876                            exact_name_match: false,
2877                            type_match: Some(
2878                                Exact,
2879                            ),
2880                            is_local: false,
2881                            trait_: None,
2882                            is_name_already_imported: false,
2883                            requires_import: false,
2884                            is_private_editable: false,
2885                            postfix_match: None,
2886                            function: None,
2887                            is_skipping_completion: false,
2888                        },
2889                    },
2890                ]
2891            "#]],
2892        )
2893    }
2894
2895    #[test]
2896    fn qualified_path_ref() {
2897        check_kinds(
2898            r#"
2899struct S;
2900
2901struct T;
2902impl T {
2903    fn foo() -> S {}
2904}
2905
2906fn bar(s: &S) {}
2907
2908fn main() {
2909    bar(T::$0);
2910}
2911"#,
2912            &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
2913            expect![[r#"
2914                [
2915                    CompletionItem {
2916                        label: "foo()",
2917                        detail_left: None,
2918                        detail_right: Some(
2919                            "fn() -> S",
2920                        ),
2921                        source_range: 95..95,
2922                        delete: 95..95,
2923                        insert: "foo()$0",
2924                        kind: SymbolKind(
2925                            Function,
2926                        ),
2927                        lookup: "foo",
2928                        detail: "fn() -> S",
2929                        relevance: CompletionRelevance {
2930                            exact_name_match: false,
2931                            type_match: None,
2932                            is_local: false,
2933                            trait_: None,
2934                            is_name_already_imported: false,
2935                            requires_import: false,
2936                            is_private_editable: false,
2937                            postfix_match: None,
2938                            function: Some(
2939                                CompletionRelevanceFn {
2940                                    has_params: false,
2941                                    has_self_param: false,
2942                                    return_type: Other,
2943                                },
2944                            ),
2945                            is_skipping_completion: false,
2946                        },
2947                        ref_match: "&@92",
2948                    },
2949                ]
2950            "#]],
2951        );
2952    }
2953
2954    #[test]
2955    fn generic_enum() {
2956        check_relevance(
2957            r#"
2958enum Foo<T> { A(T), B }
2959// bar() should not be an exact type match
2960// because the generic parameters are different
2961fn bar() -> Foo<u8> { Foo::B }
2962// FIXME baz() should be an exact type match
2963// because the types could unify, but it currently
2964// is not. This is due to the T here being
2965// TyKind::Placeholder rather than TyKind::Missing.
2966fn baz<T>() -> Foo<T> { Foo::B }
2967fn foo() {
2968    let foo: Foo<u32> = Foo::B;
2969    let _: Foo<u32> = f$0;
2970}
2971"#,
2972            expect![[r#"
2973                ev Foo::B Foo::B [type_could_unify]
2974                ev Foo::A(…) Foo::A(T) [type_could_unify]
2975                lc foo Foo<u32> [type+local]
2976                ex Foo::B  [type]
2977                ex foo  [type]
2978                en Foo Foo<{unknown}> [type_could_unify]
2979                fn bar() fn() -> Foo<u8> []
2980                fn baz() fn() -> Foo<T> []
2981                fn foo() fn() []
2982            "#]],
2983        );
2984    }
2985
2986    #[test]
2987    fn postfix_exact_match_is_high_priority() {
2988        cov_mark::check!(postfix_exact_match_is_high_priority);
2989        check_relevance_for_kinds(
2990            r#"
2991mod ops {
2992    pub trait Not {
2993        type Output;
2994        fn not(self) -> Self::Output;
2995    }
2996
2997    impl Not for bool {
2998        type Output = bool;
2999        fn not(self) -> bool { if self { false } else { true }}
3000    }
3001}
3002
3003fn main() {
3004    let _: bool = (9 > 2).not$0;
3005}
3006    "#,
3007            &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3008            expect![[r#"
3009                sn not !expr [snippet]
3010                sn box Box::new(expr) []
3011                sn call function(expr) []
3012                sn const const {} []
3013                sn dbg dbg!(expr) []
3014                sn dbgr dbg!(&expr) []
3015                sn deref *expr []
3016                sn if if expr {} []
3017                sn match match expr {} []
3018                sn ref &expr []
3019                sn refm &mut expr []
3020                sn return return expr []
3021                sn unsafe unsafe {} []
3022                sn while while expr {} []
3023                me not() fn(self) -> <Self as Not>::Output [requires_import]
3024            "#]],
3025        );
3026    }
3027
3028    #[test]
3029    fn postfix_inexact_match_is_low_priority() {
3030        cov_mark::check!(postfix_inexact_match_is_low_priority);
3031        check_relevance_for_kinds(
3032            r#"
3033struct S;
3034impl S {
3035    fn f(&self) {}
3036}
3037fn main() {
3038    S.$0
3039}
3040    "#,
3041            &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3042            expect![[r#"
3043                me f() fn(&self) []
3044                sn box Box::new(expr) []
3045                sn call function(expr) []
3046                sn const const {} []
3047                sn dbg dbg!(expr) []
3048                sn dbgr dbg!(&expr) []
3049                sn deref *expr []
3050                sn let let []
3051                sn letm let mut []
3052                sn match match expr {} []
3053                sn ref &expr []
3054                sn refm &mut expr []
3055                sn return return expr []
3056                sn unsafe unsafe {} []
3057            "#]],
3058        );
3059    }
3060
3061    #[test]
3062    fn flyimport_reduced_relevance() {
3063        check_relevance(
3064            r#"
3065mod std {
3066    pub mod io {
3067        pub trait BufRead {}
3068        pub struct BufReader;
3069        pub struct BufWriter;
3070    }
3071}
3072struct Buffer;
3073
3074fn f() {
3075    Buf$0
3076}
3077"#,
3078            expect![[r#"
3079                st Buffer Buffer []
3080                fn f() fn() []
3081                md std  []
3082                tt BufRead  [requires_import]
3083                st BufReader BufReader [requires_import]
3084                st BufWriter BufWriter [requires_import]
3085            "#]],
3086        );
3087    }
3088
3089    #[test]
3090    fn completes_struct_with_raw_identifier() {
3091        check_edit(
3092            "type",
3093            r#"
3094mod m { pub struct r#type {} }
3095fn main() {
3096    let r#type = m::t$0;
3097}
3098"#,
3099            r#"
3100mod m { pub struct r#type {} }
3101fn main() {
3102    let r#type = m::r#type;
3103}
3104"#,
3105        )
3106    }
3107
3108    #[test]
3109    fn completes_fn_with_raw_identifier() {
3110        check_edit(
3111            "type",
3112            r#"
3113mod m { pub fn r#type {} }
3114fn main() {
3115    m::t$0
3116}
3117"#,
3118            r#"
3119mod m { pub fn r#type {} }
3120fn main() {
3121    m::r#type();$0
3122}
3123"#,
3124        )
3125    }
3126
3127    #[test]
3128    fn completes_macro_with_raw_identifier() {
3129        check_edit(
3130            "let!",
3131            r#"
3132macro_rules! r#let { () => {} }
3133fn main() {
3134    $0
3135}
3136"#,
3137            r#"
3138macro_rules! r#let { () => {} }
3139fn main() {
3140    r#let!($0)
3141}
3142"#,
3143        )
3144    }
3145
3146    #[test]
3147    fn completes_variant_with_raw_identifier() {
3148        check_edit(
3149            "type",
3150            r#"
3151enum A { r#type }
3152fn main() {
3153    let a = A::t$0
3154}
3155"#,
3156            r#"
3157enum A { r#type }
3158fn main() {
3159    let a = A::r#type$0
3160}
3161"#,
3162        )
3163    }
3164
3165    #[test]
3166    fn completes_field_with_raw_identifier() {
3167        check_edit(
3168            "fn",
3169            r#"
3170mod r#type {
3171    pub struct r#struct {
3172        pub r#fn: u32
3173    }
3174}
3175
3176fn main() {
3177    let a = r#type::r#struct {};
3178    a.$0
3179}
3180"#,
3181            r#"
3182mod r#type {
3183    pub struct r#struct {
3184        pub r#fn: u32
3185    }
3186}
3187
3188fn main() {
3189    let a = r#type::r#struct {};
3190    a.r#fn
3191}
3192"#,
3193        )
3194    }
3195
3196    #[test]
3197    fn completes_const_with_raw_identifier() {
3198        check_edit(
3199            "type",
3200            r#"
3201struct r#struct {}
3202impl r#struct { pub const r#type: u8 = 1; }
3203fn main() {
3204    r#struct::t$0
3205}
3206"#,
3207            r#"
3208struct r#struct {}
3209impl r#struct { pub const r#type: u8 = 1; }
3210fn main() {
3211    r#struct::r#type
3212}
3213"#,
3214        )
3215    }
3216
3217    #[test]
3218    fn completes_type_alias_with_raw_identifier() {
3219        check_edit(
3220            "type type",
3221            r#"
3222struct r#struct {}
3223trait r#trait { type r#type; }
3224impl r#trait for r#struct { type t$0 }
3225"#,
3226            r#"
3227struct r#struct {}
3228trait r#trait { type r#type; }
3229impl r#trait for r#struct { type r#type = $0; }
3230"#,
3231        )
3232    }
3233
3234    #[test]
3235    fn field_access_includes_self() {
3236        check_edit(
3237            "length",
3238            r#"
3239struct S {
3240    length: i32
3241}
3242
3243impl S {
3244    fn some_fn(&self) {
3245        let l = len$0
3246    }
3247}
3248"#,
3249            r#"
3250struct S {
3251    length: i32
3252}
3253
3254impl S {
3255    fn some_fn(&self) {
3256        let l = self.length
3257    }
3258}
3259"#,
3260        )
3261    }
3262
3263    #[test]
3264    fn notable_traits_method_relevance() {
3265        check_kinds(
3266            r#"
3267#[doc(notable_trait)]
3268trait Write {
3269    fn write(&self);
3270    fn flush(&self);
3271}
3272
3273struct Writer;
3274
3275impl Write for Writer {
3276    fn write(&self) {}
3277    fn flush(&self) {}
3278}
3279
3280fn main() {
3281    Writer.$0
3282}
3283"#,
3284            &[
3285                CompletionItemKind::SymbolKind(SymbolKind::Method),
3286                CompletionItemKind::SymbolKind(SymbolKind::Field),
3287                CompletionItemKind::SymbolKind(SymbolKind::Function),
3288            ],
3289            expect![[r#"
3290                [
3291                    CompletionItem {
3292                        label: "flush()",
3293                        detail_left: Some(
3294                            "(as Write)",
3295                        ),
3296                        detail_right: Some(
3297                            "fn(&self)",
3298                        ),
3299                        source_range: 193..193,
3300                        delete: 193..193,
3301                        insert: "flush();$0",
3302                        kind: SymbolKind(
3303                            Method,
3304                        ),
3305                        lookup: "flush",
3306                        detail: "fn(&self)",
3307                        relevance: CompletionRelevance {
3308                            exact_name_match: false,
3309                            type_match: None,
3310                            is_local: false,
3311                            trait_: Some(
3312                                CompletionRelevanceTraitInfo {
3313                                    notable_trait: true,
3314                                    is_op_method: false,
3315                                },
3316                            ),
3317                            is_name_already_imported: false,
3318                            requires_import: false,
3319                            is_private_editable: false,
3320                            postfix_match: None,
3321                            function: None,
3322                            is_skipping_completion: false,
3323                        },
3324                    },
3325                    CompletionItem {
3326                        label: "write()",
3327                        detail_left: Some(
3328                            "(as Write)",
3329                        ),
3330                        detail_right: Some(
3331                            "fn(&self)",
3332                        ),
3333                        source_range: 193..193,
3334                        delete: 193..193,
3335                        insert: "write();$0",
3336                        kind: SymbolKind(
3337                            Method,
3338                        ),
3339                        lookup: "write",
3340                        detail: "fn(&self)",
3341                        relevance: CompletionRelevance {
3342                            exact_name_match: false,
3343                            type_match: None,
3344                            is_local: false,
3345                            trait_: Some(
3346                                CompletionRelevanceTraitInfo {
3347                                    notable_trait: true,
3348                                    is_op_method: false,
3349                                },
3350                            ),
3351                            is_name_already_imported: false,
3352                            requires_import: false,
3353                            is_private_editable: false,
3354                            postfix_match: None,
3355                            function: None,
3356                            is_skipping_completion: false,
3357                        },
3358                    },
3359                ]
3360            "#]],
3361        );
3362    }
3363}