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