]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/render.rs
Merge #9356
[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_relevance(
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                 lc s [name+local]
1071                 lc &mut s [type+name+local]
1072                 st S []
1073                 fn main() []
1074                 fn foo(…) []
1075             "#]],
1076         );
1077         check_relevance(
1078             r#"
1079 struct S;
1080 fn foo(s: &mut S) {}
1081 fn main() {
1082     let mut s = S;
1083     foo(&mut $0);
1084 }
1085             "#,
1086             expect![[r#"
1087                 lc s [type+name+local]
1088                 st S []
1089                 fn main() []
1090                 fn foo(…) []
1091             "#]],
1092         );
1093     }
1094
1095     #[test]
1096     fn suggest_deref() {
1097         check_relevance(
1098             r#"
1099 //- minicore: deref
1100 struct S;
1101 struct T(S);
1102
1103 impl core::ops::Deref for T {
1104     type Target = S;
1105
1106     fn deref(&self) -> &Self::Target {
1107         &self.0
1108     }
1109 }
1110
1111 fn foo(s: &S) {}
1112
1113 fn main() {
1114     let t = T(S);
1115     let m = 123;
1116
1117     foo($0);
1118 }
1119             "#,
1120             expect![[r#"
1121                 lc m [local]
1122                 lc t [local]
1123                 lc &t [type+local]
1124                 st T []
1125                 st S []
1126                 fn main() []
1127                 fn foo(…) []
1128                 md core []
1129                 tt Sized []
1130             "#]],
1131         )
1132     }
1133
1134     #[test]
1135     fn suggest_deref_mut() {
1136         check_relevance(
1137             r#"
1138 //- minicore: deref_mut
1139 struct S;
1140 struct T(S);
1141
1142 impl core::ops::Deref for T {
1143     type Target = S;
1144
1145     fn deref(&self) -> &Self::Target {
1146         &self.0
1147     }
1148 }
1149
1150 impl core::ops::DerefMut for T {
1151     fn deref_mut(&mut self) -> &mut Self::Target {
1152         &mut self.0
1153     }
1154 }
1155
1156 fn foo(s: &mut S) {}
1157
1158 fn main() {
1159     let t = T(S);
1160     let m = 123;
1161
1162     foo($0);
1163 }
1164             "#,
1165             expect![[r#"
1166                 lc m [local]
1167                 lc t [local]
1168                 lc &mut t [type+local]
1169                 st T []
1170                 st S []
1171                 fn main() []
1172                 fn foo(…) []
1173                 md core []
1174                 tt Sized []
1175             "#]],
1176         )
1177     }
1178
1179     #[test]
1180     fn locals() {
1181         check_relevance(
1182             r#"
1183 fn foo(bar: u32) {
1184     let baz = 0;
1185
1186     f$0
1187 }
1188 "#,
1189             expect![[r#"
1190                 lc baz [local]
1191                 lc bar [local]
1192                 fn foo(…) []
1193             "#]],
1194         );
1195     }
1196
1197     #[test]
1198     fn enum_owned() {
1199         check_relevance(
1200             r#"
1201 enum Foo { A, B }
1202 fn foo() {
1203     bar($0);
1204 }
1205 fn bar(t: Foo) {}
1206 "#,
1207             expect![[r#"
1208                 ev Foo::A [type]
1209                 ev Foo::B [type]
1210                 en Foo []
1211                 fn bar(…) []
1212                 fn foo() []
1213             "#]],
1214         );
1215     }
1216
1217     #[test]
1218     fn enum_ref() {
1219         check_relevance(
1220             r#"
1221 enum Foo { A, B }
1222 fn foo() {
1223     bar($0);
1224 }
1225 fn bar(t: &Foo) {}
1226 "#,
1227             expect![[r#"
1228                 ev Foo::A []
1229                 ev &Foo::A [type]
1230                 ev Foo::B []
1231                 ev &Foo::B [type]
1232                 en Foo []
1233                 fn bar(…) []
1234                 fn foo() []
1235             "#]],
1236         );
1237     }
1238
1239     #[test]
1240     fn suggest_deref_fn_ret() {
1241         check_relevance(
1242             r#"
1243 //- minicore: deref
1244 struct S;
1245 struct T(S);
1246
1247 impl core::ops::Deref for T {
1248     type Target = S;
1249
1250     fn deref(&self) -> &Self::Target {
1251         &self.0
1252     }
1253 }
1254
1255 fn foo(s: &S) {}
1256 fn bar() -> T {}
1257
1258 fn main() {
1259     foo($0);
1260 }
1261 "#,
1262             expect![[r#"
1263                 st T []
1264                 st S []
1265                 fn main() []
1266                 fn bar() []
1267                 fn &bar() [type]
1268                 fn foo(…) []
1269                 md core []
1270                 tt Sized []
1271             "#]],
1272         )
1273     }
1274
1275     #[test]
1276     fn struct_field_method_ref() {
1277         check(
1278             r#"
1279 struct Foo { bar: u32 }
1280 impl Foo { fn baz(&self) -> u32 { 0 } }
1281
1282 fn foo(f: Foo) { let _: &u32 = f.b$0 }
1283 "#,
1284             // FIXME
1285             // Ideally we'd also suggest &f.bar and &f.baz() as exact
1286             // type matches. See #8058.
1287             expect![[r#"
1288                 [
1289                     CompletionItem {
1290                         label: "bar",
1291                         source_range: 98..99,
1292                         delete: 98..99,
1293                         insert: "bar",
1294                         kind: SymbolKind(
1295                             Field,
1296                         ),
1297                         detail: "u32",
1298                     },
1299                     CompletionItem {
1300                         label: "baz()",
1301                         source_range: 98..99,
1302                         delete: 98..99,
1303                         insert: "baz()$0",
1304                         kind: Method,
1305                         lookup: "baz",
1306                         detail: "fn(&self) -> u32",
1307                     },
1308                 ]
1309             "#]],
1310         );
1311     }
1312
1313     #[test]
1314     fn generic_enum() {
1315         check_relevance(
1316             r#"
1317 enum Foo<T> { A(T), B }
1318 // bar() should not be an exact type match
1319 // because the generic parameters are different
1320 fn bar() -> Foo<u8> { Foo::B }
1321 // FIXME baz() should be an exact type match
1322 // because the types could unify, but it currently
1323 // is not. This is due to the T here being
1324 // TyKind::Placeholder rather than TyKind::Missing.
1325 fn baz<T>() -> Foo<T> { Foo::B }
1326 fn foo() {
1327     let foo: Foo<u32> = Foo::B;
1328     let _: Foo<u32> = f$0;
1329 }
1330 "#,
1331             expect![[r#"
1332                 ev Foo::A(…) [type_could_unify]
1333                 ev Foo::B [type_could_unify]
1334                 lc foo [type+local]
1335                 en Foo []
1336                 fn baz() []
1337                 fn bar() []
1338                 fn foo() []
1339             "#]],
1340         );
1341     }
1342 }