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