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