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