]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/render.rs
6b04ee1648717d1176c82414e15c868696e389b7
[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                     },
671                 ]
672             "#]],
673         );
674     }
675
676     #[test]
677     fn renders_docs() {
678         check(
679             r#"
680 struct S {
681     /// Field docs
682     foo:
683 }
684 impl S {
685     /// Method docs
686     fn bar(self) { self.$0 }
687 }"#,
688             expect![[r#"
689                 [
690                     CompletionItem {
691                         label: "bar()",
692                         source_range: 94..94,
693                         delete: 94..94,
694                         insert: "bar()$0",
695                         kind: Method,
696                         lookup: "bar",
697                         detail: "fn(self)",
698                         documentation: Documentation(
699                             "Method docs",
700                         ),
701                     },
702                     CompletionItem {
703                         label: "foo",
704                         source_range: 94..94,
705                         delete: 94..94,
706                         insert: "foo",
707                         kind: SymbolKind(
708                             Field,
709                         ),
710                         detail: "{unknown}",
711                         documentation: Documentation(
712                             "Field docs",
713                         ),
714                     },
715                 ]
716             "#]],
717         );
718
719         check(
720             r#"
721 use self::my$0;
722
723 /// mod docs
724 mod my { }
725
726 /// enum docs
727 enum E {
728     /// variant docs
729     V
730 }
731 use self::E::*;
732 "#,
733             expect![[r#"
734                 [
735                     CompletionItem {
736                         label: "E",
737                         source_range: 10..12,
738                         delete: 10..12,
739                         insert: "E",
740                         kind: SymbolKind(
741                             Enum,
742                         ),
743                         documentation: Documentation(
744                             "enum docs",
745                         ),
746                     },
747                     CompletionItem {
748                         label: "V",
749                         source_range: 10..12,
750                         delete: 10..12,
751                         insert: "V",
752                         kind: SymbolKind(
753                             Variant,
754                         ),
755                         detail: "()",
756                         documentation: Documentation(
757                             "variant docs",
758                         ),
759                     },
760                     CompletionItem {
761                         label: "my",
762                         source_range: 10..12,
763                         delete: 10..12,
764                         insert: "my",
765                         kind: SymbolKind(
766                             Module,
767                         ),
768                         documentation: Documentation(
769                             "mod docs",
770                         ),
771                     },
772                 ]
773             "#]],
774         )
775     }
776
777     #[test]
778     fn dont_render_attrs() {
779         check(
780             r#"
781 struct S;
782 impl S {
783     #[inline]
784     fn the_method(&self) { }
785 }
786 fn foo(s: S) { s.$0 }
787 "#,
788             expect![[r#"
789                 [
790                     CompletionItem {
791                         label: "the_method()",
792                         source_range: 81..81,
793                         delete: 81..81,
794                         insert: "the_method()$0",
795                         kind: Method,
796                         lookup: "the_method",
797                         detail: "fn(&self)",
798                     },
799                 ]
800             "#]],
801         )
802     }
803
804     #[test]
805     fn no_call_parens_if_fn_ptr_needed() {
806         cov_mark::check!(no_call_parens_if_fn_ptr_needed);
807         check_edit(
808             "foo",
809             r#"
810 fn foo(foo: u8, bar: u8) {}
811 struct ManualVtable { f: fn(u8, u8) }
812
813 fn main() -> ManualVtable {
814     ManualVtable { f: f$0 }
815 }
816 "#,
817             r#"
818 fn foo(foo: u8, bar: u8) {}
819 struct ManualVtable { f: fn(u8, u8) }
820
821 fn main() -> ManualVtable {
822     ManualVtable { f: foo }
823 }
824 "#,
825         );
826     }
827
828     #[test]
829     fn no_parens_in_use_item() {
830         cov_mark::check!(no_parens_in_use_item);
831         check_edit(
832             "foo",
833             r#"
834 mod m { pub fn foo() {} }
835 use crate::m::f$0;
836 "#,
837             r#"
838 mod m { pub fn foo() {} }
839 use crate::m::foo;
840 "#,
841         );
842     }
843
844     #[test]
845     fn no_parens_in_call() {
846         check_edit(
847             "foo",
848             r#"
849 fn foo(x: i32) {}
850 fn main() { f$0(); }
851 "#,
852             r#"
853 fn foo(x: i32) {}
854 fn main() { foo(); }
855 "#,
856         );
857         check_edit(
858             "foo",
859             r#"
860 struct Foo;
861 impl Foo { fn foo(&self){} }
862 fn f(foo: &Foo) { foo.f$0(); }
863 "#,
864             r#"
865 struct Foo;
866 impl Foo { fn foo(&self){} }
867 fn f(foo: &Foo) { foo.foo(); }
868 "#,
869         );
870     }
871
872     #[test]
873     fn inserts_angle_brackets_for_generics() {
874         cov_mark::check!(inserts_angle_brackets_for_generics);
875         check_edit(
876             "Vec",
877             r#"
878 struct Vec<T> {}
879 fn foo(xs: Ve$0)
880 "#,
881             r#"
882 struct Vec<T> {}
883 fn foo(xs: Vec<$0>)
884 "#,
885         );
886         check_edit(
887             "Vec",
888             r#"
889 type Vec<T> = (T,);
890 fn foo(xs: Ve$0)
891 "#,
892             r#"
893 type Vec<T> = (T,);
894 fn foo(xs: Vec<$0>)
895 "#,
896         );
897         check_edit(
898             "Vec",
899             r#"
900 struct Vec<T = i128> {}
901 fn foo(xs: Ve$0)
902 "#,
903             r#"
904 struct Vec<T = i128> {}
905 fn foo(xs: Vec)
906 "#,
907         );
908         check_edit(
909             "Vec",
910             r#"
911 struct Vec<T> {}
912 fn foo(xs: Ve$0<i128>)
913 "#,
914             r#"
915 struct Vec<T> {}
916 fn foo(xs: Vec<i128>)
917 "#,
918         );
919     }
920
921     #[test]
922     fn active_param_relevance() {
923         check_relevance(
924             r#"
925 struct S { foo: i64, bar: u32, baz: u32 }
926 fn test(bar: u32) { }
927 fn foo(s: S) { test(s.$0) }
928 "#,
929             expect![[r#"
930                 fd foo []
931                 fd bar [type+name]
932                 fd baz [type]
933             "#]],
934         );
935     }
936
937     #[test]
938     fn record_field_relevances() {
939         check_relevance(
940             r#"
941 struct A { foo: i64, bar: u32, baz: u32 }
942 struct B { x: (), y: f32, bar: u32 }
943 fn foo(a: A) { B { bar: a.$0 }; }
944 "#,
945             expect![[r#"
946                 fd foo []
947                 fd bar [type+name]
948                 fd baz [type]
949             "#]],
950         )
951     }
952
953     #[test]
954     fn record_field_and_call_relevances() {
955         check_relevance(
956             r#"
957 struct A { foo: i64, bar: u32, baz: u32 }
958 struct B { x: (), y: f32, bar: u32 }
959 fn f(foo: i64) {  }
960 fn foo(a: A) { B { bar: f(a.$0) }; }
961 "#,
962             expect![[r#"
963                 fd foo [type+name]
964                 fd bar []
965                 fd baz []
966             "#]],
967         );
968         check_relevance(
969             r#"
970 struct A { foo: i64, bar: u32, baz: u32 }
971 struct B { x: (), y: f32, bar: u32 }
972 fn f(foo: i64) {  }
973 fn foo(a: A) { f(B { bar: a.$0 }); }
974 "#,
975             expect![[r#"
976                 fd foo []
977                 fd bar [type+name]
978                 fd baz [type]
979             "#]],
980         );
981     }
982
983     #[test]
984     fn prioritize_exact_ref_match() {
985         check_relevance(
986             r#"
987 struct WorldSnapshot { _f: () };
988 fn go(world: &WorldSnapshot) { go(w$0) }
989 "#,
990             expect![[r#"
991                 lc world [type+name+local]
992                 st WorldSnapshot []
993                 fn go(…) []
994             "#]],
995         );
996     }
997
998     #[test]
999     fn too_many_arguments() {
1000         check_relevance(
1001             r#"
1002 struct Foo;
1003 fn f(foo: &Foo) { f(foo, w$0) }
1004 "#,
1005             expect![[r#"
1006                 lc foo [local]
1007                 st Foo []
1008                 fn f(…) []
1009             "#]],
1010         );
1011     }
1012
1013     #[test]
1014     fn score_fn_type_and_name_match() {
1015         check_relevance(
1016             r#"
1017 struct A { bar: u8 }
1018 fn baz() -> u8 { 0 }
1019 fn bar() -> u8 { 0 }
1020 fn f() { A { bar: b$0 }; }
1021 "#,
1022             expect![[r#"
1023                 fn baz() [type]
1024                 st A []
1025                 fn bar() [type+name]
1026                 fn f() []
1027             "#]],
1028         );
1029     }
1030
1031     #[test]
1032     fn score_method_type_and_name_match() {
1033         check_relevance(
1034             r#"
1035 fn baz(aaa: u32){}
1036 struct Foo;
1037 impl Foo {
1038 fn aaa(&self) -> u32 { 0 }
1039 fn bbb(&self) -> u32 { 0 }
1040 fn ccc(&self) -> u64 { 0 }
1041 }
1042 fn f() {
1043     baz(Foo.$0
1044 }
1045 "#,
1046             expect![[r#"
1047                 me aaa() [type+name]
1048                 me bbb() [type]
1049                 me ccc() []
1050             "#]],
1051         );
1052     }
1053
1054     #[test]
1055     fn score_method_name_match_only() {
1056         check_relevance(
1057             r#"
1058 fn baz(aaa: u32){}
1059 struct Foo;
1060 impl Foo {
1061 fn aaa(&self) -> u64 { 0 }
1062 }
1063 fn f() {
1064     baz(Foo.$0
1065 }
1066 "#,
1067             expect![[r#"
1068                 me aaa() [name]
1069             "#]],
1070         );
1071     }
1072
1073     #[test]
1074     fn suggest_ref_mut() {
1075         cov_mark::check!(suggest_ref);
1076         check(
1077             r#"
1078 struct S;
1079 fn foo(s: &mut S) {}
1080 fn main() {
1081     let mut s = S;
1082     foo($0);
1083 }
1084             "#,
1085             expect![[r#"
1086                 [
1087                     CompletionItem {
1088                         label: "S",
1089                         source_range: 70..70,
1090                         delete: 70..70,
1091                         insert: "S",
1092                         kind: SymbolKind(
1093                             Struct,
1094                         ),
1095                     },
1096                     CompletionItem {
1097                         label: "foo(…)",
1098                         source_range: 70..70,
1099                         delete: 70..70,
1100                         insert: "foo(${1:&mut s})$0",
1101                         kind: SymbolKind(
1102                             Function,
1103                         ),
1104                         lookup: "foo",
1105                         detail: "fn(&mut S)",
1106                         trigger_call_info: true,
1107                     },
1108                     CompletionItem {
1109                         label: "main()",
1110                         source_range: 70..70,
1111                         delete: 70..70,
1112                         insert: "main()$0",
1113                         kind: SymbolKind(
1114                             Function,
1115                         ),
1116                         lookup: "main",
1117                         detail: "fn()",
1118                     },
1119                     CompletionItem {
1120                         label: "s",
1121                         source_range: 70..70,
1122                         delete: 70..70,
1123                         insert: "s",
1124                         kind: SymbolKind(
1125                             Local,
1126                         ),
1127                         detail: "S",
1128                         relevance: CompletionRelevance {
1129                             exact_name_match: true,
1130                             type_match: None,
1131                             is_local: true,
1132                         },
1133                         ref_match: "&mut ",
1134                     },
1135                 ]
1136             "#]],
1137         )
1138     }
1139
1140     #[test]
1141     fn suggest_deref() {
1142         check_relevance(
1143             r#"
1144 #[lang = "deref"]
1145 trait Deref {
1146     type Target;
1147     fn deref(&self) -> &Self::Target;
1148 }
1149
1150 struct S;
1151 struct T(S);
1152
1153 impl Deref for T {
1154     type Target = S;
1155
1156     fn deref(&self) -> &Self::Target {
1157         &self.0
1158     }
1159 }
1160
1161 fn foo(s: &S) {}
1162
1163 fn main() {
1164     let t = T(S);
1165     let m = 123;
1166
1167     foo($0);
1168 }
1169             "#,
1170             expect![[r#"
1171                 lc m [local]
1172                 lc t [local]
1173                 lc &t [type+local]
1174                 st T []
1175                 st S []
1176                 fn main() []
1177                 tt Deref []
1178                 fn foo(…) []
1179             "#]],
1180         )
1181     }
1182
1183     #[test]
1184     fn suggest_deref_mut() {
1185         check_relevance(
1186             r#"
1187 #[lang = "deref"]
1188 trait Deref {
1189     type Target;
1190     fn deref(&self) -> &Self::Target;
1191 }
1192
1193 #[lang = "deref_mut"]
1194 pub trait DerefMut: Deref {
1195     fn deref_mut(&mut self) -> &mut Self::Target;
1196 }
1197
1198 struct S;
1199 struct T(S);
1200
1201 impl Deref for T {
1202     type Target = S;
1203
1204     fn deref(&self) -> &Self::Target {
1205         &self.0
1206     }
1207 }
1208
1209 impl DerefMut for T {
1210     fn deref_mut(&mut self) -> &mut Self::Target {
1211         &mut self.0
1212     }
1213 }
1214
1215 fn foo(s: &mut S) {}
1216
1217 fn main() {
1218     let t = T(S);
1219     let m = 123;
1220
1221     foo($0);
1222 }
1223             "#,
1224             expect![[r#"
1225                 lc m [local]
1226                 lc t [local]
1227                 lc &mut t [type+local]
1228                 tt DerefMut []
1229                 tt Deref []
1230                 fn foo(…) []
1231                 st T []
1232                 st S []
1233                 fn main() []
1234             "#]],
1235         )
1236     }
1237
1238     #[test]
1239     fn locals() {
1240         check_relevance(
1241             r#"
1242 fn foo(bar: u32) {
1243     let baz = 0;
1244
1245     f$0
1246 }
1247 "#,
1248             expect![[r#"
1249                 lc baz [local]
1250                 lc bar [local]
1251                 fn foo(…) []
1252             "#]],
1253         );
1254     }
1255
1256     #[test]
1257     fn enum_owned() {
1258         check_relevance(
1259             r#"
1260 enum Foo { A, B }
1261 fn foo() {
1262     bar($0);
1263 }
1264 fn bar(t: Foo) {}
1265 "#,
1266             expect![[r#"
1267                 ev Foo::A [type]
1268                 ev Foo::B [type]
1269                 en Foo []
1270                 fn bar(…) []
1271                 fn foo() []
1272             "#]],
1273         );
1274     }
1275
1276     #[test]
1277     fn enum_ref() {
1278         check_relevance(
1279             r#"
1280 enum Foo { A, B }
1281 fn foo() {
1282     bar($0);
1283 }
1284 fn bar(t: &Foo) {}
1285 "#,
1286             expect![[r#"
1287                 ev Foo::A []
1288                 ev &Foo::A [type]
1289                 ev Foo::B []
1290                 ev &Foo::B [type]
1291                 en Foo []
1292                 fn bar(…) []
1293                 fn foo() []
1294             "#]],
1295         );
1296     }
1297
1298     #[test]
1299     fn suggest_deref_fn_ret() {
1300         check_relevance(
1301             r#"
1302 #[lang = "deref"]
1303 trait Deref {
1304     type Target;
1305     fn deref(&self) -> &Self::Target;
1306 }
1307
1308 struct S;
1309 struct T(S);
1310
1311 impl Deref for T {
1312     type Target = S;
1313
1314     fn deref(&self) -> &Self::Target {
1315         &self.0
1316     }
1317 }
1318
1319 fn foo(s: &S) {}
1320 fn bar() -> T {}
1321
1322 fn main() {
1323     foo($0);
1324 }
1325             "#,
1326             expect![[r#"
1327                 tt Deref []
1328                 fn bar() []
1329                 fn &bar() [type]
1330                 fn foo(…) []
1331                 st T []
1332                 st S []
1333                 fn main() []
1334             "#]],
1335         )
1336     }
1337
1338     #[test]
1339     fn struct_field_method_ref() {
1340         check(
1341             r#"
1342 struct Foo { bar: u32 }
1343 impl Foo { fn baz(&self) -> u32 { 0 } }
1344
1345 fn foo(f: Foo) { let _: &u32 = f.b$0 }
1346 "#,
1347             // FIXME
1348             // Ideally we'd also suggest &f.bar and &f.baz() as exact
1349             // type matches. See #8058.
1350             expect![[r#"
1351                 [
1352                     CompletionItem {
1353                         label: "bar",
1354                         source_range: 98..99,
1355                         delete: 98..99,
1356                         insert: "bar",
1357                         kind: SymbolKind(
1358                             Field,
1359                         ),
1360                         detail: "u32",
1361                     },
1362                     CompletionItem {
1363                         label: "baz()",
1364                         source_range: 98..99,
1365                         delete: 98..99,
1366                         insert: "baz()$0",
1367                         kind: Method,
1368                         lookup: "baz",
1369                         detail: "fn(&self) -> u32",
1370                     },
1371                 ]
1372             "#]],
1373         );
1374     }
1375
1376     #[test]
1377     fn generic_enum() {
1378         check_relevance(
1379             r#"
1380 enum Foo<T> { A(T), B }
1381 // bar() should not be an exact type match
1382 // because the generic parameters are different
1383 fn bar() -> Foo<u8> { Foo::B }
1384 // FIXME baz() should be an exact type match
1385 // because the types could unify, but it currently
1386 // is not. This is due to the T here being
1387 // TyKind::Placeholder rather than TyKind::Missing.
1388 fn baz<T>() -> Foo<T> { Foo::B }
1389 fn foo() {
1390     let foo: Foo<u32> = Foo::B;
1391     let _: Foo<u32> = f$0;
1392 }
1393 "#,
1394             expect![[r#"
1395                 ev Foo::A(…) [type_could_unify]
1396                 ev Foo::B [type_could_unify]
1397                 lc foo [type+local]
1398                 en Foo []
1399                 fn baz() []
1400                 fn bar() []
1401                 fn foo() []
1402             "#]],
1403         );
1404     }
1405 }