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