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.could_unify_with(ctx.db, expected_without_ref))
635        && completion_ty.autoderef(ctx.db).any(|ty| ty == *expected_without_ref)
636    {
637        cov_mark::hit!(suggest_ref);
638        let mutability = if expected_type.is_mutable_reference() {
639            hir::Mutability::Mut
640        } else {
641            hir::Mutability::Shared
642        };
643        return Some(CompletionItemRefMode::Reference(mutability));
644    }
645
646    if let Some(completion_without_ref) = completion_without_ref
647        && completion_without_ref == *expected_type
648        && completion_without_ref.is_copy(ctx.db)
649    {
650        cov_mark::hit!(suggest_deref);
651        return Some(CompletionItemRefMode::Dereference);
652    }
653
654    None
655}
656
657fn path_ref_match(
658    completion: &CompletionContext<'_>,
659    path_ctx: &PathCompletionCtx<'_>,
660    ty: &hir::Type<'_>,
661    item: &mut Builder,
662) {
663    if let Some(original_path) = &path_ctx.original_path {
664        // At least one char was typed by the user already, in that case look for the original path
665        if let Some(original_path) = completion.sema.original_ast_node(original_path.clone())
666            && let Some(ref_mode) = compute_ref_match(completion, ty)
667        {
668            item.ref_match(ref_mode, original_path.syntax().text_range().start());
669        }
670    } else {
671        // completion requested on an empty identifier, there is no path here yet.
672        // FIXME: This might create inconsistent completions where we show a ref match in macro inputs
673        // as long as nothing was typed yet
674        if let Some(ref_mode) = compute_ref_match(completion, ty) {
675            item.ref_match(ref_mode, completion.position.offset);
676        }
677    }
678}
679
680#[cfg(test)]
681mod tests {
682    use std::cmp;
683
684    use expect_test::{Expect, expect};
685    use ide_db::SymbolKind;
686    use itertools::Itertools;
687
688    use crate::{
689        CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
690        item::CompletionRelevanceTypeMatch,
691        tests::{TEST_CONFIG, check_edit, do_completion, get_all_items},
692    };
693
694    #[track_caller]
695    fn check(
696        #[rust_analyzer::rust_fixture] ra_fixture: &str,
697        kind: impl Into<CompletionItemKind>,
698        expect: Expect,
699    ) {
700        let actual = do_completion(ra_fixture, kind.into());
701        expect.assert_debug_eq(&actual);
702    }
703
704    #[track_caller]
705    fn check_kinds(
706        #[rust_analyzer::rust_fixture] ra_fixture: &str,
707        kinds: &[CompletionItemKind],
708        expect: Expect,
709    ) {
710        let actual: Vec<_> =
711            kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
712        expect.assert_debug_eq(&actual);
713    }
714
715    #[track_caller]
716    fn check_function_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
717        let actual: Vec<_> =
718            do_completion(ra_fixture, CompletionItemKind::SymbolKind(SymbolKind::Method))
719                .into_iter()
720                .map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
721                .collect();
722
723        expect.assert_debug_eq(&actual);
724    }
725
726    #[track_caller]
727    fn check_relevance_for_kinds(
728        #[rust_analyzer::rust_fixture] ra_fixture: &str,
729        kinds: &[CompletionItemKind],
730        expect: Expect,
731    ) {
732        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
733        actual.retain(|it| kinds.contains(&it.kind));
734        actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
735        check_relevance_(actual, expect);
736    }
737
738    #[track_caller]
739    fn check_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
740        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
741        actual.retain(|it| it.kind != CompletionItemKind::Snippet);
742        actual.retain(|it| it.kind != CompletionItemKind::Keyword);
743        actual.retain(|it| it.kind != CompletionItemKind::BuiltinType);
744        actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone()));
745        check_relevance_(actual, expect);
746    }
747
748    #[track_caller]
749    fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
750        let actual = actual
751            .into_iter()
752            .flat_map(|it| {
753                let mut items = vec![];
754
755                let tag = it.kind.tag();
756                let relevance = display_relevance(it.relevance);
757                items.push(format!(
758                    "{tag} {} {} {relevance}\n",
759                    it.label.primary,
760                    it.label.detail_right.clone().unwrap_or_default(),
761                ));
762
763                if let Some((label, _indel, relevance)) = it.ref_match() {
764                    let relevance = display_relevance(relevance);
765
766                    items.push(format!("{tag} {label} {relevance}\n"));
767                }
768
769                items
770            })
771            .collect::<String>();
772
773        expect.assert_eq(&actual);
774
775        fn display_relevance(relevance: CompletionRelevance) -> String {
776            let relevance_factors = vec![
777                (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
778                (
779                    relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
780                    "type_could_unify",
781                ),
782                (relevance.exact_name_match, "name"),
783                (relevance.is_local, "local"),
784                (
785                    relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
786                    "snippet",
787                ),
788                (relevance.trait_.is_some_and(|it| it.is_op_method), "op_method"),
789                (relevance.requires_import, "requires_import"),
790            ]
791            .into_iter()
792            .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
793            .join("+");
794
795            format!("[{relevance_factors}]")
796        }
797    }
798
799    #[test]
800    fn set_struct_type_completion_info() {
801        check_relevance(
802            r#"
803//- /lib.rs crate:dep
804
805pub mod test_mod_b {
806    pub struct Struct {}
807}
808
809pub mod test_mod_a {
810    pub struct Struct {}
811}
812
813//- /main.rs crate:main deps:dep
814
815fn test(input: dep::test_mod_b::Struct) { }
816
817fn main() {
818    test(Struct$0);
819}
820"#,
821            expect![[r#"
822                st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct {  } [type_could_unify]
823                ex dep::test_mod_b::Struct {  }  [type_could_unify]
824                st Struct Struct [type_could_unify+requires_import]
825                md dep  []
826                fn main() fn() []
827                fn test(…) fn(Struct) []
828                st Struct Struct [requires_import]
829            "#]],
830        );
831    }
832
833    #[test]
834    fn set_union_type_completion_info() {
835        check_relevance(
836            r#"
837//- /lib.rs crate:dep
838
839pub mod test_mod_b {
840    pub union Union {
841        a: i32,
842        b: i32
843    }
844}
845
846pub mod test_mod_a {
847    pub enum Union {
848        a: i32,
849        b: i32
850    }
851}
852
853//- /main.rs crate:main deps:dep
854
855fn test(input: dep::test_mod_b::Union) { }
856
857fn main() {
858    test(Union$0);
859}
860"#,
861            expect![[r#"
862                un Union Union [type_could_unify+requires_import]
863                md dep  []
864                fn main() fn() []
865                fn test(…) fn(Union) []
866                en Union Union [requires_import]
867            "#]],
868        );
869    }
870
871    #[test]
872    fn set_enum_type_completion_info() {
873        check_relevance(
874            r#"
875//- /lib.rs crate:dep
876
877pub mod test_mod_b {
878    pub enum Enum {
879        variant
880    }
881}
882
883pub mod test_mod_a {
884    pub enum Enum {
885        variant
886    }
887}
888
889//- /main.rs crate:main deps:dep
890
891fn test(input: dep::test_mod_b::Enum) { }
892
893fn main() {
894    test(Enum$0);
895}
896"#,
897            expect![[r#"
898                ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type_could_unify]
899                ex dep::test_mod_b::Enum::variant  [type_could_unify]
900                en Enum Enum [type_could_unify+requires_import]
901                md dep  []
902                fn main() fn() []
903                fn test(…) fn(Enum) []
904                en Enum Enum [requires_import]
905            "#]],
906        );
907    }
908
909    #[test]
910    fn set_enum_variant_type_completion_info() {
911        check_relevance(
912            r#"
913//- /lib.rs crate:dep
914
915pub mod test_mod_b {
916    pub enum Enum {
917        Variant
918    }
919}
920
921pub mod test_mod_a {
922    pub enum Enum {
923        Variant
924    }
925}
926
927//- /main.rs crate:main deps:dep
928
929fn test(input: dep::test_mod_b::Enum) { }
930
931fn main() {
932    test(Variant$0);
933}
934"#,
935            expect![[r#"
936                ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type_could_unify]
937                ex dep::test_mod_b::Enum::Variant  [type_could_unify]
938                md dep  []
939                fn main() fn() []
940                fn test(…) fn(Enum) []
941            "#]],
942        );
943    }
944
945    #[test]
946    fn set_fn_type_completion_info() {
947        check_relevance(
948            r#"
949//- /lib.rs crate:dep
950
951pub mod test_mod_b {
952    pub fn function(j: isize) -> i32 {}
953}
954
955pub mod test_mod_a {
956    pub fn function(i: usize) -> i32 {}
957}
958
959//- /main.rs crate:main deps:dep
960
961fn test(input: fn(usize) -> i32) { }
962
963fn main() {
964    test(function$0);
965}
966"#,
967            expect![[r#"
968                md dep  []
969                fn main() fn() []
970                fn test(…) fn(fn(usize) -> i32) []
971                fn function fn(usize) -> i32 [requires_import]
972                fn function(…) fn(isize) -> i32 [requires_import]
973            "#]],
974        );
975    }
976
977    #[test]
978    fn set_const_type_completion_info() {
979        check_relevance(
980            r#"
981//- /lib.rs crate:dep
982
983pub mod test_mod_b {
984    pub const CONST: i32 = 1;
985}
986
987pub mod test_mod_a {
988    pub const CONST: i64 = 2;
989}
990
991//- /main.rs crate:main deps:dep
992
993fn test(input: i32) { }
994
995fn main() {
996    test(CONST$0);
997}
998"#,
999            expect![[r#"
1000                ct CONST i32 [type_could_unify+requires_import]
1001                md dep  []
1002                fn main() fn() []
1003                fn test(…) fn(i32) []
1004                ct CONST i64 [requires_import]
1005            "#]],
1006        );
1007    }
1008
1009    #[test]
1010    fn set_static_type_completion_info() {
1011        check_relevance(
1012            r#"
1013//- /lib.rs crate:dep
1014
1015pub mod test_mod_b {
1016    pub static STATIC: i32 = 5;
1017}
1018
1019pub mod test_mod_a {
1020    pub static STATIC: i64 = 5;
1021}
1022
1023//- /main.rs crate:main deps:dep
1024
1025fn test(input: i32) { }
1026
1027fn main() {
1028    test(STATIC$0);
1029}
1030"#,
1031            expect![[r#"
1032                sc STATIC i32 [type_could_unify+requires_import]
1033                md dep  []
1034                fn main() fn() []
1035                fn test(…) fn(i32) []
1036                sc STATIC i64 [requires_import]
1037            "#]],
1038        );
1039    }
1040
1041    #[test]
1042    fn set_self_type_completion_info_with_params() {
1043        check_relevance(
1044            r#"
1045//- /lib.rs crate:dep
1046pub struct Struct;
1047
1048impl Struct {
1049    pub fn Function(&self, input: i32) -> bool {
1050                false
1051    }
1052}
1053
1054
1055//- /main.rs crate:main deps:dep
1056
1057use dep::Struct;
1058
1059
1060fn test(input: fn(&dep::Struct, i32) -> bool) { }
1061
1062fn main() {
1063    test(Struct::Function$0);
1064}
1065
1066"#,
1067            expect![[r#"
1068                me Function fn(&self, i32) -> bool []
1069            "#]],
1070        );
1071    }
1072
1073    #[test]
1074    fn set_self_type_completion_info() {
1075        check_relevance(
1076            r#"
1077//- /main.rs crate:main
1078
1079struct Struct;
1080
1081impl Struct {
1082fn test(&self) {
1083        func(Self$0);
1084    }
1085}
1086
1087fn func(input: Struct) { }
1088
1089"#,
1090            expect![[r#"
1091                st Self Self [type]
1092                st Struct Struct [type]
1093                sp Self Struct [type]
1094                st Struct Struct [type]
1095                ex Struct  [type]
1096                lc self &Struct [local]
1097                fn func(…) fn(Struct) []
1098                me self.test() fn(&self) []
1099            "#]],
1100        );
1101    }
1102
1103    #[test]
1104    fn set_builtin_type_completion_info() {
1105        check_relevance(
1106            r#"
1107//- /main.rs crate:main
1108
1109fn test(input: bool) { }
1110    pub Input: bool = false;
1111
1112fn main() {
1113    let input = false;
1114    let inputbad = 3;
1115    test(inp$0);
1116}
1117"#,
1118            expect![[r#"
1119                lc input bool [type+name+local]
1120                ex false  [type]
1121                ex input  [type]
1122                ex true  [type]
1123                lc inputbad i32 [local]
1124                fn main() fn() []
1125                fn test(…) fn(bool) []
1126            "#]],
1127        );
1128    }
1129
1130    #[test]
1131    fn enum_detail_includes_record_fields() {
1132        check(
1133            r#"
1134enum Foo { Foo { x: i32, y: i32 } }
1135
1136fn main() { Foo::Fo$0 }
1137"#,
1138            SymbolKind::Variant,
1139            expect![[r#"
1140                [
1141                    CompletionItem {
1142                        label: "Foo {…}",
1143                        detail_left: None,
1144                        detail_right: Some(
1145                            "Foo { x: i32, y: i32 }",
1146                        ),
1147                        source_range: 54..56,
1148                        delete: 54..56,
1149                        insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
1150                        kind: SymbolKind(
1151                            Variant,
1152                        ),
1153                        lookup: "Foo{}",
1154                        detail: "Foo { x: i32, y: i32 }",
1155                        relevance: CompletionRelevance {
1156                            exact_name_match: false,
1157                            type_match: None,
1158                            is_local: false,
1159                            trait_: None,
1160                            is_name_already_imported: false,
1161                            requires_import: false,
1162                            is_private_editable: false,
1163                            postfix_match: None,
1164                            function: Some(
1165                                CompletionRelevanceFn {
1166                                    has_params: true,
1167                                    has_self_param: false,
1168                                    return_type: DirectConstructor,
1169                                },
1170                            ),
1171                            is_skipping_completion: false,
1172                        },
1173                        trigger_call_info: true,
1174                    },
1175                ]
1176            "#]],
1177        );
1178    }
1179
1180    #[test]
1181    fn enum_detail_includes_tuple_fields() {
1182        check(
1183            r#"
1184enum Foo { Foo (i32, i32) }
1185
1186fn main() { Foo::Fo$0 }
1187"#,
1188            SymbolKind::Variant,
1189            expect![[r#"
1190                [
1191                    CompletionItem {
1192                        label: "Foo(…)",
1193                        detail_left: None,
1194                        detail_right: Some(
1195                            "Foo(i32, i32)",
1196                        ),
1197                        source_range: 46..48,
1198                        delete: 46..48,
1199                        insert: "Foo(${1:()}, ${2:()})$0",
1200                        kind: SymbolKind(
1201                            Variant,
1202                        ),
1203                        lookup: "Foo()",
1204                        detail: "Foo(i32, i32)",
1205                        relevance: CompletionRelevance {
1206                            exact_name_match: false,
1207                            type_match: None,
1208                            is_local: false,
1209                            trait_: None,
1210                            is_name_already_imported: false,
1211                            requires_import: false,
1212                            is_private_editable: false,
1213                            postfix_match: None,
1214                            function: Some(
1215                                CompletionRelevanceFn {
1216                                    has_params: true,
1217                                    has_self_param: false,
1218                                    return_type: DirectConstructor,
1219                                },
1220                            ),
1221                            is_skipping_completion: false,
1222                        },
1223                        trigger_call_info: true,
1224                    },
1225                ]
1226            "#]],
1227        );
1228    }
1229
1230    #[test]
1231    fn fn_detail_includes_args_and_return_type() {
1232        check(
1233            r#"
1234fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
1235
1236fn main() { fo$0 }
1237"#,
1238            SymbolKind::Function,
1239            expect![[r#"
1240                [
1241                    CompletionItem {
1242                        label: "foo(…)",
1243                        detail_left: None,
1244                        detail_right: Some(
1245                            "fn(u32, u32, T) -> (u32, T)",
1246                        ),
1247                        source_range: 68..70,
1248                        delete: 68..70,
1249                        insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
1250                        kind: SymbolKind(
1251                            Function,
1252                        ),
1253                        lookup: "foo",
1254                        detail: "fn(u32, u32, T) -> (u32, T)",
1255                        trigger_call_info: true,
1256                    },
1257                    CompletionItem {
1258                        label: "main()",
1259                        detail_left: None,
1260                        detail_right: Some(
1261                            "fn()",
1262                        ),
1263                        source_range: 68..70,
1264                        delete: 68..70,
1265                        insert: "main();$0",
1266                        kind: SymbolKind(
1267                            Function,
1268                        ),
1269                        lookup: "main",
1270                        detail: "fn()",
1271                    },
1272                ]
1273            "#]],
1274        );
1275    }
1276
1277    #[test]
1278    fn fn_detail_includes_variadics() {
1279        check(
1280            r#"
1281unsafe extern "C" fn foo(a: u32, b: u32, ...) {}
1282
1283fn main() { fo$0 }
1284"#,
1285            SymbolKind::Function,
1286            expect![[r#"
1287                [
1288                    CompletionItem {
1289                        label: "foo(…)",
1290                        detail_left: None,
1291                        detail_right: Some(
1292                            "unsafe fn(u32, u32, ...)",
1293                        ),
1294                        source_range: 62..64,
1295                        delete: 62..64,
1296                        insert: "foo(${1:a}, ${2:b});$0",
1297                        kind: SymbolKind(
1298                            Function,
1299                        ),
1300                        lookup: "foo",
1301                        detail: "unsafe fn(u32, u32, ...)",
1302                        trigger_call_info: true,
1303                    },
1304                    CompletionItem {
1305                        label: "main()",
1306                        detail_left: None,
1307                        detail_right: Some(
1308                            "fn()",
1309                        ),
1310                        source_range: 62..64,
1311                        delete: 62..64,
1312                        insert: "main();$0",
1313                        kind: SymbolKind(
1314                            Function,
1315                        ),
1316                        lookup: "main",
1317                        detail: "fn()",
1318                    },
1319                ]
1320            "#]],
1321        );
1322    }
1323
1324    #[test]
1325    fn enum_detail_just_name_for_unit() {
1326        check(
1327            r#"
1328enum Foo { Foo }
1329
1330fn main() { Foo::Fo$0 }
1331"#,
1332            SymbolKind::Variant,
1333            expect![[r#"
1334                [
1335                    CompletionItem {
1336                        label: "Foo",
1337                        detail_left: None,
1338                        detail_right: Some(
1339                            "Foo",
1340                        ),
1341                        source_range: 35..37,
1342                        delete: 35..37,
1343                        insert: "Foo$0",
1344                        kind: SymbolKind(
1345                            Variant,
1346                        ),
1347                        detail: "Foo",
1348                        relevance: CompletionRelevance {
1349                            exact_name_match: false,
1350                            type_match: None,
1351                            is_local: false,
1352                            trait_: None,
1353                            is_name_already_imported: false,
1354                            requires_import: false,
1355                            is_private_editable: false,
1356                            postfix_match: None,
1357                            function: Some(
1358                                CompletionRelevanceFn {
1359                                    has_params: false,
1360                                    has_self_param: false,
1361                                    return_type: DirectConstructor,
1362                                },
1363                            ),
1364                            is_skipping_completion: false,
1365                        },
1366                        trigger_call_info: true,
1367                    },
1368                ]
1369            "#]],
1370        );
1371    }
1372
1373    #[test]
1374    fn lookup_enums_by_two_qualifiers() {
1375        check_kinds(
1376            r#"
1377mod m {
1378    pub enum Spam { Foo, Bar(i32) }
1379}
1380fn main() { let _: m::Spam = S$0 }
1381"#,
1382            &[
1383                CompletionItemKind::SymbolKind(SymbolKind::Function),
1384                CompletionItemKind::SymbolKind(SymbolKind::Module),
1385                CompletionItemKind::SymbolKind(SymbolKind::Variant),
1386            ],
1387            expect![[r#"
1388                [
1389                    CompletionItem {
1390                        label: "main()",
1391                        detail_left: None,
1392                        detail_right: Some(
1393                            "fn()",
1394                        ),
1395                        source_range: 75..76,
1396                        delete: 75..76,
1397                        insert: "main();$0",
1398                        kind: SymbolKind(
1399                            Function,
1400                        ),
1401                        lookup: "main",
1402                        detail: "fn()",
1403                    },
1404                    CompletionItem {
1405                        label: "m",
1406                        detail_left: None,
1407                        detail_right: None,
1408                        source_range: 75..76,
1409                        delete: 75..76,
1410                        insert: "m",
1411                        kind: SymbolKind(
1412                            Module,
1413                        ),
1414                    },
1415                    CompletionItem {
1416                        label: "m::Spam::Bar(…)",
1417                        detail_left: None,
1418                        detail_right: Some(
1419                            "m::Spam::Bar(i32)",
1420                        ),
1421                        source_range: 75..76,
1422                        delete: 75..76,
1423                        insert: "m::Spam::Bar(${1:()})$0",
1424                        kind: SymbolKind(
1425                            Variant,
1426                        ),
1427                        lookup: "Spam::Bar()",
1428                        detail: "m::Spam::Bar(i32)",
1429                        relevance: CompletionRelevance {
1430                            exact_name_match: false,
1431                            type_match: Some(
1432                                Exact,
1433                            ),
1434                            is_local: false,
1435                            trait_: None,
1436                            is_name_already_imported: false,
1437                            requires_import: false,
1438                            is_private_editable: false,
1439                            postfix_match: None,
1440                            function: Some(
1441                                CompletionRelevanceFn {
1442                                    has_params: true,
1443                                    has_self_param: false,
1444                                    return_type: DirectConstructor,
1445                                },
1446                            ),
1447                            is_skipping_completion: false,
1448                        },
1449                        trigger_call_info: true,
1450                    },
1451                    CompletionItem {
1452                        label: "m::Spam::Foo",
1453                        detail_left: None,
1454                        detail_right: Some(
1455                            "m::Spam::Foo",
1456                        ),
1457                        source_range: 75..76,
1458                        delete: 75..76,
1459                        insert: "m::Spam::Foo$0",
1460                        kind: SymbolKind(
1461                            Variant,
1462                        ),
1463                        lookup: "Spam::Foo",
1464                        detail: "m::Spam::Foo",
1465                        relevance: CompletionRelevance {
1466                            exact_name_match: false,
1467                            type_match: Some(
1468                                Exact,
1469                            ),
1470                            is_local: false,
1471                            trait_: None,
1472                            is_name_already_imported: false,
1473                            requires_import: false,
1474                            is_private_editable: false,
1475                            postfix_match: None,
1476                            function: Some(
1477                                CompletionRelevanceFn {
1478                                    has_params: false,
1479                                    has_self_param: false,
1480                                    return_type: DirectConstructor,
1481                                },
1482                            ),
1483                            is_skipping_completion: false,
1484                        },
1485                        trigger_call_info: true,
1486                    },
1487                ]
1488            "#]],
1489        )
1490    }
1491
1492    #[test]
1493    fn sets_deprecated_flag_in_items() {
1494        check(
1495            r#"
1496#[deprecated]
1497fn something_deprecated() {}
1498
1499fn main() { som$0 }
1500"#,
1501            SymbolKind::Function,
1502            expect![[r#"
1503                [
1504                    CompletionItem {
1505                        label: "main()",
1506                        detail_left: None,
1507                        detail_right: Some(
1508                            "fn()",
1509                        ),
1510                        source_range: 56..59,
1511                        delete: 56..59,
1512                        insert: "main();$0",
1513                        kind: SymbolKind(
1514                            Function,
1515                        ),
1516                        lookup: "main",
1517                        detail: "fn()",
1518                    },
1519                    CompletionItem {
1520                        label: "something_deprecated()",
1521                        detail_left: None,
1522                        detail_right: Some(
1523                            "fn()",
1524                        ),
1525                        source_range: 56..59,
1526                        delete: 56..59,
1527                        insert: "something_deprecated();$0",
1528                        kind: SymbolKind(
1529                            Function,
1530                        ),
1531                        lookup: "something_deprecated",
1532                        detail: "fn()",
1533                        deprecated: true,
1534                    },
1535                ]
1536            "#]],
1537        );
1538
1539        check(
1540            r#"
1541struct A { #[deprecated] the_field: u32 }
1542fn foo() { A { the$0 } }
1543"#,
1544            SymbolKind::Field,
1545            expect![[r#"
1546                [
1547                    CompletionItem {
1548                        label: "the_field",
1549                        detail_left: None,
1550                        detail_right: Some(
1551                            "u32",
1552                        ),
1553                        source_range: 57..60,
1554                        delete: 57..60,
1555                        insert: "the_field",
1556                        kind: SymbolKind(
1557                            Field,
1558                        ),
1559                        detail: "u32",
1560                        deprecated: true,
1561                        relevance: CompletionRelevance {
1562                            exact_name_match: false,
1563                            type_match: Some(
1564                                CouldUnify,
1565                            ),
1566                            is_local: false,
1567                            trait_: None,
1568                            is_name_already_imported: false,
1569                            requires_import: false,
1570                            is_private_editable: false,
1571                            postfix_match: None,
1572                            function: None,
1573                            is_skipping_completion: false,
1574                        },
1575                    },
1576                ]
1577            "#]],
1578        );
1579    }
1580
1581    #[test]
1582    fn renders_docs() {
1583        check_kinds(
1584            r#"
1585struct S {
1586    /// Field docs
1587    foo:
1588}
1589impl S {
1590    /// Method docs
1591    fn bar(self) { self.$0 }
1592}"#,
1593            &[
1594                CompletionItemKind::SymbolKind(SymbolKind::Method),
1595                CompletionItemKind::SymbolKind(SymbolKind::Field),
1596            ],
1597            expect![[r#"
1598                [
1599                    CompletionItem {
1600                        label: "bar()",
1601                        detail_left: None,
1602                        detail_right: Some(
1603                            "fn(self)",
1604                        ),
1605                        source_range: 94..94,
1606                        delete: 94..94,
1607                        insert: "bar();$0",
1608                        kind: SymbolKind(
1609                            Method,
1610                        ),
1611                        lookup: "bar",
1612                        detail: "fn(self)",
1613                        documentation: Documentation(
1614                            "Method docs",
1615                        ),
1616                        relevance: CompletionRelevance {
1617                            exact_name_match: false,
1618                            type_match: None,
1619                            is_local: false,
1620                            trait_: None,
1621                            is_name_already_imported: false,
1622                            requires_import: false,
1623                            is_private_editable: false,
1624                            postfix_match: None,
1625                            function: Some(
1626                                CompletionRelevanceFn {
1627                                    has_params: true,
1628                                    has_self_param: true,
1629                                    return_type: Other,
1630                                },
1631                            ),
1632                            is_skipping_completion: false,
1633                        },
1634                    },
1635                    CompletionItem {
1636                        label: "foo",
1637                        detail_left: None,
1638                        detail_right: Some(
1639                            "{unknown}",
1640                        ),
1641                        source_range: 94..94,
1642                        delete: 94..94,
1643                        insert: "foo",
1644                        kind: SymbolKind(
1645                            Field,
1646                        ),
1647                        detail: "{unknown}",
1648                        documentation: Documentation(
1649                            "Field docs",
1650                        ),
1651                    },
1652                ]
1653            "#]],
1654        );
1655
1656        check_kinds(
1657            r#"
1658use self::my$0;
1659
1660/// mod docs
1661mod my { }
1662
1663/// enum docs
1664enum E {
1665    /// variant docs
1666    V
1667}
1668use self::E::*;
1669"#,
1670            &[
1671                CompletionItemKind::SymbolKind(SymbolKind::Module),
1672                CompletionItemKind::SymbolKind(SymbolKind::Variant),
1673                CompletionItemKind::SymbolKind(SymbolKind::Enum),
1674            ],
1675            expect![[r#"
1676                [
1677                    CompletionItem {
1678                        label: "my",
1679                        detail_left: None,
1680                        detail_right: None,
1681                        source_range: 10..12,
1682                        delete: 10..12,
1683                        insert: "my",
1684                        kind: SymbolKind(
1685                            Module,
1686                        ),
1687                        documentation: Documentation(
1688                            "mod docs",
1689                        ),
1690                    },
1691                    CompletionItem {
1692                        label: "V",
1693                        detail_left: None,
1694                        detail_right: Some(
1695                            "V",
1696                        ),
1697                        source_range: 10..12,
1698                        delete: 10..12,
1699                        insert: "V$0",
1700                        kind: SymbolKind(
1701                            Variant,
1702                        ),
1703                        detail: "V",
1704                        documentation: Documentation(
1705                            "variant docs",
1706                        ),
1707                        relevance: CompletionRelevance {
1708                            exact_name_match: false,
1709                            type_match: None,
1710                            is_local: false,
1711                            trait_: None,
1712                            is_name_already_imported: false,
1713                            requires_import: false,
1714                            is_private_editable: false,
1715                            postfix_match: None,
1716                            function: Some(
1717                                CompletionRelevanceFn {
1718                                    has_params: false,
1719                                    has_self_param: false,
1720                                    return_type: DirectConstructor,
1721                                },
1722                            ),
1723                            is_skipping_completion: false,
1724                        },
1725                        trigger_call_info: true,
1726                    },
1727                    CompletionItem {
1728                        label: "E",
1729                        detail_left: None,
1730                        detail_right: Some(
1731                            "E",
1732                        ),
1733                        source_range: 10..12,
1734                        delete: 10..12,
1735                        insert: "E",
1736                        kind: SymbolKind(
1737                            Enum,
1738                        ),
1739                        detail: "E",
1740                        documentation: Documentation(
1741                            "enum docs",
1742                        ),
1743                    },
1744                ]
1745            "#]],
1746        )
1747    }
1748
1749    #[test]
1750    fn dont_render_attrs() {
1751        check(
1752            r#"
1753struct S;
1754impl S {
1755    #[inline]
1756    fn the_method(&self) { }
1757}
1758fn foo(s: S) { s.$0 }
1759"#,
1760            CompletionItemKind::SymbolKind(SymbolKind::Method),
1761            expect![[r#"
1762                [
1763                    CompletionItem {
1764                        label: "the_method()",
1765                        detail_left: None,
1766                        detail_right: Some(
1767                            "fn(&self)",
1768                        ),
1769                        source_range: 81..81,
1770                        delete: 81..81,
1771                        insert: "the_method();$0",
1772                        kind: SymbolKind(
1773                            Method,
1774                        ),
1775                        lookup: "the_method",
1776                        detail: "fn(&self)",
1777                        relevance: CompletionRelevance {
1778                            exact_name_match: false,
1779                            type_match: None,
1780                            is_local: false,
1781                            trait_: None,
1782                            is_name_already_imported: false,
1783                            requires_import: false,
1784                            is_private_editable: false,
1785                            postfix_match: None,
1786                            function: Some(
1787                                CompletionRelevanceFn {
1788                                    has_params: true,
1789                                    has_self_param: true,
1790                                    return_type: Other,
1791                                },
1792                            ),
1793                            is_skipping_completion: false,
1794                        },
1795                    },
1796                ]
1797            "#]],
1798        )
1799    }
1800
1801    #[test]
1802    fn no_call_parens_if_fn_ptr_needed() {
1803        cov_mark::check!(no_call_parens_if_fn_ptr_needed);
1804        check_edit(
1805            "foo",
1806            r#"
1807fn foo(foo: u8, bar: u8) {}
1808struct ManualVtable { f: fn(u8, u8) }
1809
1810fn main() -> ManualVtable {
1811    ManualVtable { f: f$0 }
1812}
1813"#,
1814            r#"
1815fn foo(foo: u8, bar: u8) {}
1816struct ManualVtable { f: fn(u8, u8) }
1817
1818fn main() -> ManualVtable {
1819    ManualVtable { f: foo }
1820}
1821"#,
1822        );
1823        check_edit(
1824            "type",
1825            r#"
1826struct RawIdentTable { r#type: u32 }
1827
1828fn main() -> RawIdentTable {
1829    RawIdentTable { t$0: 42 }
1830}
1831"#,
1832            r#"
1833struct RawIdentTable { r#type: u32 }
1834
1835fn main() -> RawIdentTable {
1836    RawIdentTable { r#type: 42 }
1837}
1838"#,
1839        );
1840    }
1841
1842    #[test]
1843    fn no_parens_in_use_item() {
1844        check_edit(
1845            "foo",
1846            r#"
1847mod m { pub fn foo() {} }
1848use crate::m::f$0;
1849"#,
1850            r#"
1851mod m { pub fn foo() {} }
1852use crate::m::foo;
1853"#,
1854        );
1855    }
1856
1857    #[test]
1858    fn no_parens_in_call() {
1859        check_edit(
1860            "foo",
1861            r#"
1862fn foo(x: i32) {}
1863fn main() { f$0(); }
1864"#,
1865            r#"
1866fn foo(x: i32) {}
1867fn main() { foo(); }
1868"#,
1869        );
1870        check_edit(
1871            "foo",
1872            r#"
1873struct Foo;
1874impl Foo { fn foo(&self){} }
1875fn f(foo: &Foo) { foo.f$0(); }
1876"#,
1877            r#"
1878struct Foo;
1879impl Foo { fn foo(&self){} }
1880fn f(foo: &Foo) { foo.foo(); }
1881"#,
1882        );
1883    }
1884
1885    #[test]
1886    fn inserts_angle_brackets_for_generics() {
1887        cov_mark::check!(inserts_angle_brackets_for_generics);
1888        check_edit(
1889            "Vec",
1890            r#"
1891struct Vec<T> {}
1892fn foo(xs: Ve$0)
1893"#,
1894            r#"
1895struct Vec<T> {}
1896fn foo(xs: Vec<$0>)
1897"#,
1898        );
1899        check_edit(
1900            "Vec",
1901            r#"
1902type Vec<T> = (T,);
1903fn foo(xs: Ve$0)
1904"#,
1905            r#"
1906type Vec<T> = (T,);
1907fn foo(xs: Vec<$0>)
1908"#,
1909        );
1910        check_edit(
1911            "Vec",
1912            r#"
1913struct Vec<T = i128> {}
1914fn foo(xs: Ve$0)
1915"#,
1916            r#"
1917struct Vec<T = i128> {}
1918fn foo(xs: Vec)
1919"#,
1920        );
1921        check_edit(
1922            "Vec",
1923            r#"
1924struct Vec<T> {}
1925fn foo(xs: Ve$0<i128>)
1926"#,
1927            r#"
1928struct Vec<T> {}
1929fn foo(xs: Vec<i128>)
1930"#,
1931        );
1932    }
1933
1934    #[test]
1935    fn active_param_relevance() {
1936        check_relevance(
1937            r#"
1938struct S { foo: i64, bar: u32, baz: u32 }
1939fn test(bar: u32) { }
1940fn foo(s: S) { test(s.$0) }
1941"#,
1942            expect![[r#"
1943                fd bar u32 [type+name]
1944                fd baz u32 [type]
1945                fd foo i64 []
1946            "#]],
1947        );
1948    }
1949
1950    #[test]
1951    fn record_field_relevances() {
1952        check_relevance(
1953            r#"
1954struct A { foo: i64, bar: u32, baz: u32 }
1955struct B { x: (), y: f32, bar: u32 }
1956fn foo(a: A) { B { bar: a.$0 }; }
1957"#,
1958            expect![[r#"
1959                fd bar u32 [type+name]
1960                fd baz u32 [type]
1961                fd foo i64 []
1962            "#]],
1963        )
1964    }
1965
1966    #[test]
1967    fn tuple_field_detail() {
1968        check(
1969            r#"
1970struct S(i32);
1971
1972fn f() -> i32 {
1973    let s = S(0);
1974    s.0$0
1975}
1976"#,
1977            SymbolKind::Field,
1978            expect![[r#"
1979                [
1980                    CompletionItem {
1981                        label: "0",
1982                        detail_left: None,
1983                        detail_right: Some(
1984                            "i32",
1985                        ),
1986                        source_range: 56..57,
1987                        delete: 56..57,
1988                        insert: "0",
1989                        kind: SymbolKind(
1990                            Field,
1991                        ),
1992                        detail: "i32",
1993                        relevance: CompletionRelevance {
1994                            exact_name_match: false,
1995                            type_match: Some(
1996                                Exact,
1997                            ),
1998                            is_local: false,
1999                            trait_: None,
2000                            is_name_already_imported: false,
2001                            requires_import: false,
2002                            is_private_editable: false,
2003                            postfix_match: None,
2004                            function: None,
2005                            is_skipping_completion: false,
2006                        },
2007                    },
2008                ]
2009            "#]],
2010        );
2011    }
2012
2013    #[test]
2014    fn record_field_and_call_relevances() {
2015        check_relevance(
2016            r#"
2017struct A { foo: i64, bar: u32, baz: u32 }
2018struct B { x: (), y: f32, bar: u32 }
2019fn f(foo: i64) {  }
2020fn foo(a: A) { B { bar: f(a.$0) }; }
2021"#,
2022            expect![[r#"
2023                fd foo i64 [type+name]
2024                fd bar u32 []
2025                fd baz u32 []
2026            "#]],
2027        );
2028        check_relevance(
2029            r#"
2030struct A { foo: i64, bar: u32, baz: u32 }
2031struct B { x: (), y: f32, bar: u32 }
2032fn f(foo: i64) {  }
2033fn foo(a: A) { f(B { bar: a.$0 }); }
2034"#,
2035            expect![[r#"
2036                fd bar u32 [type+name]
2037                fd baz u32 [type]
2038                fd foo i64 []
2039            "#]],
2040        );
2041    }
2042
2043    #[test]
2044    fn prioritize_exact_ref_match() {
2045        check_relevance(
2046            r#"
2047struct WorldSnapshot { _f: () };
2048fn go(world: &WorldSnapshot) { go(w$0) }
2049"#,
2050            expect![[r#"
2051                lc world &WorldSnapshot [type+name+local]
2052                ex world  [type]
2053                st WorldSnapshot {…} WorldSnapshot { _f: () } []
2054                st &WorldSnapshot {…} [type]
2055                st WorldSnapshot WorldSnapshot []
2056                st &WorldSnapshot [type]
2057                fn go(…) fn(&WorldSnapshot) []
2058            "#]],
2059        );
2060    }
2061
2062    #[test]
2063    fn prioritize_mutable_ref_as_immutable_ref_match() {
2064        check_relevance(
2065            r#"fn foo(r: &mut i32) -> &i32 { $0 }"#,
2066            expect![[r#"
2067                lc r &mut i32 [type+local]
2068                fn foo(…) fn(&mut i32) -> &i32 [type]
2069            "#]],
2070        );
2071    }
2072
2073    #[test]
2074    fn too_many_arguments() {
2075        cov_mark::check!(too_many_arguments);
2076        check_relevance(
2077            r#"
2078struct Foo;
2079fn f(foo: &Foo) { f(foo, w$0) }
2080"#,
2081            expect![[r#"
2082                lc foo &Foo [local]
2083                st Foo Foo []
2084                fn f(…) fn(&Foo) []
2085            "#]],
2086        );
2087    }
2088
2089    #[test]
2090    fn score_fn_type_and_name_match() {
2091        check_relevance(
2092            r#"
2093struct A { bar: u8 }
2094fn baz() -> u8 { 0 }
2095fn bar() -> u8 { 0 }
2096fn f() { A { bar: b$0 }; }
2097"#,
2098            expect![[r#"
2099                fn bar() fn() -> u8 [type+name]
2100                ex bar()  [type]
2101                fn baz() fn() -> u8 [type]
2102                ex baz()  [type]
2103                st A A []
2104                fn f() fn() []
2105            "#]],
2106        );
2107    }
2108
2109    #[test]
2110    fn score_method_type_and_name_match() {
2111        check_relevance(
2112            r#"
2113fn baz(aaa: u32){}
2114struct Foo;
2115impl Foo {
2116fn aaa(&self) -> u32 { 0 }
2117fn bbb(&self) -> u32 { 0 }
2118fn ccc(&self) -> u64 { 0 }
2119}
2120fn f() {
2121    baz(Foo.$0
2122}
2123"#,
2124            expect![[r#"
2125                me aaa() fn(&self) -> u32 [type+name]
2126                me bbb() fn(&self) -> u32 [type]
2127                me ccc() fn(&self) -> u64 []
2128            "#]],
2129        );
2130    }
2131
2132    #[test]
2133    fn score_method_name_match_only() {
2134        check_relevance(
2135            r#"
2136fn baz(aaa: u32){}
2137struct Foo;
2138impl Foo {
2139fn aaa(&self) -> u64 { 0 }
2140}
2141fn f() {
2142    baz(Foo.$0
2143}
2144"#,
2145            expect![[r#"
2146                me aaa() fn(&self) -> u64 [name]
2147            "#]],
2148        );
2149    }
2150
2151    #[test]
2152    fn test_avoid_redundant_suggestion() {
2153        check_relevance(
2154            r#"
2155struct aa([u8]);
2156
2157impl aa {
2158    fn from_bytes(bytes: &[u8]) -> &Self {
2159        unsafe { &*(bytes as *const [u8] as *const aa) }
2160    }
2161}
2162
2163fn bb()-> &'static aa {
2164    let bytes = b"hello";
2165    aa::$0
2166}
2167"#,
2168            expect![[r#"
2169                ex bb()  [type]
2170                fn from_bytes(…) fn(&[u8]) -> &aa [type_could_unify]
2171            "#]],
2172        );
2173    }
2174
2175    #[test]
2176    fn suggest_ref_mut() {
2177        cov_mark::check!(suggest_ref);
2178        check_relevance(
2179            r#"
2180struct S;
2181fn foo(s: &mut S) {}
2182fn main() {
2183    let mut s = S;
2184    foo($0);
2185}
2186            "#,
2187            expect![[r#"
2188                lc s S [name+local]
2189                lc &mut s [type+name+local]
2190                st S S []
2191                st &mut S [type]
2192                st S S []
2193                st &mut S [type]
2194                fn foo(…) fn(&mut S) []
2195                fn main() fn() []
2196            "#]],
2197        );
2198        check_relevance(
2199            r#"
2200struct S;
2201fn foo(s: &mut S) {}
2202fn main() {
2203    let mut s = S;
2204    foo(&mut $0);
2205}
2206            "#,
2207            expect![[r#"
2208                lc s S [type+name+local]
2209                st S S [type]
2210                st S S [type]
2211                ex S  [type]
2212                ex s  [type]
2213                fn foo(…) fn(&mut S) []
2214                fn main() fn() []
2215            "#]],
2216        );
2217        check_relevance(
2218            r#"
2219struct S;
2220fn foo(s: &mut S) {}
2221fn main() {
2222    let mut ssss = S;
2223    foo(&mut s$0);
2224}
2225            "#,
2226            expect![[r#"
2227                st S S [type]
2228                lc ssss S [type+local]
2229                st S S [type]
2230                ex S  [type]
2231                ex ssss  [type]
2232                fn foo(…) fn(&mut S) []
2233                fn main() fn() []
2234            "#]],
2235        );
2236        check_relevance(
2237            r#"
2238struct S;
2239fn foo(s: &&S) {}
2240fn main() {
2241    let mut ssss = &S;
2242    foo($0);
2243}
2244            "#,
2245            expect![[r#"
2246                st S S []
2247                lc ssss &S [local]
2248                lc &ssss [type+local]
2249                st S S []
2250                fn foo(…) fn(&&S) []
2251                fn main() fn() []
2252            "#]],
2253        );
2254    }
2255
2256    #[test]
2257    fn suggest_deref_copy() {
2258        cov_mark::check!(suggest_deref);
2259        check_relevance(
2260            r#"
2261//- minicore: copy
2262struct Foo;
2263
2264impl Copy for Foo {}
2265impl Clone for Foo {
2266    fn clone(&self) -> Self { *self }
2267}
2268
2269fn bar(x: Foo) {}
2270
2271fn main() {
2272    let foo = &Foo;
2273    bar($0);
2274}
2275"#,
2276            expect![[r#"
2277                st Foo Foo [type]
2278                st Foo Foo [type]
2279                ex Foo  [type]
2280                lc foo &Foo [local]
2281                lc *foo [type+local]
2282                tt Clone  []
2283                tt Copy  []
2284                fn bar(…) fn(Foo) []
2285                md core  []
2286                fn main() fn() []
2287            "#]],
2288        );
2289    }
2290
2291    #[test]
2292    fn suggest_deref_trait() {
2293        check_relevance(
2294            r#"
2295//- minicore: deref
2296struct S;
2297struct T(S);
2298
2299impl core::ops::Deref for T {
2300    type Target = S;
2301
2302    fn deref(&self) -> &Self::Target {
2303        &self.0
2304    }
2305}
2306
2307fn foo(s: &S) {}
2308
2309fn main() {
2310    let t = T(S);
2311    let m = 123;
2312
2313    foo($0);
2314}
2315            "#,
2316            expect![[r#"
2317                st S S []
2318                st &S [type]
2319                ex core::ops::Deref::deref(&t)  [type_could_unify]
2320                lc m i32 [local]
2321                lc t T [local]
2322                lc &t [type+local]
2323                st S S []
2324                st &S [type]
2325                st T T []
2326                st &T [type]
2327                md core  []
2328                fn foo(…) fn(&S) []
2329                fn main() fn() []
2330            "#]],
2331        )
2332    }
2333
2334    #[test]
2335    fn suggest_deref_mut() {
2336        check_relevance(
2337            r#"
2338//- minicore: deref_mut
2339struct S;
2340struct T(S);
2341
2342impl core::ops::Deref for T {
2343    type Target = S;
2344
2345    fn deref(&self) -> &Self::Target {
2346        &self.0
2347    }
2348}
2349
2350impl core::ops::DerefMut for T {
2351    fn deref_mut(&mut self) -> &mut Self::Target {
2352        &mut self.0
2353    }
2354}
2355
2356fn foo(s: &mut S) {}
2357
2358fn main() {
2359    let t = T(S);
2360    let m = 123;
2361
2362    foo($0);
2363}
2364            "#,
2365            expect![[r#"
2366                st S S []
2367                st &mut S [type]
2368                ex core::ops::DerefMut::deref_mut(&mut t)  [type_could_unify]
2369                lc m i32 [local]
2370                lc t T [local]
2371                lc &mut t [type+local]
2372                st S S []
2373                st &mut S [type]
2374                st T T []
2375                st &mut T [type]
2376                md core  []
2377                fn foo(…) fn(&mut S) []
2378                fn main() fn() []
2379            "#]],
2380        )
2381    }
2382
2383    #[test]
2384    fn locals() {
2385        check_relevance(
2386            r#"
2387fn foo(bar: u32) {
2388    let baz = 0;
2389
2390    f$0
2391}
2392"#,
2393            expect![[r#"
2394                lc bar u32 [local]
2395                lc baz i32 [local]
2396                fn foo(…) fn(u32) []
2397            "#]],
2398        );
2399    }
2400
2401    #[test]
2402    fn enum_owned() {
2403        check_relevance(
2404            r#"
2405enum Foo { A, B }
2406fn foo() {
2407    bar($0);
2408}
2409fn bar(t: Foo) {}
2410"#,
2411            expect![[r#"
2412                ev Foo::A Foo::A [type]
2413                ev Foo::B Foo::B [type]
2414                en Foo Foo [type]
2415                ex Foo::A  [type]
2416                ex Foo::B  [type]
2417                fn bar(…) fn(Foo) []
2418                fn foo() fn() []
2419            "#]],
2420        );
2421    }
2422
2423    #[test]
2424    fn enum_ref() {
2425        check_relevance(
2426            r#"
2427enum Foo { A, B }
2428fn foo() {
2429    bar($0);
2430}
2431fn bar(t: &Foo) {}
2432"#,
2433            expect![[r#"
2434                ev Foo::A Foo::A []
2435                ev &Foo::A [type]
2436                ev Foo::B Foo::B []
2437                ev &Foo::B [type]
2438                en Foo Foo []
2439                en &Foo [type]
2440                fn bar(…) fn(&Foo) []
2441                fn foo() fn() []
2442            "#]],
2443        );
2444    }
2445
2446    #[test]
2447    fn suggest_deref_fn_ret() {
2448        check_relevance(
2449            r#"
2450//- minicore: deref
2451struct S;
2452struct T(S);
2453
2454impl core::ops::Deref for T {
2455    type Target = S;
2456
2457    fn deref(&self) -> &Self::Target {
2458        &self.0
2459    }
2460}
2461
2462fn foo(s: &S) {}
2463fn bar() -> T {}
2464
2465fn main() {
2466    foo($0);
2467}
2468"#,
2469            expect![[r#"
2470                st S S []
2471                st &S [type]
2472                ex core::ops::Deref::deref(&bar())  [type_could_unify]
2473                st S S []
2474                st &S [type]
2475                st T T []
2476                st &T [type]
2477                fn bar() fn() -> T []
2478                fn &bar() [type]
2479                md core  []
2480                fn foo(…) fn(&S) []
2481                fn main() fn() []
2482            "#]],
2483        )
2484    }
2485
2486    #[test]
2487    fn op_function_relevances() {
2488        check_relevance(
2489            r#"
2490#[lang = "sub"]
2491trait Sub {
2492    fn sub(self, other: Self) -> Self { self }
2493}
2494impl Sub for u32 {}
2495fn foo(a: u32) { a.$0 }
2496"#,
2497            expect![[r#"
2498                me sub(…) fn(self, Self) -> Self [op_method]
2499            "#]],
2500        );
2501        check_relevance(
2502            r#"
2503struct Foo;
2504impl Foo {
2505    fn new() -> Self {}
2506}
2507#[lang = "eq"]
2508pub trait PartialEq<Rhs: ?Sized = Self> {
2509    fn eq(&self, other: &Rhs) -> bool;
2510    fn ne(&self, other: &Rhs) -> bool;
2511}
2512
2513impl PartialEq for Foo {}
2514fn main() {
2515    Foo::$0
2516}
2517"#,
2518            expect![[r#"
2519                fn new() fn() -> Foo []
2520                me eq(…) fn(&self, &Rhs) -> bool [op_method]
2521                me ne(…) fn(&self, &Rhs) -> bool [op_method]
2522            "#]],
2523        );
2524    }
2525
2526    #[test]
2527    fn constructor_order_simple() {
2528        check_relevance(
2529            r#"
2530struct Foo;
2531struct Other;
2532struct Option<T>(T);
2533
2534impl Foo {
2535    fn fn_ctr() -> Foo { unimplemented!() }
2536    fn fn_another(n: u32) -> Other { unimplemented!() }
2537    fn fn_ctr_self() -> Option<Self> { unimplemented!() }
2538}
2539
2540fn test() {
2541    let a = Foo::$0;
2542}
2543"#,
2544            expect![[r#"
2545                fn fn_ctr() fn() -> Foo [type_could_unify]
2546                fn fn_ctr_self() fn() -> Option<Foo> [type_could_unify]
2547                fn fn_another(…) fn(u32) -> Other [type_could_unify]
2548            "#]],
2549        );
2550    }
2551
2552    #[test]
2553    fn constructor_order_kind() {
2554        check_function_relevance(
2555            r#"
2556struct Foo;
2557struct Bar;
2558struct Option<T>(T);
2559enum Result<T, E> { Ok(T), Err(E) };
2560
2561impl Foo {
2562    fn fn_ctr(&self) -> Foo { unimplemented!() }
2563    fn fn_ctr_with_args(&self, n: u32) -> Foo { unimplemented!() }
2564    fn fn_another(&self, n: u32) -> Bar { unimplemented!() }
2565    fn fn_ctr_wrapped(&self, ) -> Option<Self> { unimplemented!() }
2566    fn fn_ctr_wrapped_2(&self, ) -> Result<Self, Bar> { unimplemented!() }
2567    fn fn_ctr_wrapped_3(&self, ) -> Result<Bar, Self> { unimplemented!() } // Self is not the first type
2568    fn fn_ctr_wrapped_with_args(&self, m: u32) -> Option<Self> { unimplemented!() }
2569    fn fn_another_unit(&self) { unimplemented!() }
2570}
2571
2572fn test() {
2573    let a = self::Foo::$0;
2574}
2575"#,
2576            expect![[r#"
2577                [
2578                    (
2579                        "fn(&self, u32) -> Bar",
2580                        Some(
2581                            CompletionRelevanceFn {
2582                                has_params: true,
2583                                has_self_param: true,
2584                                return_type: Other,
2585                            },
2586                        ),
2587                    ),
2588                    (
2589                        "fn(&self)",
2590                        Some(
2591                            CompletionRelevanceFn {
2592                                has_params: true,
2593                                has_self_param: true,
2594                                return_type: Other,
2595                            },
2596                        ),
2597                    ),
2598                    (
2599                        "fn(&self) -> Foo",
2600                        Some(
2601                            CompletionRelevanceFn {
2602                                has_params: true,
2603                                has_self_param: true,
2604                                return_type: DirectConstructor,
2605                            },
2606                        ),
2607                    ),
2608                    (
2609                        "fn(&self, u32) -> Foo",
2610                        Some(
2611                            CompletionRelevanceFn {
2612                                has_params: true,
2613                                has_self_param: true,
2614                                return_type: DirectConstructor,
2615                            },
2616                        ),
2617                    ),
2618                    (
2619                        "fn(&self) -> Option<Foo>",
2620                        Some(
2621                            CompletionRelevanceFn {
2622                                has_params: true,
2623                                has_self_param: true,
2624                                return_type: Constructor,
2625                            },
2626                        ),
2627                    ),
2628                    (
2629                        "fn(&self) -> Result<Foo, Bar>",
2630                        Some(
2631                            CompletionRelevanceFn {
2632                                has_params: true,
2633                                has_self_param: true,
2634                                return_type: Constructor,
2635                            },
2636                        ),
2637                    ),
2638                    (
2639                        "fn(&self) -> Result<Bar, Foo>",
2640                        Some(
2641                            CompletionRelevanceFn {
2642                                has_params: true,
2643                                has_self_param: true,
2644                                return_type: Constructor,
2645                            },
2646                        ),
2647                    ),
2648                    (
2649                        "fn(&self, u32) -> Option<Foo>",
2650                        Some(
2651                            CompletionRelevanceFn {
2652                                has_params: true,
2653                                has_self_param: true,
2654                                return_type: Constructor,
2655                            },
2656                        ),
2657                    ),
2658                ]
2659            "#]],
2660        );
2661    }
2662
2663    #[test]
2664    fn constructor_order_relevance() {
2665        check_relevance(
2666            r#"
2667struct Foo;
2668struct FooBuilder;
2669struct Result<T>(T);
2670
2671impl Foo {
2672    fn fn_no_ret(&self) {}
2673    fn fn_ctr_with_args(input: u32) -> Foo { unimplemented!() }
2674    fn fn_direct_ctr() -> Self { unimplemented!() }
2675    fn fn_ctr() -> Result<Self> { unimplemented!() }
2676    fn fn_other() -> Result<u32> { unimplemented!() }
2677    fn fn_builder() -> FooBuilder { unimplemented!() }
2678}
2679
2680fn test() {
2681    let a = self::Foo::$0;
2682}
2683"#,
2684            // preference:
2685            // Direct Constructor
2686            // Direct Constructor with args
2687            // Builder
2688            // Constructor
2689            // Others
2690            expect![[r#"
2691                fn fn_direct_ctr() fn() -> Foo [type_could_unify]
2692                fn fn_ctr_with_args(…) fn(u32) -> Foo [type_could_unify]
2693                fn fn_builder() fn() -> FooBuilder [type_could_unify]
2694                fn fn_ctr() fn() -> Result<Foo> [type_could_unify]
2695                me fn_no_ret(…) fn(&self) [type_could_unify]
2696                fn fn_other() fn() -> Result<u32> [type_could_unify]
2697            "#]],
2698        );
2699
2700        //
2701    }
2702
2703    #[test]
2704    fn function_relevance_generic_1() {
2705        check_relevance(
2706            r#"
2707struct Foo<T: Default>(T);
2708struct FooBuilder;
2709struct Option<T>(T);
2710enum Result<T, E>{Ok(T), Err(E)};
2711
2712impl<T: Default> Foo<T> {
2713    fn fn_returns_unit(&self) {}
2714    fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
2715    fn fn_direct_ctr() -> Self { unimplemented!() }
2716    fn fn_ctr_wrapped() -> Option<Self> { unimplemented!() }
2717    fn fn_ctr_wrapped_2() -> Result<Self, u32> { unimplemented!() }
2718    fn fn_other() -> Option<u32> { unimplemented!() }
2719    fn fn_builder() -> FooBuilder { unimplemented!() }
2720}
2721
2722fn test() {
2723    let a = self::Foo::<u32>::$0;
2724}
2725                "#,
2726            expect![[r#"
2727                fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
2728                fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
2729                fn fn_builder() fn() -> FooBuilder [type_could_unify]
2730                fn fn_ctr_wrapped() fn() -> Option<Foo<T>> [type_could_unify]
2731                fn fn_ctr_wrapped_2() fn() -> Result<Foo<T>, u32> [type_could_unify]
2732                fn fn_other() fn() -> Option<u32> [type_could_unify]
2733                me fn_returns_unit(…) fn(&self) [type_could_unify]
2734            "#]],
2735        );
2736    }
2737
2738    #[test]
2739    fn function_relevance_generic_2() {
2740        // Generic 2
2741        check_relevance(
2742            r#"
2743struct Foo<T: Default>(T);
2744struct FooBuilder;
2745struct Option<T>(T);
2746enum Result<T, E>{Ok(T), Err(E)};
2747
2748impl<T: Default> Foo<T> {
2749    fn fn_no_ret(&self) {}
2750    fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
2751    fn fn_direct_ctr() -> Self { unimplemented!() }
2752    fn fn_ctr() -> Option<Self> { unimplemented!() }
2753    fn fn_ctr2() -> Result<Self, u32> { unimplemented!() }
2754    fn fn_other() -> Option<u32> { unimplemented!() }
2755    fn fn_builder() -> FooBuilder { unimplemented!() }
2756}
2757
2758fn test() {
2759    let a : Res<Foo<u32>> = Foo::$0;
2760}
2761                "#,
2762            expect![[r#"
2763                fn fn_direct_ctr() fn() -> Foo<T> [type_could_unify]
2764                fn fn_ctr_with_args(…) fn(T) -> Foo<T> [type_could_unify]
2765                fn fn_builder() fn() -> FooBuilder [type_could_unify]
2766                fn fn_ctr() fn() -> Option<Foo<T>> [type_could_unify]
2767                fn fn_ctr2() fn() -> Result<Foo<T>, u32> [type_could_unify]
2768                me fn_no_ret(…) fn(&self) [type_could_unify]
2769                fn fn_other() fn() -> Option<u32> [type_could_unify]
2770            "#]],
2771        );
2772    }
2773
2774    #[test]
2775    fn struct_field_method_ref() {
2776        check_kinds(
2777            r#"
2778struct Foo { bar: u32, qux: fn() }
2779impl Foo { fn baz(&self) -> u32 { 0 } }
2780
2781fn foo(f: Foo) { let _: &u32 = f.b$0 }
2782"#,
2783            &[
2784                CompletionItemKind::SymbolKind(SymbolKind::Method),
2785                CompletionItemKind::SymbolKind(SymbolKind::Field),
2786            ],
2787            expect![[r#"
2788                [
2789                    CompletionItem {
2790                        label: "baz()",
2791                        detail_left: None,
2792                        detail_right: Some(
2793                            "fn(&self) -> u32",
2794                        ),
2795                        source_range: 109..110,
2796                        delete: 109..110,
2797                        insert: "baz()$0",
2798                        kind: SymbolKind(
2799                            Method,
2800                        ),
2801                        lookup: "baz",
2802                        detail: "fn(&self) -> u32",
2803                        relevance: CompletionRelevance {
2804                            exact_name_match: false,
2805                            type_match: None,
2806                            is_local: false,
2807                            trait_: None,
2808                            is_name_already_imported: false,
2809                            requires_import: false,
2810                            is_private_editable: false,
2811                            postfix_match: None,
2812                            function: Some(
2813                                CompletionRelevanceFn {
2814                                    has_params: true,
2815                                    has_self_param: true,
2816                                    return_type: Other,
2817                                },
2818                            ),
2819                            is_skipping_completion: false,
2820                        },
2821                        ref_match: "&@107",
2822                    },
2823                    CompletionItem {
2824                        label: "bar",
2825                        detail_left: None,
2826                        detail_right: Some(
2827                            "u32",
2828                        ),
2829                        source_range: 109..110,
2830                        delete: 109..110,
2831                        insert: "bar",
2832                        kind: SymbolKind(
2833                            Field,
2834                        ),
2835                        detail: "u32",
2836                        ref_match: "&@107",
2837                    },
2838                    CompletionItem {
2839                        label: "qux",
2840                        detail_left: None,
2841                        detail_right: Some(
2842                            "fn()",
2843                        ),
2844                        source_range: 109..110,
2845                        text_edit: TextEdit {
2846                            indels: [
2847                                Indel {
2848                                    insert: "(",
2849                                    delete: 107..107,
2850                                },
2851                                Indel {
2852                                    insert: "qux)()",
2853                                    delete: 109..110,
2854                                },
2855                            ],
2856                            annotation: None,
2857                        },
2858                        kind: SymbolKind(
2859                            Field,
2860                        ),
2861                        detail: "fn()",
2862                    },
2863                ]
2864            "#]],
2865        );
2866    }
2867
2868    #[test]
2869    fn expected_fn_type_ref() {
2870        check_kinds(
2871            r#"
2872struct S { field: fn() }
2873
2874fn foo() {
2875    let foo: fn() = S { fields: || {}}.fi$0;
2876}
2877"#,
2878            &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
2879            expect![[r#"
2880                [
2881                    CompletionItem {
2882                        label: "field",
2883                        detail_left: None,
2884                        detail_right: Some(
2885                            "fn()",
2886                        ),
2887                        source_range: 76..78,
2888                        delete: 76..78,
2889                        insert: "field",
2890                        kind: SymbolKind(
2891                            Field,
2892                        ),
2893                        detail: "fn()",
2894                        relevance: CompletionRelevance {
2895                            exact_name_match: false,
2896                            type_match: Some(
2897                                Exact,
2898                            ),
2899                            is_local: false,
2900                            trait_: None,
2901                            is_name_already_imported: false,
2902                            requires_import: false,
2903                            is_private_editable: false,
2904                            postfix_match: None,
2905                            function: None,
2906                            is_skipping_completion: false,
2907                        },
2908                    },
2909                ]
2910            "#]],
2911        )
2912    }
2913
2914    #[test]
2915    fn qualified_path_ref() {
2916        check_kinds(
2917            r#"
2918struct S;
2919
2920struct T;
2921impl T {
2922    fn foo() -> S {}
2923}
2924
2925fn bar(s: &S) {}
2926
2927fn main() {
2928    bar(T::$0);
2929}
2930"#,
2931            &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
2932            expect![[r#"
2933                [
2934                    CompletionItem {
2935                        label: "foo()",
2936                        detail_left: None,
2937                        detail_right: Some(
2938                            "fn() -> S",
2939                        ),
2940                        source_range: 95..95,
2941                        delete: 95..95,
2942                        insert: "foo()$0",
2943                        kind: SymbolKind(
2944                            Function,
2945                        ),
2946                        lookup: "foo",
2947                        detail: "fn() -> S",
2948                        relevance: CompletionRelevance {
2949                            exact_name_match: false,
2950                            type_match: None,
2951                            is_local: false,
2952                            trait_: None,
2953                            is_name_already_imported: false,
2954                            requires_import: false,
2955                            is_private_editable: false,
2956                            postfix_match: None,
2957                            function: Some(
2958                                CompletionRelevanceFn {
2959                                    has_params: false,
2960                                    has_self_param: false,
2961                                    return_type: Other,
2962                                },
2963                            ),
2964                            is_skipping_completion: false,
2965                        },
2966                        ref_match: "&@92",
2967                    },
2968                ]
2969            "#]],
2970        );
2971    }
2972
2973    #[test]
2974    fn generic_enum() {
2975        check_relevance(
2976            r#"
2977enum Foo<T> { A(T), B }
2978// bar() should not be an exact type match
2979// because the generic parameters are different
2980fn bar() -> Foo<u8> { Foo::B }
2981// FIXME baz() should be an exact type match
2982// because the types could unify, but it currently
2983// is not. This is due to the T here being
2984// TyKind::Placeholder rather than TyKind::Missing.
2985fn baz<T>() -> Foo<T> { Foo::B }
2986fn foo() {
2987    let foo: Foo<u32> = Foo::B;
2988    let _: Foo<u32> = f$0;
2989}
2990"#,
2991            expect![[r#"
2992                ev Foo::B Foo::B [type_could_unify]
2993                ev Foo::A(…) Foo::A(T) [type_could_unify]
2994                lc foo Foo<u32> [type+local]
2995                ex Foo::B  [type]
2996                ex foo  [type]
2997                en Foo Foo<{unknown}> [type_could_unify]
2998                fn bar() fn() -> Foo<u8> []
2999                fn baz() fn() -> Foo<T> []
3000                fn foo() fn() []
3001            "#]],
3002        );
3003    }
3004
3005    #[test]
3006    fn postfix_exact_match_is_high_priority() {
3007        cov_mark::check!(postfix_exact_match_is_high_priority);
3008        check_relevance_for_kinds(
3009            r#"
3010mod ops {
3011    pub trait Not {
3012        type Output;
3013        fn not(self) -> Self::Output;
3014    }
3015
3016    impl Not for bool {
3017        type Output = bool;
3018        fn not(self) -> bool { if self { false } else { true }}
3019    }
3020}
3021
3022fn main() {
3023    let _: bool = (9 > 2).not$0;
3024}
3025    "#,
3026            &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3027            expect![[r#"
3028                sn not !expr [snippet]
3029                sn box Box::new(expr) []
3030                sn call function(expr) []
3031                sn const const {} []
3032                sn dbg dbg!(expr) []
3033                sn dbgr dbg!(&expr) []
3034                sn deref *expr []
3035                sn if if expr {} []
3036                sn match match expr {} []
3037                sn ref &expr []
3038                sn refm &mut expr []
3039                sn return return expr []
3040                sn unsafe unsafe {} []
3041                sn while while expr {} []
3042                me not() fn(self) -> <Self as Not>::Output [requires_import]
3043            "#]],
3044        );
3045    }
3046
3047    #[test]
3048    fn postfix_inexact_match_is_low_priority() {
3049        cov_mark::check!(postfix_inexact_match_is_low_priority);
3050        check_relevance_for_kinds(
3051            r#"
3052struct S;
3053impl S {
3054    fn f(&self) {}
3055}
3056fn main() {
3057    S.$0
3058}
3059    "#,
3060            &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
3061            expect![[r#"
3062                me f() fn(&self) []
3063                sn box Box::new(expr) []
3064                sn call function(expr) []
3065                sn const const {} []
3066                sn dbg dbg!(expr) []
3067                sn dbgr dbg!(&expr) []
3068                sn deref *expr []
3069                sn let let []
3070                sn letm let mut []
3071                sn match match expr {} []
3072                sn ref &expr []
3073                sn refm &mut expr []
3074                sn return return expr []
3075                sn unsafe unsafe {} []
3076            "#]],
3077        );
3078    }
3079
3080    #[test]
3081    fn flyimport_reduced_relevance() {
3082        check_relevance(
3083            r#"
3084mod std {
3085    pub mod io {
3086        pub trait BufRead {}
3087        pub struct BufReader;
3088        pub struct BufWriter;
3089    }
3090}
3091struct Buffer;
3092
3093fn f() {
3094    Buf$0
3095}
3096"#,
3097            expect![[r#"
3098                st Buffer Buffer []
3099                fn f() fn() []
3100                md std  []
3101                tt BufRead  [requires_import]
3102                st BufReader BufReader [requires_import]
3103                st BufWriter BufWriter [requires_import]
3104            "#]],
3105        );
3106    }
3107
3108    #[test]
3109    fn completes_struct_with_raw_identifier() {
3110        check_edit(
3111            "type",
3112            r#"
3113mod m { pub struct r#type {} }
3114fn main() {
3115    let r#type = m::t$0;
3116}
3117"#,
3118            r#"
3119mod m { pub struct r#type {} }
3120fn main() {
3121    let r#type = m::r#type;
3122}
3123"#,
3124        )
3125    }
3126
3127    #[test]
3128    fn completes_fn_with_raw_identifier() {
3129        check_edit(
3130            "type",
3131            r#"
3132mod m { pub fn r#type {} }
3133fn main() {
3134    m::t$0
3135}
3136"#,
3137            r#"
3138mod m { pub fn r#type {} }
3139fn main() {
3140    m::r#type();$0
3141}
3142"#,
3143        )
3144    }
3145
3146    #[test]
3147    fn completes_macro_with_raw_identifier() {
3148        check_edit(
3149            "let!",
3150            r#"
3151macro_rules! r#let { () => {} }
3152fn main() {
3153    $0
3154}
3155"#,
3156            r#"
3157macro_rules! r#let { () => {} }
3158fn main() {
3159    r#let!($0)
3160}
3161"#,
3162        )
3163    }
3164
3165    #[test]
3166    fn completes_variant_with_raw_identifier() {
3167        check_edit(
3168            "type",
3169            r#"
3170enum A { r#type }
3171fn main() {
3172    let a = A::t$0
3173}
3174"#,
3175            r#"
3176enum A { r#type }
3177fn main() {
3178    let a = A::r#type$0
3179}
3180"#,
3181        )
3182    }
3183
3184    #[test]
3185    fn completes_field_with_raw_identifier() {
3186        check_edit(
3187            "fn",
3188            r#"
3189mod r#type {
3190    pub struct r#struct {
3191        pub r#fn: u32
3192    }
3193}
3194
3195fn main() {
3196    let a = r#type::r#struct {};
3197    a.$0
3198}
3199"#,
3200            r#"
3201mod r#type {
3202    pub struct r#struct {
3203        pub r#fn: u32
3204    }
3205}
3206
3207fn main() {
3208    let a = r#type::r#struct {};
3209    a.r#fn
3210}
3211"#,
3212        )
3213    }
3214
3215    #[test]
3216    fn completes_const_with_raw_identifier() {
3217        check_edit(
3218            "type",
3219            r#"
3220struct r#struct {}
3221impl r#struct { pub const r#type: u8 = 1; }
3222fn main() {
3223    r#struct::t$0
3224}
3225"#,
3226            r#"
3227struct r#struct {}
3228impl r#struct { pub const r#type: u8 = 1; }
3229fn main() {
3230    r#struct::r#type
3231}
3232"#,
3233        )
3234    }
3235
3236    #[test]
3237    fn completes_type_alias_with_raw_identifier() {
3238        check_edit(
3239            "type type",
3240            r#"
3241struct r#struct {}
3242trait r#trait { type r#type; }
3243impl r#trait for r#struct { type t$0 }
3244"#,
3245            r#"
3246struct r#struct {}
3247trait r#trait { type r#type; }
3248impl r#trait for r#struct { type r#type = $0; }
3249"#,
3250        )
3251    }
3252
3253    #[test]
3254    fn field_access_includes_self() {
3255        check_edit(
3256            "length",
3257            r#"
3258struct S {
3259    length: i32
3260}
3261
3262impl S {
3263    fn some_fn(&self) {
3264        let l = len$0
3265    }
3266}
3267"#,
3268            r#"
3269struct S {
3270    length: i32
3271}
3272
3273impl S {
3274    fn some_fn(&self) {
3275        let l = self.length
3276    }
3277}
3278"#,
3279        )
3280    }
3281
3282    #[test]
3283    fn field_access_includes_closure_this_param() {
3284        check_edit(
3285            "length",
3286            r#"
3287//- minicore: fn
3288struct S {
3289    length: i32
3290}
3291
3292impl S {
3293    fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
3294        self.length += 1;
3295        f(self, 3);
3296        self.length -= 1;
3297    }
3298
3299    fn some_fn(&mut self) {
3300        self.pack(|this, n| len$0);
3301    }
3302}
3303"#,
3304            r#"
3305struct S {
3306    length: i32
3307}
3308
3309impl S {
3310    fn pack(&mut self, f: impl FnOnce(&mut Self, i32)) {
3311        self.length += 1;
3312        f(self, 3);
3313        self.length -= 1;
3314    }
3315
3316    fn some_fn(&mut self) {
3317        self.pack(|this, n| this.length);
3318    }
3319}
3320"#,
3321        )
3322    }
3323
3324    #[test]
3325    fn notable_traits_method_relevance() {
3326        check_kinds(
3327            r#"
3328#[doc(notable_trait)]
3329trait Write {
3330    fn write(&self);
3331    fn flush(&self);
3332}
3333
3334struct Writer;
3335
3336impl Write for Writer {
3337    fn write(&self) {}
3338    fn flush(&self) {}
3339}
3340
3341fn main() {
3342    Writer.$0
3343}
3344"#,
3345            &[
3346                CompletionItemKind::SymbolKind(SymbolKind::Method),
3347                CompletionItemKind::SymbolKind(SymbolKind::Field),
3348                CompletionItemKind::SymbolKind(SymbolKind::Function),
3349            ],
3350            expect![[r#"
3351                [
3352                    CompletionItem {
3353                        label: "flush()",
3354                        detail_left: Some(
3355                            "(as Write)",
3356                        ),
3357                        detail_right: Some(
3358                            "fn(&self)",
3359                        ),
3360                        source_range: 193..193,
3361                        delete: 193..193,
3362                        insert: "flush();$0",
3363                        kind: SymbolKind(
3364                            Method,
3365                        ),
3366                        lookup: "flush",
3367                        detail: "fn(&self)",
3368                        relevance: CompletionRelevance {
3369                            exact_name_match: false,
3370                            type_match: None,
3371                            is_local: false,
3372                            trait_: Some(
3373                                CompletionRelevanceTraitInfo {
3374                                    notable_trait: true,
3375                                    is_op_method: false,
3376                                },
3377                            ),
3378                            is_name_already_imported: false,
3379                            requires_import: false,
3380                            is_private_editable: false,
3381                            postfix_match: None,
3382                            function: None,
3383                            is_skipping_completion: false,
3384                        },
3385                    },
3386                    CompletionItem {
3387                        label: "write()",
3388                        detail_left: Some(
3389                            "(as Write)",
3390                        ),
3391                        detail_right: Some(
3392                            "fn(&self)",
3393                        ),
3394                        source_range: 193..193,
3395                        delete: 193..193,
3396                        insert: "write();$0",
3397                        kind: SymbolKind(
3398                            Method,
3399                        ),
3400                        lookup: "write",
3401                        detail: "fn(&self)",
3402                        relevance: CompletionRelevance {
3403                            exact_name_match: false,
3404                            type_match: None,
3405                            is_local: false,
3406                            trait_: Some(
3407                                CompletionRelevanceTraitInfo {
3408                                    notable_trait: true,
3409                                    is_op_method: false,
3410                                },
3411                            ),
3412                            is_name_already_imported: false,
3413                            requires_import: false,
3414                            is_private_editable: false,
3415                            postfix_match: None,
3416                            function: None,
3417                            is_skipping_completion: false,
3418                        },
3419                    },
3420                ]
3421            "#]],
3422        );
3423    }
3424}