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