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