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