]> git.lizzy.rs Git - rust.git/blob - crates/ide-completion/src/render.rs
Remove pattern rendering hack
[rust.git] / crates / ide-completion / src / render.rs
1 //! `render` module provides utilities for rendering completion suggestions
2 //! into code pieces that will be presented to user.
3
4 pub(crate) mod macro_;
5 pub(crate) mod function;
6 pub(crate) mod const_;
7 pub(crate) mod pattern;
8 pub(crate) mod type_alias;
9 pub(crate) mod variant;
10 pub(crate) mod union_literal;
11 pub(crate) mod literal;
12
13 use hir::{AsAssocItem, HasAttrs, HirDisplay, ScopeDef};
14 use ide_db::{
15     helpers::item_name, imports::import_assets::LocatedImport, RootDatabase, SnippetCap, SymbolKind,
16 };
17 use syntax::{AstNode, SmolStr, SyntaxKind, TextRange};
18
19 use crate::{
20     context::{PathCompletionCtx, PathKind, PatternContext},
21     item::{Builder, CompletionRelevanceTypeMatch},
22     render::{
23         function::render_fn,
24         literal::render_variant_lit,
25         macro_::{render_macro, render_macro_pat},
26     },
27     CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
28 };
29 /// Interface for data and methods required for items rendering.
30 #[derive(Debug, Clone)]
31 pub(crate) struct RenderContext<'a> {
32     completion: &'a CompletionContext<'a>,
33     is_private_editable: bool,
34     import_to_add: Option<LocatedImport>,
35 }
36
37 impl<'a> RenderContext<'a> {
38     pub(crate) fn new(completion: &'a CompletionContext<'a>) -> RenderContext<'a> {
39         RenderContext { completion, is_private_editable: false, import_to_add: None }
40     }
41
42     pub(crate) fn private_editable(mut self, private_editable: bool) -> Self {
43         self.is_private_editable = private_editable;
44         self
45     }
46
47     pub(crate) fn import_to_add(mut self, import_to_add: Option<LocatedImport>) -> Self {
48         self.import_to_add = import_to_add;
49         self
50     }
51
52     fn snippet_cap(&self) -> Option<SnippetCap> {
53         self.completion.config.snippet_cap
54     }
55
56     fn db(&self) -> &'a RootDatabase {
57         self.completion.db
58     }
59
60     fn source_range(&self) -> TextRange {
61         self.completion.source_range()
62     }
63
64     fn completion_relevance(&self) -> CompletionRelevance {
65         CompletionRelevance {
66             is_private_editable: self.is_private_editable,
67             requires_import: self.import_to_add.is_some(),
68             ..Default::default()
69         }
70     }
71
72     fn is_immediately_after_macro_bang(&self) -> bool {
73         self.completion.token.kind() == SyntaxKind::BANG
74             && self
75                 .completion
76                 .token
77                 .parent()
78                 .map_or(false, |it| it.kind() == SyntaxKind::MACRO_CALL)
79     }
80
81     fn is_deprecated(&self, def: impl HasAttrs) -> bool {
82         let attrs = def.attrs(self.db());
83         attrs.by_key("deprecated").exists()
84     }
85
86     fn is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool {
87         let db = self.db();
88         let assoc = match as_assoc_item.as_assoc_item(db) {
89             Some(assoc) => assoc,
90             None => return false,
91         };
92
93         let is_assoc_deprecated = match assoc {
94             hir::AssocItem::Function(it) => self.is_deprecated(it),
95             hir::AssocItem::Const(it) => self.is_deprecated(it),
96             hir::AssocItem::TypeAlias(it) => self.is_deprecated(it),
97         };
98         is_assoc_deprecated
99             || assoc
100                 .containing_trait_or_trait_impl(db)
101                 .map(|trait_| self.is_deprecated(trait_))
102                 .unwrap_or(false)
103     }
104
105     // FIXME: remove this
106     fn docs(&self, def: impl HasAttrs) -> Option<hir::Documentation> {
107         def.docs(self.db())
108     }
109 }
110
111 pub(crate) fn render_field(
112     ctx: RenderContext<'_>,
113     receiver: Option<hir::Name>,
114     field: hir::Field,
115     ty: &hir::Type,
116 ) -> CompletionItem {
117     let is_deprecated = ctx.is_deprecated(field);
118     let name = field.name(ctx.db()).to_smol_str();
119     let mut item = CompletionItem::new(
120         SymbolKind::Field,
121         ctx.source_range(),
122         receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name).into()),
123     );
124     item.set_relevance(CompletionRelevance {
125         type_match: compute_type_match(ctx.completion, ty),
126         exact_name_match: compute_exact_name_match(ctx.completion, name.as_str()),
127         ..CompletionRelevance::default()
128     });
129     item.detail(ty.display(ctx.db()).to_string())
130         .set_documentation(field.docs(ctx.db()))
131         .set_deprecated(is_deprecated)
132         .lookup_by(name.clone());
133     let is_keyword = SyntaxKind::from_keyword(name.as_str()).is_some();
134     if is_keyword && !matches!(name.as_str(), "self" | "crate" | "super" | "Self") {
135         item.insert_text(format!("r#{}", name));
136     }
137     if let Some(_ref_match) = compute_ref_match(ctx.completion, ty) {
138         // FIXME
139         // For now we don't properly calculate the edits for ref match
140         // completions on struct fields, so we've disabled them. See #8058.
141     }
142     item.build()
143 }
144
145 pub(crate) fn render_tuple_field(
146     ctx: RenderContext<'_>,
147     receiver: Option<hir::Name>,
148     field: usize,
149     ty: &hir::Type,
150 ) -> CompletionItem {
151     let mut item = CompletionItem::new(
152         SymbolKind::Field,
153         ctx.source_range(),
154         receiver.map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)),
155     );
156     item.detail(ty.display(ctx.db()).to_string()).lookup_by(field.to_string());
157     item.build()
158 }
159
160 pub(crate) fn render_type_inference(ty_string: String, ctx: &CompletionContext) -> CompletionItem {
161     let mut builder =
162         CompletionItem::new(CompletionItemKind::InferredType, ctx.source_range(), ty_string);
163     builder.set_relevance(CompletionRelevance { is_definite: true, ..Default::default() });
164     builder.build()
165 }
166
167 pub(crate) fn render_path_resolution(
168     ctx: RenderContext<'_>,
169     path_ctx: &PathCompletionCtx,
170     local_name: hir::Name,
171     resolution: ScopeDef,
172 ) -> Builder {
173     render_resolution_path(ctx, path_ctx, local_name, None, resolution)
174 }
175
176 pub(crate) fn render_pattern_resolution(
177     ctx: RenderContext<'_>,
178     pattern_ctx: &PatternContext,
179     local_name: hir::Name,
180     resolution: ScopeDef,
181 ) -> Builder {
182     render_resolution_pat(ctx, pattern_ctx, local_name, None, resolution)
183 }
184
185 pub(crate) fn render_resolution_with_import(
186     ctx: RenderContext<'_>,
187     path_ctx: &PathCompletionCtx,
188     import_edit: LocatedImport,
189 ) -> Option<Builder> {
190     let resolution = ScopeDef::from(import_edit.original_item);
191     let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?;
192
193     Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
194 }
195
196 pub(crate) fn render_resolution_with_import_pat(
197     ctx: RenderContext<'_>,
198     pattern_ctx: &PatternContext,
199     import_edit: LocatedImport,
200 ) -> Option<Builder> {
201     let resolution = ScopeDef::from(import_edit.original_item);
202     let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?;
203     Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
204 }
205
206 fn scope_def_to_name(
207     resolution: ScopeDef,
208     ctx: &RenderContext,
209     import_edit: &LocatedImport,
210 ) -> Option<hir::Name> {
211     Some(match resolution {
212         ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
213         ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
214         ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
215         _ => item_name(ctx.db(), import_edit.original_item)?,
216     })
217 }
218
219 fn render_resolution_pat(
220     ctx: RenderContext<'_>,
221     pattern_ctx: &PatternContext,
222     local_name: hir::Name,
223     import_to_add: Option<LocatedImport>,
224     resolution: ScopeDef,
225 ) -> Builder {
226     let _p = profile::span("render_resolution");
227     use hir::ModuleDef::*;
228
229     match resolution {
230         ScopeDef::ModuleDef(Macro(mac)) => {
231             let ctx = ctx.import_to_add(import_to_add);
232             return render_macro_pat(ctx, pattern_ctx, local_name, mac);
233         }
234         _ => (),
235     }
236
237     render_resolution_simple_(ctx, local_name, import_to_add, resolution)
238 }
239
240 fn render_resolution_path(
241     ctx: RenderContext<'_>,
242     path_ctx: &PathCompletionCtx,
243     local_name: hir::Name,
244     import_to_add: Option<LocatedImport>,
245     resolution: ScopeDef,
246 ) -> Builder {
247     let _p = profile::span("render_resolution");
248     use hir::ModuleDef::*;
249
250     match resolution {
251         ScopeDef::ModuleDef(Macro(mac)) => {
252             let ctx = ctx.import_to_add(import_to_add);
253             return render_macro(ctx, path_ctx, local_name, mac);
254         }
255         ScopeDef::ModuleDef(Function(func)) => {
256             let ctx = ctx.import_to_add(import_to_add);
257             return render_fn(ctx, path_ctx, Some(local_name), func);
258         }
259         ScopeDef::ModuleDef(Variant(var)) => {
260             let ctx = ctx.clone().import_to_add(import_to_add.clone());
261             if let Some(item) =
262                 render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
263             {
264                 return item;
265             }
266         }
267         _ => (),
268     }
269
270     let completion = ctx.completion;
271     let cap = ctx.snippet_cap();
272     let db = completion.db;
273     let config = completion.config;
274
275     let name = local_name.to_smol_str();
276     let mut item = render_resolution_simple_(ctx, local_name, import_to_add, resolution);
277     // Add `<>` for generic types
278     let type_path_no_ty_args = matches!(
279         path_ctx,
280         PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
281     ) && config.callable.is_some();
282     if type_path_no_ty_args {
283         if let Some(cap) = cap {
284             let has_non_default_type_params = match resolution {
285                 ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
286                 ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
287                     it.has_non_default_type_params(db)
288                 }
289                 _ => false,
290             };
291
292             if has_non_default_type_params {
293                 cov_mark::hit!(inserts_angle_brackets_for_generics);
294                 item.lookup_by(name.clone())
295                     .label(SmolStr::from_iter([&name, "<…>"]))
296                     .trigger_call_info()
297                     .insert_snippet(cap, format!("{}<$0>", name));
298             }
299         }
300     }
301     if let ScopeDef::Local(local) = resolution {
302         let ty = local.ty(db);
303         if !ty.is_unknown() {
304             item.detail(ty.display(db).to_string());
305         }
306
307         item.set_relevance(CompletionRelevance {
308             type_match: compute_type_match(completion, &ty),
309             exact_name_match: compute_exact_name_match(completion, &name),
310             is_local: true,
311             ..CompletionRelevance::default()
312         });
313
314         if let Some(ref_match) = compute_ref_match(completion, &ty) {
315             item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
316         }
317     };
318     item
319 }
320
321 fn render_resolution_simple_(
322     ctx: RenderContext<'_>,
323     local_name: hir::Name,
324     import_to_add: Option<LocatedImport>,
325     resolution: ScopeDef,
326 ) -> Builder {
327     let _p = profile::span("render_resolution");
328
329     let db = ctx.db();
330     let ctx = ctx.import_to_add(import_to_add);
331     let kind = res_to_kind(resolution);
332
333     let mut item = CompletionItem::new(kind, ctx.source_range(), local_name.to_smol_str());
334     item.set_relevance(ctx.completion_relevance())
335         .set_documentation(scope_def_docs(db, resolution))
336         .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
337
338     if let Some(import_to_add) = ctx.import_to_add {
339         item.add_import(import_to_add);
340     }
341     item
342 }
343
344 fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
345     use hir::ModuleDef::*;
346     match resolution {
347         ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
348         ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
349         ScopeDef::ModuleDef(Variant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
350         ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
351         ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
352         ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
353             hir::Adt::Struct(_) => SymbolKind::Struct,
354             hir::Adt::Union(_) => SymbolKind::Union,
355             hir::Adt::Enum(_) => SymbolKind::Enum,
356         }),
357         ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
358         ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
359         ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
360         ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
361         ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
362         ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
363             hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
364             hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
365             hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
366         }),
367         ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
368         ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
369         ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
370             CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
371         }
372     }
373 }
374
375 fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<hir::Documentation> {
376     use hir::ModuleDef::*;
377     match resolution {
378         ScopeDef::ModuleDef(Module(it)) => it.docs(db),
379         ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
380         ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
381         ScopeDef::ModuleDef(Const(it)) => it.docs(db),
382         ScopeDef::ModuleDef(Static(it)) => it.docs(db),
383         ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
384         ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
385         _ => None,
386     }
387 }
388
389 fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> bool {
390     match resolution {
391         ScopeDef::ModuleDef(it) => ctx.is_deprecated_assoc_item(it),
392         ScopeDef::GenericParam(it) => ctx.is_deprecated(it),
393         ScopeDef::AdtSelfType(it) => ctx.is_deprecated(it),
394         _ => false,
395     }
396 }
397
398 fn compute_type_match(
399     ctx: &CompletionContext,
400     completion_ty: &hir::Type,
401 ) -> Option<CompletionRelevanceTypeMatch> {
402     let expected_type = ctx.expected_type.as_ref()?;
403
404     // We don't ever consider unit type to be an exact type match, since
405     // nearly always this is not meaningful to the user.
406     if expected_type.is_unit() {
407         return None;
408     }
409
410     if completion_ty == expected_type {
411         Some(CompletionRelevanceTypeMatch::Exact)
412     } else if expected_type.could_unify_with(ctx.db, completion_ty) {
413         Some(CompletionRelevanceTypeMatch::CouldUnify)
414     } else {
415         None
416     }
417 }
418
419 fn compute_exact_name_match(ctx: &CompletionContext, completion_name: &str) -> bool {
420     ctx.expected_name.as_ref().map_or(false, |name| name.text() == completion_name)
421 }
422
423 fn compute_ref_match(
424     ctx: &CompletionContext,
425     completion_ty: &hir::Type,
426 ) -> Option<hir::Mutability> {
427     let expected_type = ctx.expected_type.as_ref()?;
428     if completion_ty != expected_type {
429         let expected_type_without_ref = expected_type.remove_ref()?;
430         if completion_ty.autoderef(ctx.db).any(|deref_ty| deref_ty == expected_type_without_ref) {
431             cov_mark::hit!(suggest_ref);
432             let mutability = if expected_type.is_mutable_reference() {
433                 hir::Mutability::Mut
434             } else {
435                 hir::Mutability::Shared
436             };
437             return Some(mutability);
438         };
439     }
440     None
441 }
442
443 #[cfg(test)]
444 mod tests {
445     use std::cmp;
446
447     use expect_test::{expect, Expect};
448     use ide_db::SymbolKind;
449     use itertools::Itertools;
450
451     use crate::{
452         item::CompletionRelevanceTypeMatch,
453         tests::{check_edit, do_completion, get_all_items, TEST_CONFIG},
454         CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
455     };
456
457     #[track_caller]
458     fn check(ra_fixture: &str, kind: impl Into<CompletionItemKind>, expect: Expect) {
459         let actual = do_completion(ra_fixture, kind.into());
460         expect.assert_debug_eq(&actual);
461     }
462
463     #[track_caller]
464     fn check_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
465         let actual: Vec<_> =
466             kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
467         expect.assert_debug_eq(&actual);
468     }
469
470     #[track_caller]
471     fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
472         let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
473         actual.retain(|it| kinds.contains(&it.kind()));
474         actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
475         check_relevance_(actual, expect);
476     }
477
478     #[track_caller]
479     fn check_relevance(ra_fixture: &str, expect: Expect) {
480         let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
481         actual.retain(|it| it.kind() != CompletionItemKind::Snippet);
482         actual.retain(|it| it.kind() != CompletionItemKind::Keyword);
483         actual.retain(|it| it.kind() != CompletionItemKind::BuiltinType);
484         actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
485         check_relevance_(actual, expect);
486     }
487
488     #[track_caller]
489     fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
490         let actual = actual
491             .into_iter()
492             .flat_map(|it| {
493                 let mut items = vec![];
494
495                 let tag = it.kind().tag();
496                 let relevance = display_relevance(it.relevance());
497                 items.push(format!("{} {} {}\n", tag, it.label(), relevance));
498
499                 if let Some((mutability, _offset, relevance)) = it.ref_match() {
500                     let label = format!("&{}{}", mutability.as_keyword_for_ref(), it.label());
501                     let relevance = display_relevance(relevance);
502
503                     items.push(format!("{} {} {}\n", tag, label, relevance));
504                 }
505
506                 items
507             })
508             .collect::<String>();
509
510         expect.assert_eq(&actual);
511
512         fn display_relevance(relevance: CompletionRelevance) -> String {
513             let relevance_factors = vec![
514                 (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
515                 (
516                     relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
517                     "type_could_unify",
518                 ),
519                 (relevance.exact_name_match, "name"),
520                 (relevance.is_local, "local"),
521                 (
522                     relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
523                     "snippet",
524                 ),
525                 (relevance.is_op_method, "op_method"),
526                 (relevance.requires_import, "requires_import"),
527             ]
528             .into_iter()
529             .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
530             .join("+");
531
532             format!("[{}]", relevance_factors)
533         }
534     }
535
536     #[test]
537     fn enum_detail_includes_record_fields() {
538         check(
539             r#"
540 enum Foo { Foo { x: i32, y: i32 } }
541
542 fn main() { Foo::Fo$0 }
543 "#,
544             SymbolKind::Variant,
545             expect![[r#"
546                 [
547                     CompletionItem {
548                         label: "Foo {…}",
549                         source_range: 54..56,
550                         delete: 54..56,
551                         insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
552                         kind: SymbolKind(
553                             Variant,
554                         ),
555                         detail: "Foo { x: i32, y: i32 }",
556                     },
557                 ]
558             "#]],
559         );
560     }
561
562     #[test]
563     fn enum_detail_includes_tuple_fields() {
564         check(
565             r#"
566 enum Foo { Foo (i32, i32) }
567
568 fn main() { Foo::Fo$0 }
569 "#,
570             SymbolKind::Variant,
571             expect![[r#"
572                 [
573                     CompletionItem {
574                         label: "Foo(…)",
575                         source_range: 46..48,
576                         delete: 46..48,
577                         insert: "Foo(${1:()}, ${2:()})$0",
578                         kind: SymbolKind(
579                             Variant,
580                         ),
581                         detail: "Foo(i32, i32)",
582                     },
583                 ]
584             "#]],
585         );
586     }
587
588     #[test]
589     fn fn_detail_includes_args_and_return_type() {
590         check(
591             r#"
592 fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
593
594 fn main() { fo$0 }
595 "#,
596             SymbolKind::Function,
597             expect![[r#"
598                 [
599                     CompletionItem {
600                         label: "foo(…)",
601                         source_range: 68..70,
602                         delete: 68..70,
603                         insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
604                         kind: SymbolKind(
605                             Function,
606                         ),
607                         lookup: "foo",
608                         detail: "fn(u32, u32, T) -> (u32, T)",
609                         trigger_call_info: true,
610                     },
611                     CompletionItem {
612                         label: "main()",
613                         source_range: 68..70,
614                         delete: 68..70,
615                         insert: "main()$0",
616                         kind: SymbolKind(
617                             Function,
618                         ),
619                         lookup: "main",
620                         detail: "fn()",
621                     },
622                 ]
623             "#]],
624         );
625     }
626
627     #[test]
628     fn enum_detail_just_name_for_unit() {
629         check(
630             r#"
631 enum Foo { Foo }
632
633 fn main() { Foo::Fo$0 }
634 "#,
635             SymbolKind::Variant,
636             expect![[r#"
637                 [
638                     CompletionItem {
639                         label: "Foo",
640                         source_range: 35..37,
641                         delete: 35..37,
642                         insert: "Foo$0",
643                         kind: SymbolKind(
644                             Variant,
645                         ),
646                         detail: "Foo",
647                     },
648                 ]
649             "#]],
650         );
651     }
652
653     #[test]
654     fn lookup_enums_by_two_qualifiers() {
655         check_kinds(
656             r#"
657 mod m {
658     pub enum Spam { Foo, Bar(i32) }
659 }
660 fn main() { let _: m::Spam = S$0 }
661 "#,
662             &[
663                 CompletionItemKind::SymbolKind(SymbolKind::Function),
664                 CompletionItemKind::SymbolKind(SymbolKind::Module),
665                 CompletionItemKind::SymbolKind(SymbolKind::Variant),
666             ],
667             expect![[r#"
668                 [
669                     CompletionItem {
670                         label: "main()",
671                         source_range: 75..76,
672                         delete: 75..76,
673                         insert: "main()$0",
674                         kind: SymbolKind(
675                             Function,
676                         ),
677                         lookup: "main",
678                         detail: "fn()",
679                     },
680                     CompletionItem {
681                         label: "m",
682                         source_range: 75..76,
683                         delete: 75..76,
684                         insert: "m",
685                         kind: SymbolKind(
686                             Module,
687                         ),
688                     },
689                     CompletionItem {
690                         label: "m::Spam::Bar(…)",
691                         source_range: 75..76,
692                         delete: 75..76,
693                         insert: "m::Spam::Bar(${1:()})$0",
694                         kind: SymbolKind(
695                             Variant,
696                         ),
697                         lookup: "Spam::Bar(…)",
698                         detail: "m::Spam::Bar(i32)",
699                         relevance: CompletionRelevance {
700                             exact_name_match: false,
701                             type_match: Some(
702                                 Exact,
703                             ),
704                             is_local: false,
705                             is_item_from_trait: false,
706                             is_name_already_imported: false,
707                             requires_import: false,
708                             is_op_method: false,
709                             is_private_editable: false,
710                             postfix_match: None,
711                             is_definite: false,
712                         },
713                     },
714                     CompletionItem {
715                         label: "m::Spam::Foo",
716                         source_range: 75..76,
717                         delete: 75..76,
718                         insert: "m::Spam::Foo$0",
719                         kind: SymbolKind(
720                             Variant,
721                         ),
722                         lookup: "Spam::Foo",
723                         detail: "m::Spam::Foo",
724                         relevance: CompletionRelevance {
725                             exact_name_match: false,
726                             type_match: Some(
727                                 Exact,
728                             ),
729                             is_local: false,
730                             is_item_from_trait: false,
731                             is_name_already_imported: false,
732                             requires_import: false,
733                             is_op_method: false,
734                             is_private_editable: false,
735                             postfix_match: None,
736                             is_definite: false,
737                         },
738                     },
739                 ]
740             "#]],
741         )
742     }
743
744     #[test]
745     fn sets_deprecated_flag_in_items() {
746         check(
747             r#"
748 #[deprecated]
749 fn something_deprecated() {}
750
751 fn main() { som$0 }
752 "#,
753             SymbolKind::Function,
754             expect![[r#"
755                 [
756                     CompletionItem {
757                         label: "main()",
758                         source_range: 56..59,
759                         delete: 56..59,
760                         insert: "main()$0",
761                         kind: SymbolKind(
762                             Function,
763                         ),
764                         lookup: "main",
765                         detail: "fn()",
766                     },
767                     CompletionItem {
768                         label: "something_deprecated()",
769                         source_range: 56..59,
770                         delete: 56..59,
771                         insert: "something_deprecated()$0",
772                         kind: SymbolKind(
773                             Function,
774                         ),
775                         lookup: "something_deprecated",
776                         detail: "fn()",
777                         deprecated: true,
778                     },
779                 ]
780             "#]],
781         );
782
783         check(
784             r#"
785 struct A { #[deprecated] the_field: u32 }
786 fn foo() { A { the$0 } }
787 "#,
788             SymbolKind::Field,
789             expect![[r#"
790                 [
791                     CompletionItem {
792                         label: "the_field",
793                         source_range: 57..60,
794                         delete: 57..60,
795                         insert: "the_field",
796                         kind: SymbolKind(
797                             Field,
798                         ),
799                         detail: "u32",
800                         deprecated: true,
801                         relevance: CompletionRelevance {
802                             exact_name_match: false,
803                             type_match: Some(
804                                 CouldUnify,
805                             ),
806                             is_local: false,
807                             is_item_from_trait: false,
808                             is_name_already_imported: false,
809                             requires_import: false,
810                             is_op_method: false,
811                             is_private_editable: false,
812                             postfix_match: None,
813                             is_definite: false,
814                         },
815                     },
816                 ]
817             "#]],
818         );
819     }
820
821     #[test]
822     fn renders_docs() {
823         check_kinds(
824             r#"
825 struct S {
826     /// Field docs
827     foo:
828 }
829 impl S {
830     /// Method docs
831     fn bar(self) { self.$0 }
832 }"#,
833             &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
834             expect![[r#"
835                 [
836                     CompletionItem {
837                         label: "bar()",
838                         source_range: 94..94,
839                         delete: 94..94,
840                         insert: "bar()$0",
841                         kind: Method,
842                         lookup: "bar",
843                         detail: "fn(self)",
844                         documentation: Documentation(
845                             "Method docs",
846                         ),
847                     },
848                     CompletionItem {
849                         label: "foo",
850                         source_range: 94..94,
851                         delete: 94..94,
852                         insert: "foo",
853                         kind: SymbolKind(
854                             Field,
855                         ),
856                         detail: "{unknown}",
857                         documentation: Documentation(
858                             "Field docs",
859                         ),
860                     },
861                 ]
862             "#]],
863         );
864
865         check_kinds(
866             r#"
867 use self::my$0;
868
869 /// mod docs
870 mod my { }
871
872 /// enum docs
873 enum E {
874     /// variant docs
875     V
876 }
877 use self::E::*;
878 "#,
879             &[
880                 CompletionItemKind::SymbolKind(SymbolKind::Module),
881                 CompletionItemKind::SymbolKind(SymbolKind::Variant),
882                 CompletionItemKind::SymbolKind(SymbolKind::Enum),
883             ],
884             expect![[r#"
885                 [
886                     CompletionItem {
887                         label: "my",
888                         source_range: 10..12,
889                         delete: 10..12,
890                         insert: "my",
891                         kind: SymbolKind(
892                             Module,
893                         ),
894                         documentation: Documentation(
895                             "mod docs",
896                         ),
897                     },
898                     CompletionItem {
899                         label: "V",
900                         source_range: 10..12,
901                         delete: 10..12,
902                         insert: "V$0",
903                         kind: SymbolKind(
904                             Variant,
905                         ),
906                         detail: "V",
907                         documentation: Documentation(
908                             "variant docs",
909                         ),
910                     },
911                     CompletionItem {
912                         label: "E",
913                         source_range: 10..12,
914                         delete: 10..12,
915                         insert: "E",
916                         kind: SymbolKind(
917                             Enum,
918                         ),
919                         documentation: Documentation(
920                             "enum docs",
921                         ),
922                     },
923                 ]
924             "#]],
925         )
926     }
927
928     #[test]
929     fn dont_render_attrs() {
930         check(
931             r#"
932 struct S;
933 impl S {
934     #[inline]
935     fn the_method(&self) { }
936 }
937 fn foo(s: S) { s.$0 }
938 "#,
939             CompletionItemKind::Method,
940             expect![[r#"
941                 [
942                     CompletionItem {
943                         label: "the_method()",
944                         source_range: 81..81,
945                         delete: 81..81,
946                         insert: "the_method()$0",
947                         kind: Method,
948                         lookup: "the_method",
949                         detail: "fn(&self)",
950                     },
951                 ]
952             "#]],
953         )
954     }
955
956     #[test]
957     fn no_call_parens_if_fn_ptr_needed() {
958         cov_mark::check!(no_call_parens_if_fn_ptr_needed);
959         check_edit(
960             "foo",
961             r#"
962 fn foo(foo: u8, bar: u8) {}
963 struct ManualVtable { f: fn(u8, u8) }
964
965 fn main() -> ManualVtable {
966     ManualVtable { f: f$0 }
967 }
968 "#,
969             r#"
970 fn foo(foo: u8, bar: u8) {}
971 struct ManualVtable { f: fn(u8, u8) }
972
973 fn main() -> ManualVtable {
974     ManualVtable { f: foo }
975 }
976 "#,
977         );
978         check_edit(
979             "type",
980             r#"
981 struct RawIdentTable { r#type: u32 }
982
983 fn main() -> RawIdentTable {
984     RawIdentTable { t$0: 42 }
985 }
986 "#,
987             r#"
988 struct RawIdentTable { r#type: u32 }
989
990 fn main() -> RawIdentTable {
991     RawIdentTable { r#type: 42 }
992 }
993 "#,
994         );
995     }
996
997     #[test]
998     fn no_parens_in_use_item() {
999         check_edit(
1000             "foo",
1001             r#"
1002 mod m { pub fn foo() {} }
1003 use crate::m::f$0;
1004 "#,
1005             r#"
1006 mod m { pub fn foo() {} }
1007 use crate::m::foo;
1008 "#,
1009         );
1010     }
1011
1012     #[test]
1013     fn no_parens_in_call() {
1014         check_edit(
1015             "foo",
1016             r#"
1017 fn foo(x: i32) {}
1018 fn main() { f$0(); }
1019 "#,
1020             r#"
1021 fn foo(x: i32) {}
1022 fn main() { foo(); }
1023 "#,
1024         );
1025         check_edit(
1026             "foo",
1027             r#"
1028 struct Foo;
1029 impl Foo { fn foo(&self){} }
1030 fn f(foo: &Foo) { foo.f$0(); }
1031 "#,
1032             r#"
1033 struct Foo;
1034 impl Foo { fn foo(&self){} }
1035 fn f(foo: &Foo) { foo.foo(); }
1036 "#,
1037         );
1038     }
1039
1040     #[test]
1041     fn inserts_angle_brackets_for_generics() {
1042         cov_mark::check!(inserts_angle_brackets_for_generics);
1043         check_edit(
1044             "Vec",
1045             r#"
1046 struct Vec<T> {}
1047 fn foo(xs: Ve$0)
1048 "#,
1049             r#"
1050 struct Vec<T> {}
1051 fn foo(xs: Vec<$0>)
1052 "#,
1053         );
1054         check_edit(
1055             "Vec",
1056             r#"
1057 type Vec<T> = (T,);
1058 fn foo(xs: Ve$0)
1059 "#,
1060             r#"
1061 type Vec<T> = (T,);
1062 fn foo(xs: Vec<$0>)
1063 "#,
1064         );
1065         check_edit(
1066             "Vec",
1067             r#"
1068 struct Vec<T = i128> {}
1069 fn foo(xs: Ve$0)
1070 "#,
1071             r#"
1072 struct Vec<T = i128> {}
1073 fn foo(xs: Vec)
1074 "#,
1075         );
1076         check_edit(
1077             "Vec",
1078             r#"
1079 struct Vec<T> {}
1080 fn foo(xs: Ve$0<i128>)
1081 "#,
1082             r#"
1083 struct Vec<T> {}
1084 fn foo(xs: Vec<i128>)
1085 "#,
1086         );
1087     }
1088
1089     #[test]
1090     fn active_param_relevance() {
1091         check_relevance(
1092             r#"
1093 struct S { foo: i64, bar: u32, baz: u32 }
1094 fn test(bar: u32) { }
1095 fn foo(s: S) { test(s.$0) }
1096 "#,
1097             expect![[r#"
1098                 fd bar [type+name]
1099                 fd baz [type]
1100                 fd foo []
1101             "#]],
1102         );
1103     }
1104
1105     #[test]
1106     fn record_field_relevances() {
1107         check_relevance(
1108             r#"
1109 struct A { foo: i64, bar: u32, baz: u32 }
1110 struct B { x: (), y: f32, bar: u32 }
1111 fn foo(a: A) { B { bar: a.$0 }; }
1112 "#,
1113             expect![[r#"
1114                 fd bar [type+name]
1115                 fd baz [type]
1116                 fd foo []
1117             "#]],
1118         )
1119     }
1120
1121     #[test]
1122     fn record_field_and_call_relevances() {
1123         check_relevance(
1124             r#"
1125 struct A { foo: i64, bar: u32, baz: u32 }
1126 struct B { x: (), y: f32, bar: u32 }
1127 fn f(foo: i64) {  }
1128 fn foo(a: A) { B { bar: f(a.$0) }; }
1129 "#,
1130             expect![[r#"
1131                 fd foo [type+name]
1132                 fd bar []
1133                 fd baz []
1134             "#]],
1135         );
1136         check_relevance(
1137             r#"
1138 struct A { foo: i64, bar: u32, baz: u32 }
1139 struct B { x: (), y: f32, bar: u32 }
1140 fn f(foo: i64) {  }
1141 fn foo(a: A) { f(B { bar: a.$0 }); }
1142 "#,
1143             expect![[r#"
1144                 fd bar [type+name]
1145                 fd baz [type]
1146                 fd foo []
1147             "#]],
1148         );
1149     }
1150
1151     #[test]
1152     fn prioritize_exact_ref_match() {
1153         check_relevance(
1154             r#"
1155 struct WorldSnapshot { _f: () };
1156 fn go(world: &WorldSnapshot) { go(w$0) }
1157 "#,
1158             expect![[r#"
1159                 lc world [type+name+local]
1160                 st WorldSnapshot {…} []
1161                 st &WorldSnapshot {…} [type]
1162                 st WorldSnapshot []
1163                 fn go(…) []
1164             "#]],
1165         );
1166     }
1167
1168     #[test]
1169     fn too_many_arguments() {
1170         cov_mark::check!(too_many_arguments);
1171         check_relevance(
1172             r#"
1173 struct Foo;
1174 fn f(foo: &Foo) { f(foo, w$0) }
1175 "#,
1176             expect![[r#"
1177                 lc foo [local]
1178                 st Foo []
1179                 fn f(…) []
1180             "#]],
1181         );
1182     }
1183
1184     #[test]
1185     fn score_fn_type_and_name_match() {
1186         check_relevance(
1187             r#"
1188 struct A { bar: u8 }
1189 fn baz() -> u8 { 0 }
1190 fn bar() -> u8 { 0 }
1191 fn f() { A { bar: b$0 }; }
1192 "#,
1193             expect![[r#"
1194                 fn bar() [type+name]
1195                 fn baz() [type]
1196                 st A []
1197                 fn f() []
1198             "#]],
1199         );
1200     }
1201
1202     #[test]
1203     fn score_method_type_and_name_match() {
1204         check_relevance(
1205             r#"
1206 fn baz(aaa: u32){}
1207 struct Foo;
1208 impl Foo {
1209 fn aaa(&self) -> u32 { 0 }
1210 fn bbb(&self) -> u32 { 0 }
1211 fn ccc(&self) -> u64 { 0 }
1212 }
1213 fn f() {
1214     baz(Foo.$0
1215 }
1216 "#,
1217             expect![[r#"
1218                 me aaa() [type+name]
1219                 me bbb() [type]
1220                 me ccc() []
1221             "#]],
1222         );
1223     }
1224
1225     #[test]
1226     fn score_method_name_match_only() {
1227         check_relevance(
1228             r#"
1229 fn baz(aaa: u32){}
1230 struct Foo;
1231 impl Foo {
1232 fn aaa(&self) -> u64 { 0 }
1233 }
1234 fn f() {
1235     baz(Foo.$0
1236 }
1237 "#,
1238             expect![[r#"
1239                 me aaa() [name]
1240             "#]],
1241         );
1242     }
1243
1244     #[test]
1245     fn suggest_ref_mut() {
1246         cov_mark::check!(suggest_ref);
1247         check_relevance(
1248             r#"
1249 struct S;
1250 fn foo(s: &mut S) {}
1251 fn main() {
1252     let mut s = S;
1253     foo($0);
1254 }
1255             "#,
1256             expect![[r#"
1257                 lc s [name+local]
1258                 lc &mut s [type+name+local]
1259                 st S []
1260                 st &mut S [type]
1261                 st S []
1262                 fn main() []
1263                 fn foo(…) []
1264             "#]],
1265         );
1266         check_relevance(
1267             r#"
1268 struct S;
1269 fn foo(s: &mut S) {}
1270 fn main() {
1271     let mut s = S;
1272     foo(&mut $0);
1273 }
1274             "#,
1275             expect![[r#"
1276                 lc s [type+name+local]
1277                 st S [type]
1278                 st S []
1279                 fn main() []
1280                 fn foo(…) []
1281             "#]],
1282         );
1283         check_relevance(
1284             r#"
1285 struct S;
1286 fn foo(s: &mut S) {}
1287 fn main() {
1288     let mut ssss = S;
1289     foo(&mut s$0);
1290 }
1291             "#,
1292             expect![[r#"
1293                 lc ssss [type+local]
1294                 st S [type]
1295                 st S []
1296                 fn main() []
1297                 fn foo(…) []
1298             "#]],
1299         );
1300     }
1301
1302     #[test]
1303     fn suggest_deref() {
1304         check_relevance(
1305             r#"
1306 //- minicore: deref
1307 struct S;
1308 struct T(S);
1309
1310 impl core::ops::Deref for T {
1311     type Target = S;
1312
1313     fn deref(&self) -> &Self::Target {
1314         &self.0
1315     }
1316 }
1317
1318 fn foo(s: &S) {}
1319
1320 fn main() {
1321     let t = T(S);
1322     let m = 123;
1323
1324     foo($0);
1325 }
1326             "#,
1327             expect![[r#"
1328                 lc m [local]
1329                 lc t [local]
1330                 lc &t [type+local]
1331                 st S []
1332                 st &S [type]
1333                 st T []
1334                 st S []
1335                 fn main() []
1336                 fn foo(…) []
1337                 md core []
1338                 tt Sized []
1339             "#]],
1340         )
1341     }
1342
1343     #[test]
1344     fn suggest_deref_mut() {
1345         check_relevance(
1346             r#"
1347 //- minicore: deref_mut
1348 struct S;
1349 struct T(S);
1350
1351 impl core::ops::Deref for T {
1352     type Target = S;
1353
1354     fn deref(&self) -> &Self::Target {
1355         &self.0
1356     }
1357 }
1358
1359 impl core::ops::DerefMut for T {
1360     fn deref_mut(&mut self) -> &mut Self::Target {
1361         &mut self.0
1362     }
1363 }
1364
1365 fn foo(s: &mut S) {}
1366
1367 fn main() {
1368     let t = T(S);
1369     let m = 123;
1370
1371     foo($0);
1372 }
1373             "#,
1374             expect![[r#"
1375                 lc m [local]
1376                 lc t [local]
1377                 lc &mut t [type+local]
1378                 st S []
1379                 st &mut S [type]
1380                 st T []
1381                 st S []
1382                 fn main() []
1383                 fn foo(…) []
1384                 md core []
1385                 tt Sized []
1386             "#]],
1387         )
1388     }
1389
1390     #[test]
1391     fn locals() {
1392         check_relevance(
1393             r#"
1394 fn foo(bar: u32) {
1395     let baz = 0;
1396
1397     f$0
1398 }
1399 "#,
1400             expect![[r#"
1401                 lc baz [local]
1402                 lc bar [local]
1403                 fn foo(…) []
1404             "#]],
1405         );
1406     }
1407
1408     #[test]
1409     fn enum_owned() {
1410         check_relevance(
1411             r#"
1412 enum Foo { A, B }
1413 fn foo() {
1414     bar($0);
1415 }
1416 fn bar(t: Foo) {}
1417 "#,
1418             expect![[r#"
1419                 ev Foo::A [type]
1420                 ev Foo::B [type]
1421                 en Foo []
1422                 fn bar(…) []
1423                 fn foo() []
1424             "#]],
1425         );
1426     }
1427
1428     #[test]
1429     fn enum_ref() {
1430         check_relevance(
1431             r#"
1432 enum Foo { A, B }
1433 fn foo() {
1434     bar($0);
1435 }
1436 fn bar(t: &Foo) {}
1437 "#,
1438             expect![[r#"
1439                 ev Foo::A []
1440                 ev &Foo::A [type]
1441                 ev Foo::B []
1442                 ev &Foo::B [type]
1443                 en Foo []
1444                 fn bar(…) []
1445                 fn foo() []
1446             "#]],
1447         );
1448     }
1449
1450     #[test]
1451     fn suggest_deref_fn_ret() {
1452         check_relevance(
1453             r#"
1454 //- minicore: deref
1455 struct S;
1456 struct T(S);
1457
1458 impl core::ops::Deref for T {
1459     type Target = S;
1460
1461     fn deref(&self) -> &Self::Target {
1462         &self.0
1463     }
1464 }
1465
1466 fn foo(s: &S) {}
1467 fn bar() -> T {}
1468
1469 fn main() {
1470     foo($0);
1471 }
1472 "#,
1473             expect![[r#"
1474                 st S []
1475                 st &S [type]
1476                 st T []
1477                 st S []
1478                 fn main() []
1479                 fn bar() []
1480                 fn &bar() [type]
1481                 fn foo(…) []
1482                 md core []
1483                 tt Sized []
1484             "#]],
1485         )
1486     }
1487
1488     #[test]
1489     fn op_function_relevances() {
1490         check_relevance(
1491             r#"
1492 #[lang = "sub"]
1493 trait Sub {
1494     fn sub(self, other: Self) -> Self { self }
1495 }
1496 impl Sub for u32 {}
1497 fn foo(a: u32) { a.$0 }
1498 "#,
1499             expect![[r#"
1500                 me sub(…) (as Sub) [op_method]
1501             "#]],
1502         );
1503         check_relevance(
1504             r#"
1505 struct Foo;
1506 impl Foo {
1507     fn new() -> Self {}
1508 }
1509 #[lang = "eq"]
1510 pub trait PartialEq<Rhs: ?Sized = Self> {
1511     fn eq(&self, other: &Rhs) -> bool;
1512     fn ne(&self, other: &Rhs) -> bool;
1513 }
1514
1515 impl PartialEq for Foo {}
1516 fn main() {
1517     Foo::$0
1518 }
1519 "#,
1520             expect![[r#"
1521                 fn new() []
1522                 me eq(…) (as PartialEq) [op_method]
1523                 me ne(…) (as PartialEq) [op_method]
1524             "#]],
1525         );
1526     }
1527
1528     #[test]
1529     fn struct_field_method_ref() {
1530         check_kinds(
1531             r#"
1532 struct Foo { bar: u32 }
1533 impl Foo { fn baz(&self) -> u32 { 0 } }
1534
1535 fn foo(f: Foo) { let _: &u32 = f.b$0 }
1536 "#,
1537             &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
1538             // FIXME
1539             // Ideally we'd also suggest &f.bar as exact
1540             // type matches. See #8058.
1541             expect![[r#"
1542                 [
1543                     CompletionItem {
1544                         label: "baz()",
1545                         source_range: 98..99,
1546                         delete: 98..99,
1547                         insert: "baz()$0",
1548                         kind: Method,
1549                         lookup: "baz",
1550                         detail: "fn(&self) -> u32",
1551                         ref_match: "&@96",
1552                     },
1553                     CompletionItem {
1554                         label: "bar",
1555                         source_range: 98..99,
1556                         delete: 98..99,
1557                         insert: "bar",
1558                         kind: SymbolKind(
1559                             Field,
1560                         ),
1561                         detail: "u32",
1562                     },
1563                 ]
1564             "#]],
1565         );
1566     }
1567
1568     #[test]
1569     fn qualified_path_ref() {
1570         check_kinds(
1571             r#"
1572 struct S;
1573
1574 struct T;
1575 impl T {
1576     fn foo() -> S {}
1577 }
1578
1579 fn bar(s: &S) {}
1580
1581 fn main() {
1582     bar(T::$0);
1583 }
1584 "#,
1585             &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
1586             expect![[r#"
1587                 [
1588                     CompletionItem {
1589                         label: "foo()",
1590                         source_range: 95..95,
1591                         delete: 95..95,
1592                         insert: "foo()$0",
1593                         kind: SymbolKind(
1594                             Function,
1595                         ),
1596                         lookup: "foo",
1597                         detail: "fn() -> S",
1598                         ref_match: "&@92",
1599                     },
1600                 ]
1601             "#]],
1602         );
1603     }
1604
1605     #[test]
1606     fn generic_enum() {
1607         check_relevance(
1608             r#"
1609 enum Foo<T> { A(T), B }
1610 // bar() should not be an exact type match
1611 // because the generic parameters are different
1612 fn bar() -> Foo<u8> { Foo::B }
1613 // FIXME baz() should be an exact type match
1614 // because the types could unify, but it currently
1615 // is not. This is due to the T here being
1616 // TyKind::Placeholder rather than TyKind::Missing.
1617 fn baz<T>() -> Foo<T> { Foo::B }
1618 fn foo() {
1619     let foo: Foo<u32> = Foo::B;
1620     let _: Foo<u32> = f$0;
1621 }
1622 "#,
1623             expect![[r#"
1624                 lc foo [type+local]
1625                 ev Foo::A(…) [type_could_unify]
1626                 ev Foo::B [type_could_unify]
1627                 fn foo() []
1628                 en Foo []
1629                 fn baz() []
1630                 fn bar() []
1631             "#]],
1632         );
1633     }
1634
1635     #[test]
1636     fn postfix_exact_match_is_high_priority() {
1637         cov_mark::check!(postfix_exact_match_is_high_priority);
1638         check_relevance_for_kinds(
1639             r#"
1640 mod ops {
1641     pub trait Not {
1642         type Output;
1643         fn not(self) -> Self::Output;
1644     }
1645
1646     impl Not for bool {
1647         type Output = bool;
1648         fn not(self) -> bool { if self { false } else { true }}
1649     }
1650 }
1651
1652 fn main() {
1653     let _: bool = (9 > 2).not$0;
1654 }
1655     "#,
1656             &[CompletionItemKind::Snippet, CompletionItemKind::Method],
1657             expect![[r#"
1658                 sn not [snippet]
1659                 me not() (use ops::Not) [type_could_unify+requires_import]
1660                 sn if []
1661                 sn while []
1662                 sn ref []
1663                 sn refm []
1664                 sn match []
1665                 sn box []
1666                 sn dbg []
1667                 sn dbgr []
1668                 sn call []
1669             "#]],
1670         );
1671     }
1672
1673     #[test]
1674     fn postfix_inexact_match_is_low_priority() {
1675         cov_mark::check!(postfix_inexact_match_is_low_priority);
1676         check_relevance_for_kinds(
1677             r#"
1678 struct S;
1679 impl S {
1680     fn f(&self) {}
1681 }
1682 fn main() {
1683     S.$0
1684 }
1685     "#,
1686             &[CompletionItemKind::Snippet, CompletionItemKind::Method],
1687             expect![[r#"
1688                 me f() []
1689                 sn ref []
1690                 sn refm []
1691                 sn match []
1692                 sn box []
1693                 sn dbg []
1694                 sn dbgr []
1695                 sn call []
1696                 sn let []
1697                 sn letm []
1698             "#]],
1699         );
1700     }
1701
1702     #[test]
1703     fn flyimport_reduced_relevance() {
1704         check_relevance(
1705             r#"
1706 mod std {
1707     pub mod io {
1708         pub trait BufRead {}
1709         pub struct BufReader;
1710         pub struct BufWriter;
1711     }
1712 }
1713 struct Buffer;
1714
1715 fn f() {
1716     Buf$0
1717 }
1718 "#,
1719             expect![[r#"
1720                 md std []
1721                 st Buffer []
1722                 fn f() []
1723                 tt BufRead (use std::io::BufRead) [requires_import]
1724                 st BufReader (use std::io::BufReader) [requires_import]
1725                 st BufWriter (use std::io::BufWriter) [requires_import]
1726             "#]],
1727         );
1728     }
1729 }