]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/render.rs
91300c56e9379f10713d4e6b932fae1812a0d347
[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(_)) if self.ctx.completion.is_pat_or_const.is_some() => {
191                 CompletionItemKind::SymbolKind(SymbolKind::Variant)
192             }
193             ScopeDef::ModuleDef(Variant(var)) => {
194                 let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None);
195                 return Some(item);
196             }
197             ScopeDef::MacroDef(mac) => {
198                 let item = render_macro(self.ctx, import_to_add, local_name, *mac);
199                 return item;
200             }
201
202             ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
203             ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
204                 hir::Adt::Struct(_) => SymbolKind::Struct,
205                 hir::Adt::Union(_) => SymbolKind::Union,
206                 hir::Adt::Enum(_) => SymbolKind::Enum,
207             }),
208             ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
209             ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
210             ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
211             ScopeDef::ModuleDef(TypeAlias(..)) => {
212                 CompletionItemKind::SymbolKind(SymbolKind::TypeAlias)
213             }
214             ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
215             ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
216                 hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
217                 hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
218                 hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
219             }),
220             ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
221             ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
222             ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
223                 CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
224             }
225             ScopeDef::Unknown => {
226                 let mut item = CompletionItem::new(
227                     CompletionKind::Reference,
228                     self.ctx.source_range(),
229                     local_name,
230                 );
231                 item.kind(CompletionItemKind::UnresolvedReference).add_import(import_to_add);
232                 return Some(item.build());
233             }
234         };
235
236         let mut item =
237             CompletionItem::new(completion_kind, self.ctx.source_range(), local_name.clone());
238         if let ScopeDef::Local(local) = resolution {
239             let ty = local.ty(self.ctx.db());
240             if !ty.is_unknown() {
241                 item.detail(ty.display(self.ctx.db()).to_string());
242             }
243
244             item.set_relevance(CompletionRelevance {
245                 type_match: compute_type_match(self.ctx.completion, &ty),
246                 exact_name_match: compute_exact_name_match(self.ctx.completion, &local_name),
247                 is_local: true,
248                 ..CompletionRelevance::default()
249             });
250
251             if let Some(ref_match) = compute_ref_match(self.ctx.completion, &ty) {
252                 item.ref_match(ref_match);
253             }
254         };
255
256         // Add `<>` for generic types
257         if self.ctx.completion.is_path_type
258             && !self.ctx.completion.has_type_args
259             && self.ctx.completion.config.add_call_parenthesis
260         {
261             if let Some(cap) = self.ctx.snippet_cap() {
262                 let has_non_default_type_params = match resolution {
263                     ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(self.ctx.db()),
264                     ScopeDef::ModuleDef(TypeAlias(it)) => {
265                         it.has_non_default_type_params(self.ctx.db())
266                     }
267                     _ => false,
268                 };
269                 if has_non_default_type_params {
270                     cov_mark::hit!(inserts_angle_brackets_for_generics);
271                     item.lookup_by(local_name.clone())
272                         .label(format!("{}<…>", local_name))
273                         .insert_snippet(cap, format!("{}<$0>", local_name));
274                 }
275             }
276         }
277         item.kind(kind)
278             .add_import(import_to_add)
279             .set_documentation(self.docs(resolution))
280             .set_deprecated(self.is_deprecated(resolution));
281         Some(item.build())
282     }
283
284     fn docs(&self, resolution: &ScopeDef) -> Option<Documentation> {
285         use hir::ModuleDef::*;
286         match resolution {
287             ScopeDef::ModuleDef(Module(it)) => it.docs(self.ctx.db()),
288             ScopeDef::ModuleDef(Adt(it)) => it.docs(self.ctx.db()),
289             ScopeDef::ModuleDef(Variant(it)) => it.docs(self.ctx.db()),
290             ScopeDef::ModuleDef(Const(it)) => it.docs(self.ctx.db()),
291             ScopeDef::ModuleDef(Static(it)) => it.docs(self.ctx.db()),
292             ScopeDef::ModuleDef(Trait(it)) => it.docs(self.ctx.db()),
293             ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(self.ctx.db()),
294             _ => None,
295         }
296     }
297
298     fn is_deprecated(&self, resolution: &ScopeDef) -> bool {
299         match resolution {
300             ScopeDef::ModuleDef(it) => self.ctx.is_deprecated_assoc_item(*it),
301             ScopeDef::MacroDef(it) => self.ctx.is_deprecated(*it),
302             ScopeDef::GenericParam(it) => self.ctx.is_deprecated(*it),
303             ScopeDef::AdtSelfType(it) => self.ctx.is_deprecated(*it),
304             _ => false,
305         }
306     }
307 }
308
309 fn compute_type_match(
310     ctx: &CompletionContext,
311     completion_ty: &hir::Type,
312 ) -> Option<CompletionRelevanceTypeMatch> {
313     let expected_type = ctx.expected_type.as_ref()?;
314
315     // We don't ever consider unit type to be an exact type match, since
316     // nearly always this is not meaningful to the user.
317     if expected_type.is_unit() {
318         return None;
319     }
320
321     if completion_ty == expected_type {
322         Some(CompletionRelevanceTypeMatch::Exact)
323     } else if expected_type.could_unify_with(ctx.db, completion_ty) {
324         Some(CompletionRelevanceTypeMatch::CouldUnify)
325     } else {
326         None
327     }
328 }
329
330 fn compute_exact_name_match(ctx: &CompletionContext, completion_name: impl Into<String>) -> bool {
331     let completion_name = completion_name.into();
332     ctx.expected_name.as_ref().map_or(false, |name| name.text() == completion_name)
333 }
334
335 fn compute_ref_match(ctx: &CompletionContext, completion_ty: &hir::Type) -> Option<Mutability> {
336     let expected_type = ctx.expected_type.as_ref()?;
337     if completion_ty != expected_type {
338         let expected_type_without_ref = expected_type.remove_ref()?;
339         if completion_ty.autoderef(ctx.db).any(|deref_ty| deref_ty == expected_type_without_ref) {
340             cov_mark::hit!(suggest_ref);
341             let mutability = if expected_type.is_mutable_reference() {
342                 Mutability::Mut
343             } else {
344                 Mutability::Shared
345             };
346             return Some(mutability);
347         };
348     }
349     None
350 }
351
352 #[cfg(test)]
353 mod tests {
354     use expect_test::{expect, Expect};
355     use itertools::Itertools;
356
357     use crate::{
358         item::CompletionRelevanceTypeMatch,
359         test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG},
360         CompletionKind, CompletionRelevance,
361     };
362
363     fn check(ra_fixture: &str, expect: Expect) {
364         let actual = do_completion(ra_fixture, CompletionKind::Reference);
365         expect.assert_debug_eq(&actual);
366     }
367
368     fn check_relevance(ra_fixture: &str, expect: Expect) {
369         fn display_relevance(relevance: CompletionRelevance) -> String {
370             let relevance_factors = vec![
371                 (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
372                 (
373                     relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
374                     "type_could_unify",
375                 ),
376                 (relevance.exact_name_match, "name"),
377                 (relevance.is_local, "local"),
378             ]
379             .into_iter()
380             .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
381             .join("+");
382
383             format!("[{}]", relevance_factors)
384         }
385
386         let actual = get_all_items(TEST_CONFIG, ra_fixture)
387             .into_iter()
388             .filter(|it| it.completion_kind == CompletionKind::Reference)
389             .flat_map(|it| {
390                 let mut items = vec![];
391
392                 let tag = it.kind().unwrap().tag();
393                 let relevance = display_relevance(it.relevance());
394                 items.push(format!("{} {} {}\n", tag, it.label(), relevance));
395
396                 if let Some((mutability, relevance)) = it.ref_match() {
397                     let label = format!("&{}{}", mutability.as_keyword_for_ref(), it.label());
398                     let relevance = display_relevance(relevance);
399
400                     items.push(format!("{} {} {}\n", tag, label, relevance));
401                 }
402
403                 items
404             })
405             .collect::<String>();
406
407         expect.assert_eq(&actual);
408     }
409
410     #[test]
411     fn enum_detail_includes_record_fields() {
412         check(
413             r#"
414 enum Foo { Foo { x: i32, y: i32 } }
415
416 fn main() { Foo::Fo$0 }
417 "#,
418             expect![[r#"
419                 [
420                     CompletionItem {
421                         label: "Foo",
422                         source_range: 54..56,
423                         delete: 54..56,
424                         insert: "Foo",
425                         kind: SymbolKind(
426                             Variant,
427                         ),
428                         detail: "{ x: i32, y: i32 }",
429                     },
430                 ]
431             "#]],
432         );
433     }
434
435     #[test]
436     fn enum_detail_doesnt_include_tuple_fields() {
437         check(
438             r#"
439 enum Foo { Foo (i32, i32) }
440
441 fn main() { Foo::Fo$0 }
442 "#,
443             expect![[r#"
444                 [
445                     CompletionItem {
446                         label: "Foo(…)",
447                         source_range: 46..48,
448                         delete: 46..48,
449                         insert: "Foo($0)",
450                         kind: SymbolKind(
451                             Variant,
452                         ),
453                         lookup: "Foo",
454                         detail: "(i32, i32)",
455                         trigger_call_info: true,
456                     },
457                 ]
458             "#]],
459         );
460     }
461
462     #[test]
463     fn fn_detail_includes_args_and_return_type() {
464         check(
465             r#"
466 fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
467
468 fn main() { fo$0 }
469 "#,
470             expect![[r#"
471                 [
472                     CompletionItem {
473                         label: "foo(…)",
474                         source_range: 68..70,
475                         delete: 68..70,
476                         insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
477                         kind: SymbolKind(
478                             Function,
479                         ),
480                         lookup: "foo",
481                         detail: "fn(u32, u32, T) -> (u32, T)",
482                         trigger_call_info: true,
483                     },
484                     CompletionItem {
485                         label: "main()",
486                         source_range: 68..70,
487                         delete: 68..70,
488                         insert: "main()$0",
489                         kind: SymbolKind(
490                             Function,
491                         ),
492                         lookup: "main",
493                         detail: "fn()",
494                     },
495                 ]
496             "#]],
497         );
498     }
499
500     #[test]
501     fn enum_detail_just_parentheses_for_unit() {
502         check(
503             r#"
504 enum Foo { Foo }
505
506 fn main() { Foo::Fo$0 }
507 "#,
508             expect![[r#"
509                 [
510                     CompletionItem {
511                         label: "Foo",
512                         source_range: 35..37,
513                         delete: 35..37,
514                         insert: "Foo",
515                         kind: SymbolKind(
516                             Variant,
517                         ),
518                         detail: "()",
519                     },
520                 ]
521             "#]],
522         );
523     }
524
525     #[test]
526     fn lookup_enums_by_two_qualifiers() {
527         check(
528             r#"
529 mod m {
530     pub enum Spam { Foo, Bar(i32) }
531 }
532 fn main() { let _: m::Spam = S$0 }
533 "#,
534             expect![[r#"
535                 [
536                     CompletionItem {
537                         label: "Spam::Bar(…)",
538                         source_range: 75..76,
539                         delete: 75..76,
540                         insert: "Spam::Bar($0)",
541                         kind: SymbolKind(
542                             Variant,
543                         ),
544                         lookup: "Spam::Bar",
545                         detail: "(i32)",
546                         relevance: CompletionRelevance {
547                             exact_name_match: false,
548                             type_match: Some(
549                                 Exact,
550                             ),
551                             is_local: false,
552                         },
553                         trigger_call_info: true,
554                     },
555                     CompletionItem {
556                         label: "m",
557                         source_range: 75..76,
558                         delete: 75..76,
559                         insert: "m",
560                         kind: SymbolKind(
561                             Module,
562                         ),
563                     },
564                     CompletionItem {
565                         label: "m::Spam::Foo",
566                         source_range: 75..76,
567                         delete: 75..76,
568                         insert: "m::Spam::Foo",
569                         kind: SymbolKind(
570                             Variant,
571                         ),
572                         lookup: "Spam::Foo",
573                         detail: "()",
574                         relevance: CompletionRelevance {
575                             exact_name_match: false,
576                             type_match: Some(
577                                 Exact,
578                             ),
579                             is_local: false,
580                         },
581                     },
582                     CompletionItem {
583                         label: "main()",
584                         source_range: 75..76,
585                         delete: 75..76,
586                         insert: "main()$0",
587                         kind: SymbolKind(
588                             Function,
589                         ),
590                         lookup: "main",
591                         detail: "fn()",
592                     },
593                 ]
594             "#]],
595         )
596     }
597
598     #[test]
599     fn sets_deprecated_flag_in_items() {
600         check(
601             r#"
602 #[deprecated]
603 fn something_deprecated() {}
604 #[rustc_deprecated(since = "1.0.0")]
605 fn something_else_deprecated() {}
606
607 fn main() { som$0 }
608 "#,
609             expect![[r#"
610                 [
611                     CompletionItem {
612                         label: "main()",
613                         source_range: 127..130,
614                         delete: 127..130,
615                         insert: "main()$0",
616                         kind: SymbolKind(
617                             Function,
618                         ),
619                         lookup: "main",
620                         detail: "fn()",
621                     },
622                     CompletionItem {
623                         label: "something_deprecated()",
624                         source_range: 127..130,
625                         delete: 127..130,
626                         insert: "something_deprecated()$0",
627                         kind: SymbolKind(
628                             Function,
629                         ),
630                         lookup: "something_deprecated",
631                         detail: "fn()",
632                         deprecated: true,
633                     },
634                     CompletionItem {
635                         label: "something_else_deprecated()",
636                         source_range: 127..130,
637                         delete: 127..130,
638                         insert: "something_else_deprecated()$0",
639                         kind: SymbolKind(
640                             Function,
641                         ),
642                         lookup: "something_else_deprecated",
643                         detail: "fn()",
644                         deprecated: true,
645                     },
646                 ]
647             "#]],
648         );
649
650         check(
651             r#"
652 struct A { #[deprecated] the_field: u32 }
653 fn foo() { A { the$0 } }
654 "#,
655             expect![[r#"
656                 [
657                     CompletionItem {
658                         label: "the_field",
659                         source_range: 57..60,
660                         delete: 57..60,
661                         insert: "the_field",
662                         kind: SymbolKind(
663                             Field,
664                         ),
665                         detail: "u32",
666                         deprecated: true,
667                         relevance: CompletionRelevance {
668                             exact_name_match: false,
669                             type_match: Some(
670                                 CouldUnify,
671                             ),
672                             is_local: false,
673                         },
674                     },
675                 ]
676             "#]],
677         );
678     }
679
680     #[test]
681     fn renders_docs() {
682         check(
683             r#"
684 struct S {
685     /// Field docs
686     foo:
687 }
688 impl S {
689     /// Method docs
690     fn bar(self) { self.$0 }
691 }"#,
692             expect![[r#"
693                 [
694                     CompletionItem {
695                         label: "bar()",
696                         source_range: 94..94,
697                         delete: 94..94,
698                         insert: "bar()$0",
699                         kind: Method,
700                         lookup: "bar",
701                         detail: "fn(self)",
702                         documentation: Documentation(
703                             "Method docs",
704                         ),
705                     },
706                     CompletionItem {
707                         label: "foo",
708                         source_range: 94..94,
709                         delete: 94..94,
710                         insert: "foo",
711                         kind: SymbolKind(
712                             Field,
713                         ),
714                         detail: "{unknown}",
715                         documentation: Documentation(
716                             "Field docs",
717                         ),
718                     },
719                 ]
720             "#]],
721         );
722
723         check(
724             r#"
725 use self::my$0;
726
727 /// mod docs
728 mod my { }
729
730 /// enum docs
731 enum E {
732     /// variant docs
733     V
734 }
735 use self::E::*;
736 "#,
737             expect![[r#"
738                 [
739                     CompletionItem {
740                         label: "E",
741                         source_range: 10..12,
742                         delete: 10..12,
743                         insert: "E",
744                         kind: SymbolKind(
745                             Enum,
746                         ),
747                         documentation: Documentation(
748                             "enum docs",
749                         ),
750                     },
751                     CompletionItem {
752                         label: "V",
753                         source_range: 10..12,
754                         delete: 10..12,
755                         insert: "V",
756                         kind: SymbolKind(
757                             Variant,
758                         ),
759                         detail: "()",
760                         documentation: Documentation(
761                             "variant docs",
762                         ),
763                     },
764                     CompletionItem {
765                         label: "my",
766                         source_range: 10..12,
767                         delete: 10..12,
768                         insert: "my",
769                         kind: SymbolKind(
770                             Module,
771                         ),
772                         documentation: Documentation(
773                             "mod docs",
774                         ),
775                     },
776                 ]
777             "#]],
778         )
779     }
780
781     #[test]
782     fn dont_render_attrs() {
783         check(
784             r#"
785 struct S;
786 impl S {
787     #[inline]
788     fn the_method(&self) { }
789 }
790 fn foo(s: S) { s.$0 }
791 "#,
792             expect![[r#"
793                 [
794                     CompletionItem {
795                         label: "the_method()",
796                         source_range: 81..81,
797                         delete: 81..81,
798                         insert: "the_method()$0",
799                         kind: Method,
800                         lookup: "the_method",
801                         detail: "fn(&self)",
802                     },
803                 ]
804             "#]],
805         )
806     }
807
808     #[test]
809     fn no_call_parens_if_fn_ptr_needed() {
810         cov_mark::check!(no_call_parens_if_fn_ptr_needed);
811         check_edit(
812             "foo",
813             r#"
814 fn foo(foo: u8, bar: u8) {}
815 struct ManualVtable { f: fn(u8, u8) }
816
817 fn main() -> ManualVtable {
818     ManualVtable { f: f$0 }
819 }
820 "#,
821             r#"
822 fn foo(foo: u8, bar: u8) {}
823 struct ManualVtable { f: fn(u8, u8) }
824
825 fn main() -> ManualVtable {
826     ManualVtable { f: foo }
827 }
828 "#,
829         );
830     }
831
832     #[test]
833     fn no_parens_in_use_item() {
834         cov_mark::check!(no_parens_in_use_item);
835         check_edit(
836             "foo",
837             r#"
838 mod m { pub fn foo() {} }
839 use crate::m::f$0;
840 "#,
841             r#"
842 mod m { pub fn foo() {} }
843 use crate::m::foo;
844 "#,
845         );
846     }
847
848     #[test]
849     fn no_parens_in_call() {
850         check_edit(
851             "foo",
852             r#"
853 fn foo(x: i32) {}
854 fn main() { f$0(); }
855 "#,
856             r#"
857 fn foo(x: i32) {}
858 fn main() { foo(); }
859 "#,
860         );
861         check_edit(
862             "foo",
863             r#"
864 struct Foo;
865 impl Foo { fn foo(&self){} }
866 fn f(foo: &Foo) { foo.f$0(); }
867 "#,
868             r#"
869 struct Foo;
870 impl Foo { fn foo(&self){} }
871 fn f(foo: &Foo) { foo.foo(); }
872 "#,
873         );
874     }
875
876     #[test]
877     fn inserts_angle_brackets_for_generics() {
878         cov_mark::check!(inserts_angle_brackets_for_generics);
879         check_edit(
880             "Vec",
881             r#"
882 struct Vec<T> {}
883 fn foo(xs: Ve$0)
884 "#,
885             r#"
886 struct Vec<T> {}
887 fn foo(xs: Vec<$0>)
888 "#,
889         );
890         check_edit(
891             "Vec",
892             r#"
893 type Vec<T> = (T,);
894 fn foo(xs: Ve$0)
895 "#,
896             r#"
897 type Vec<T> = (T,);
898 fn foo(xs: Vec<$0>)
899 "#,
900         );
901         check_edit(
902             "Vec",
903             r#"
904 struct Vec<T = i128> {}
905 fn foo(xs: Ve$0)
906 "#,
907             r#"
908 struct Vec<T = i128> {}
909 fn foo(xs: Vec)
910 "#,
911         );
912         check_edit(
913             "Vec",
914             r#"
915 struct Vec<T> {}
916 fn foo(xs: Ve$0<i128>)
917 "#,
918             r#"
919 struct Vec<T> {}
920 fn foo(xs: Vec<i128>)
921 "#,
922         );
923     }
924
925     #[test]
926     fn active_param_relevance() {
927         check_relevance(
928             r#"
929 struct S { foo: i64, bar: u32, baz: u32 }
930 fn test(bar: u32) { }
931 fn foo(s: S) { test(s.$0) }
932 "#,
933             expect![[r#"
934                 fd foo []
935                 fd bar [type+name]
936                 fd baz [type]
937             "#]],
938         );
939     }
940
941     #[test]
942     fn record_field_relevances() {
943         check_relevance(
944             r#"
945 struct A { foo: i64, bar: u32, baz: u32 }
946 struct B { x: (), y: f32, bar: u32 }
947 fn foo(a: A) { B { bar: a.$0 }; }
948 "#,
949             expect![[r#"
950                 fd foo []
951                 fd bar [type+name]
952                 fd baz [type]
953             "#]],
954         )
955     }
956
957     #[test]
958     fn record_field_and_call_relevances() {
959         check_relevance(
960             r#"
961 struct A { foo: i64, bar: u32, baz: u32 }
962 struct B { x: (), y: f32, bar: u32 }
963 fn f(foo: i64) {  }
964 fn foo(a: A) { B { bar: f(a.$0) }; }
965 "#,
966             expect![[r#"
967                 fd foo [type+name]
968                 fd bar []
969                 fd baz []
970             "#]],
971         );
972         check_relevance(
973             r#"
974 struct A { foo: i64, bar: u32, baz: u32 }
975 struct B { x: (), y: f32, bar: u32 }
976 fn f(foo: i64) {  }
977 fn foo(a: A) { f(B { bar: a.$0 }); }
978 "#,
979             expect![[r#"
980                 fd foo []
981                 fd bar [type+name]
982                 fd baz [type]
983             "#]],
984         );
985     }
986
987     #[test]
988     fn prioritize_exact_ref_match() {
989         check_relevance(
990             r#"
991 struct WorldSnapshot { _f: () };
992 fn go(world: &WorldSnapshot) { go(w$0) }
993 "#,
994             expect![[r#"
995                 lc world [type+name+local]
996                 st WorldSnapshot []
997                 fn go(…) []
998             "#]],
999         );
1000     }
1001
1002     #[test]
1003     fn too_many_arguments() {
1004         check_relevance(
1005             r#"
1006 struct Foo;
1007 fn f(foo: &Foo) { f(foo, w$0) }
1008 "#,
1009             expect![[r#"
1010                 lc foo [local]
1011                 st Foo []
1012                 fn f(…) []
1013             "#]],
1014         );
1015     }
1016
1017     #[test]
1018     fn score_fn_type_and_name_match() {
1019         check_relevance(
1020             r#"
1021 struct A { bar: u8 }
1022 fn baz() -> u8 { 0 }
1023 fn bar() -> u8 { 0 }
1024 fn f() { A { bar: b$0 }; }
1025 "#,
1026             expect![[r#"
1027                 fn baz() [type]
1028                 st A []
1029                 fn bar() [type+name]
1030                 fn f() []
1031             "#]],
1032         );
1033     }
1034
1035     #[test]
1036     fn score_method_type_and_name_match() {
1037         check_relevance(
1038             r#"
1039 fn baz(aaa: u32){}
1040 struct Foo;
1041 impl Foo {
1042 fn aaa(&self) -> u32 { 0 }
1043 fn bbb(&self) -> u32 { 0 }
1044 fn ccc(&self) -> u64 { 0 }
1045 }
1046 fn f() {
1047     baz(Foo.$0
1048 }
1049 "#,
1050             expect![[r#"
1051                 me aaa() [type+name]
1052                 me bbb() [type]
1053                 me ccc() []
1054             "#]],
1055         );
1056     }
1057
1058     #[test]
1059     fn score_method_name_match_only() {
1060         check_relevance(
1061             r#"
1062 fn baz(aaa: u32){}
1063 struct Foo;
1064 impl Foo {
1065 fn aaa(&self) -> u64 { 0 }
1066 }
1067 fn f() {
1068     baz(Foo.$0
1069 }
1070 "#,
1071             expect![[r#"
1072                 me aaa() [name]
1073             "#]],
1074         );
1075     }
1076
1077     #[test]
1078     fn suggest_ref_mut() {
1079         cov_mark::check!(suggest_ref);
1080         check(
1081             r#"
1082 struct S;
1083 fn foo(s: &mut S) {}
1084 fn main() {
1085     let mut s = S;
1086     foo($0);
1087 }
1088             "#,
1089             expect![[r#"
1090                 [
1091                     CompletionItem {
1092                         label: "S",
1093                         source_range: 70..70,
1094                         delete: 70..70,
1095                         insert: "S",
1096                         kind: SymbolKind(
1097                             Struct,
1098                         ),
1099                     },
1100                     CompletionItem {
1101                         label: "foo(…)",
1102                         source_range: 70..70,
1103                         delete: 70..70,
1104                         insert: "foo(${1:&mut s})$0",
1105                         kind: SymbolKind(
1106                             Function,
1107                         ),
1108                         lookup: "foo",
1109                         detail: "fn(&mut S)",
1110                         trigger_call_info: true,
1111                     },
1112                     CompletionItem {
1113                         label: "main()",
1114                         source_range: 70..70,
1115                         delete: 70..70,
1116                         insert: "main()$0",
1117                         kind: SymbolKind(
1118                             Function,
1119                         ),
1120                         lookup: "main",
1121                         detail: "fn()",
1122                     },
1123                     CompletionItem {
1124                         label: "s",
1125                         source_range: 70..70,
1126                         delete: 70..70,
1127                         insert: "s",
1128                         kind: SymbolKind(
1129                             Local,
1130                         ),
1131                         detail: "S",
1132                         relevance: CompletionRelevance {
1133                             exact_name_match: true,
1134                             type_match: None,
1135                             is_local: true,
1136                         },
1137                         ref_match: "&mut ",
1138                     },
1139                 ]
1140             "#]],
1141         )
1142     }
1143
1144     #[test]
1145     fn suggest_deref() {
1146         check_relevance(
1147             r#"
1148 #[lang = "deref"]
1149 trait Deref {
1150     type Target;
1151     fn deref(&self) -> &Self::Target;
1152 }
1153
1154 struct S;
1155 struct T(S);
1156
1157 impl Deref for T {
1158     type Target = S;
1159
1160     fn deref(&self) -> &Self::Target {
1161         &self.0
1162     }
1163 }
1164
1165 fn foo(s: &S) {}
1166
1167 fn main() {
1168     let t = T(S);
1169     let m = 123;
1170
1171     foo($0);
1172 }
1173             "#,
1174             expect![[r#"
1175                 lc m [local]
1176                 lc t [local]
1177                 lc &t [type+local]
1178                 st T []
1179                 st S []
1180                 fn main() []
1181                 tt Deref []
1182                 fn foo(…) []
1183             "#]],
1184         )
1185     }
1186
1187     #[test]
1188     fn suggest_deref_mut() {
1189         check_relevance(
1190             r#"
1191 #[lang = "deref"]
1192 trait Deref {
1193     type Target;
1194     fn deref(&self) -> &Self::Target;
1195 }
1196
1197 #[lang = "deref_mut"]
1198 pub trait DerefMut: Deref {
1199     fn deref_mut(&mut self) -> &mut Self::Target;
1200 }
1201
1202 struct S;
1203 struct T(S);
1204
1205 impl Deref for T {
1206     type Target = S;
1207
1208     fn deref(&self) -> &Self::Target {
1209         &self.0
1210     }
1211 }
1212
1213 impl DerefMut for T {
1214     fn deref_mut(&mut self) -> &mut Self::Target {
1215         &mut self.0
1216     }
1217 }
1218
1219 fn foo(s: &mut S) {}
1220
1221 fn main() {
1222     let t = T(S);
1223     let m = 123;
1224
1225     foo($0);
1226 }
1227             "#,
1228             expect![[r#"
1229                 lc m [local]
1230                 lc t [local]
1231                 lc &mut t [type+local]
1232                 tt DerefMut []
1233                 tt Deref []
1234                 fn foo(…) []
1235                 st T []
1236                 st S []
1237                 fn main() []
1238             "#]],
1239         )
1240     }
1241
1242     #[test]
1243     fn locals() {
1244         check_relevance(
1245             r#"
1246 fn foo(bar: u32) {
1247     let baz = 0;
1248
1249     f$0
1250 }
1251 "#,
1252             expect![[r#"
1253                 lc baz [local]
1254                 lc bar [local]
1255                 fn foo(…) []
1256             "#]],
1257         );
1258     }
1259
1260     #[test]
1261     fn enum_owned() {
1262         check_relevance(
1263             r#"
1264 enum Foo { A, B }
1265 fn foo() {
1266     bar($0);
1267 }
1268 fn bar(t: Foo) {}
1269 "#,
1270             expect![[r#"
1271                 ev Foo::A [type]
1272                 ev Foo::B [type]
1273                 en Foo []
1274                 fn bar(…) []
1275                 fn foo() []
1276             "#]],
1277         );
1278     }
1279
1280     #[test]
1281     fn enum_ref() {
1282         check_relevance(
1283             r#"
1284 enum Foo { A, B }
1285 fn foo() {
1286     bar($0);
1287 }
1288 fn bar(t: &Foo) {}
1289 "#,
1290             expect![[r#"
1291                 ev Foo::A []
1292                 ev &Foo::A [type]
1293                 ev Foo::B []
1294                 ev &Foo::B [type]
1295                 en Foo []
1296                 fn bar(…) []
1297                 fn foo() []
1298             "#]],
1299         );
1300     }
1301
1302     #[test]
1303     fn suggest_deref_fn_ret() {
1304         check_relevance(
1305             r#"
1306 #[lang = "deref"]
1307 trait Deref {
1308     type Target;
1309     fn deref(&self) -> &Self::Target;
1310 }
1311
1312 struct S;
1313 struct T(S);
1314
1315 impl Deref for T {
1316     type Target = S;
1317
1318     fn deref(&self) -> &Self::Target {
1319         &self.0
1320     }
1321 }
1322
1323 fn foo(s: &S) {}
1324 fn bar() -> T {}
1325
1326 fn main() {
1327     foo($0);
1328 }
1329             "#,
1330             expect![[r#"
1331                 tt Deref []
1332                 fn bar() []
1333                 fn &bar() [type]
1334                 fn foo(…) []
1335                 st T []
1336                 st S []
1337                 fn main() []
1338             "#]],
1339         )
1340     }
1341
1342     #[test]
1343     fn struct_field_method_ref() {
1344         check(
1345             r#"
1346 struct Foo { bar: u32 }
1347 impl Foo { fn baz(&self) -> u32 { 0 } }
1348
1349 fn foo(f: Foo) { let _: &u32 = f.b$0 }
1350 "#,
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: "bar",
1358                         source_range: 98..99,
1359                         delete: 98..99,
1360                         insert: "bar",
1361                         kind: SymbolKind(
1362                             Field,
1363                         ),
1364                         detail: "u32",
1365                     },
1366                     CompletionItem {
1367                         label: "baz()",
1368                         source_range: 98..99,
1369                         delete: 98..99,
1370                         insert: "baz()$0",
1371                         kind: Method,
1372                         lookup: "baz",
1373                         detail: "fn(&self) -> u32",
1374                     },
1375                 ]
1376             "#]],
1377         );
1378     }
1379
1380     #[test]
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                 ev Foo::A(…) [type_could_unify]
1400                 ev Foo::B [type_could_unify]
1401                 lc foo [type+local]
1402                 en Foo []
1403                 fn baz() []
1404                 fn bar() []
1405                 fn foo() []
1406             "#]],
1407         );
1408     }
1409 }