ide_completion/
render.rs

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