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