]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/render.rs
Merge #9775
[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 std::cmp;
334
335     use expect_test::{expect, Expect};
336     use itertools::Itertools;
337
338     use crate::{
339         item::CompletionRelevanceTypeMatch,
340         tests::{check_edit, do_completion, get_all_items, TEST_CONFIG},
341         CompletionKind, CompletionRelevance,
342     };
343
344     #[track_caller]
345     fn check(ra_fixture: &str, expect: Expect) {
346         let actual = do_completion(ra_fixture, CompletionKind::Reference);
347         expect.assert_debug_eq(&actual);
348     }
349
350     #[track_caller]
351     fn check_relevance(ra_fixture: &str, expect: Expect) {
352         check_relevance_for_kinds(&[CompletionKind::Reference], ra_fixture, expect)
353     }
354
355     #[track_caller]
356     fn check_relevance_for_kinds(kinds: &[CompletionKind], ra_fixture: &str, expect: Expect) {
357         let mut actual = get_all_items(TEST_CONFIG, ra_fixture);
358         actual.retain(|it| kinds.contains(&it.completion_kind));
359         actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
360
361         let actual = actual
362             .into_iter()
363             .flat_map(|it| {
364                 let mut items = vec![];
365
366                 let tag = it.kind().unwrap().tag();
367                 let relevance = display_relevance(it.relevance());
368                 items.push(format!("{} {} {}\n", tag, it.label(), relevance));
369
370                 if let Some((mutability, relevance)) = it.ref_match() {
371                     let label = format!("&{}{}", mutability.as_keyword_for_ref(), it.label());
372                     let relevance = display_relevance(relevance);
373
374                     items.push(format!("{} {} {}\n", tag, label, relevance));
375                 }
376
377                 items
378             })
379             .collect::<String>();
380
381         expect.assert_eq(&actual);
382
383         fn display_relevance(relevance: CompletionRelevance) -> String {
384             let relevance_factors = vec![
385                 (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
386                 (
387                     relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
388                     "type_could_unify",
389                 ),
390                 (relevance.exact_name_match, "name"),
391                 (relevance.is_local, "local"),
392                 (relevance.exact_postfix_snippet_match, "snippet"),
393             ]
394             .into_iter()
395             .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
396             .join("+");
397
398             format!("[{}]", relevance_factors)
399         }
400     }
401
402     #[test]
403     fn enum_detail_includes_record_fields() {
404         check(
405             r#"
406 enum Foo { Foo { x: i32, y: i32 } }
407
408 fn main() { Foo::Fo$0 }
409 "#,
410             expect![[r#"
411                 [
412                     CompletionItem {
413                         label: "Foo",
414                         source_range: 54..56,
415                         delete: 54..56,
416                         insert: "Foo",
417                         kind: SymbolKind(
418                             Variant,
419                         ),
420                         detail: "{ x: i32, y: i32 }",
421                     },
422                 ]
423             "#]],
424         );
425     }
426
427     #[test]
428     fn enum_detail_doesnt_include_tuple_fields() {
429         check(
430             r#"
431 enum Foo { Foo (i32, i32) }
432
433 fn main() { Foo::Fo$0 }
434 "#,
435             expect![[r#"
436                 [
437                     CompletionItem {
438                         label: "Foo(…)",
439                         source_range: 46..48,
440                         delete: 46..48,
441                         insert: "Foo($0)",
442                         kind: SymbolKind(
443                             Variant,
444                         ),
445                         lookup: "Foo",
446                         detail: "(i32, i32)",
447                         trigger_call_info: true,
448                     },
449                 ]
450             "#]],
451         );
452     }
453
454     #[test]
455     fn fn_detail_includes_args_and_return_type() {
456         check(
457             r#"
458 fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
459
460 fn main() { fo$0 }
461 "#,
462             expect![[r#"
463                 [
464                     CompletionItem {
465                         label: "foo(…)",
466                         source_range: 68..70,
467                         delete: 68..70,
468                         insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
469                         kind: SymbolKind(
470                             Function,
471                         ),
472                         lookup: "foo",
473                         detail: "fn(u32, u32, T) -> (u32, T)",
474                         trigger_call_info: true,
475                     },
476                     CompletionItem {
477                         label: "main()",
478                         source_range: 68..70,
479                         delete: 68..70,
480                         insert: "main()$0",
481                         kind: SymbolKind(
482                             Function,
483                         ),
484                         lookup: "main",
485                         detail: "fn()",
486                     },
487                 ]
488             "#]],
489         );
490     }
491
492     #[test]
493     fn enum_detail_just_parentheses_for_unit() {
494         check(
495             r#"
496 enum Foo { Foo }
497
498 fn main() { Foo::Fo$0 }
499 "#,
500             expect![[r#"
501                 [
502                     CompletionItem {
503                         label: "Foo",
504                         source_range: 35..37,
505                         delete: 35..37,
506                         insert: "Foo",
507                         kind: SymbolKind(
508                             Variant,
509                         ),
510                         detail: "()",
511                     },
512                 ]
513             "#]],
514         );
515     }
516
517     #[test]
518     fn lookup_enums_by_two_qualifiers() {
519         check(
520             r#"
521 mod m {
522     pub enum Spam { Foo, Bar(i32) }
523 }
524 fn main() { let _: m::Spam = S$0 }
525 "#,
526             expect![[r#"
527                 [
528                     CompletionItem {
529                         label: "Spam::Bar(…)",
530                         source_range: 75..76,
531                         delete: 75..76,
532                         insert: "Spam::Bar($0)",
533                         kind: SymbolKind(
534                             Variant,
535                         ),
536                         lookup: "Spam::Bar",
537                         detail: "(i32)",
538                         relevance: CompletionRelevance {
539                             exact_name_match: false,
540                             type_match: Some(
541                                 Exact,
542                             ),
543                             is_local: false,
544                             exact_postfix_snippet_match: false,
545                         },
546                         trigger_call_info: true,
547                     },
548                     CompletionItem {
549                         label: "m",
550                         source_range: 75..76,
551                         delete: 75..76,
552                         insert: "m",
553                         kind: SymbolKind(
554                             Module,
555                         ),
556                     },
557                     CompletionItem {
558                         label: "m::Spam::Foo",
559                         source_range: 75..76,
560                         delete: 75..76,
561                         insert: "m::Spam::Foo",
562                         kind: SymbolKind(
563                             Variant,
564                         ),
565                         lookup: "Spam::Foo",
566                         detail: "()",
567                         relevance: CompletionRelevance {
568                             exact_name_match: false,
569                             type_match: Some(
570                                 Exact,
571                             ),
572                             is_local: false,
573                             exact_postfix_snippet_match: false,
574                         },
575                     },
576                     CompletionItem {
577                         label: "main()",
578                         source_range: 75..76,
579                         delete: 75..76,
580                         insert: "main()$0",
581                         kind: SymbolKind(
582                             Function,
583                         ),
584                         lookup: "main",
585                         detail: "fn()",
586                     },
587                 ]
588             "#]],
589         )
590     }
591
592     #[test]
593     fn sets_deprecated_flag_in_items() {
594         check(
595             r#"
596 #[deprecated]
597 fn something_deprecated() {}
598 #[rustc_deprecated(since = "1.0.0")]
599 fn something_else_deprecated() {}
600
601 fn main() { som$0 }
602 "#,
603             expect![[r#"
604                 [
605                     CompletionItem {
606                         label: "main()",
607                         source_range: 127..130,
608                         delete: 127..130,
609                         insert: "main()$0",
610                         kind: SymbolKind(
611                             Function,
612                         ),
613                         lookup: "main",
614                         detail: "fn()",
615                     },
616                     CompletionItem {
617                         label: "something_deprecated()",
618                         source_range: 127..130,
619                         delete: 127..130,
620                         insert: "something_deprecated()$0",
621                         kind: SymbolKind(
622                             Function,
623                         ),
624                         lookup: "something_deprecated",
625                         detail: "fn()",
626                         deprecated: true,
627                     },
628                     CompletionItem {
629                         label: "something_else_deprecated()",
630                         source_range: 127..130,
631                         delete: 127..130,
632                         insert: "something_else_deprecated()$0",
633                         kind: SymbolKind(
634                             Function,
635                         ),
636                         lookup: "something_else_deprecated",
637                         detail: "fn()",
638                         deprecated: true,
639                     },
640                 ]
641             "#]],
642         );
643
644         check(
645             r#"
646 struct A { #[deprecated] the_field: u32 }
647 fn foo() { A { the$0 } }
648 "#,
649             expect![[r#"
650                 [
651                     CompletionItem {
652                         label: "the_field",
653                         source_range: 57..60,
654                         delete: 57..60,
655                         insert: "the_field",
656                         kind: SymbolKind(
657                             Field,
658                         ),
659                         detail: "u32",
660                         deprecated: true,
661                         relevance: CompletionRelevance {
662                             exact_name_match: false,
663                             type_match: Some(
664                                 CouldUnify,
665                             ),
666                             is_local: false,
667                             exact_postfix_snippet_match: false,
668                         },
669                     },
670                 ]
671             "#]],
672         );
673     }
674
675     #[test]
676     fn renders_docs() {
677         check(
678             r#"
679 struct S {
680     /// Field docs
681     foo:
682 }
683 impl S {
684     /// Method docs
685     fn bar(self) { self.$0 }
686 }"#,
687             expect![[r#"
688                 [
689                     CompletionItem {
690                         label: "bar()",
691                         source_range: 94..94,
692                         delete: 94..94,
693                         insert: "bar()$0",
694                         kind: Method,
695                         lookup: "bar",
696                         detail: "fn(self)",
697                         documentation: Documentation(
698                             "Method docs",
699                         ),
700                     },
701                     CompletionItem {
702                         label: "foo",
703                         source_range: 94..94,
704                         delete: 94..94,
705                         insert: "foo",
706                         kind: SymbolKind(
707                             Field,
708                         ),
709                         detail: "{unknown}",
710                         documentation: Documentation(
711                             "Field docs",
712                         ),
713                     },
714                 ]
715             "#]],
716         );
717
718         check(
719             r#"
720 use self::my$0;
721
722 /// mod docs
723 mod my { }
724
725 /// enum docs
726 enum E {
727     /// variant docs
728     V
729 }
730 use self::E::*;
731 "#,
732             expect![[r#"
733                 [
734                     CompletionItem {
735                         label: "E",
736                         source_range: 10..12,
737                         delete: 10..12,
738                         insert: "E",
739                         kind: SymbolKind(
740                             Enum,
741                         ),
742                         documentation: Documentation(
743                             "enum docs",
744                         ),
745                     },
746                     CompletionItem {
747                         label: "V",
748                         source_range: 10..12,
749                         delete: 10..12,
750                         insert: "V",
751                         kind: SymbolKind(
752                             Variant,
753                         ),
754                         detail: "()",
755                         documentation: Documentation(
756                             "variant docs",
757                         ),
758                     },
759                     CompletionItem {
760                         label: "my",
761                         source_range: 10..12,
762                         delete: 10..12,
763                         insert: "my",
764                         kind: SymbolKind(
765                             Module,
766                         ),
767                         documentation: Documentation(
768                             "mod docs",
769                         ),
770                     },
771                 ]
772             "#]],
773         )
774     }
775
776     #[test]
777     fn dont_render_attrs() {
778         check(
779             r#"
780 struct S;
781 impl S {
782     #[inline]
783     fn the_method(&self) { }
784 }
785 fn foo(s: S) { s.$0 }
786 "#,
787             expect![[r#"
788                 [
789                     CompletionItem {
790                         label: "the_method()",
791                         source_range: 81..81,
792                         delete: 81..81,
793                         insert: "the_method()$0",
794                         kind: Method,
795                         lookup: "the_method",
796                         detail: "fn(&self)",
797                     },
798                 ]
799             "#]],
800         )
801     }
802
803     #[test]
804     fn no_call_parens_if_fn_ptr_needed() {
805         cov_mark::check!(no_call_parens_if_fn_ptr_needed);
806         check_edit(
807             "foo",
808             r#"
809 fn foo(foo: u8, bar: u8) {}
810 struct ManualVtable { f: fn(u8, u8) }
811
812 fn main() -> ManualVtable {
813     ManualVtable { f: f$0 }
814 }
815 "#,
816             r#"
817 fn foo(foo: u8, bar: u8) {}
818 struct ManualVtable { f: fn(u8, u8) }
819
820 fn main() -> ManualVtable {
821     ManualVtable { f: foo }
822 }
823 "#,
824         );
825     }
826
827     #[test]
828     fn no_parens_in_use_item() {
829         cov_mark::check!(no_parens_in_use_item);
830         check_edit(
831             "foo",
832             r#"
833 mod m { pub fn foo() {} }
834 use crate::m::f$0;
835 "#,
836             r#"
837 mod m { pub fn foo() {} }
838 use crate::m::foo;
839 "#,
840         );
841     }
842
843     #[test]
844     fn no_parens_in_call() {
845         check_edit(
846             "foo",
847             r#"
848 fn foo(x: i32) {}
849 fn main() { f$0(); }
850 "#,
851             r#"
852 fn foo(x: i32) {}
853 fn main() { foo(); }
854 "#,
855         );
856         check_edit(
857             "foo",
858             r#"
859 struct Foo;
860 impl Foo { fn foo(&self){} }
861 fn f(foo: &Foo) { foo.f$0(); }
862 "#,
863             r#"
864 struct Foo;
865 impl Foo { fn foo(&self){} }
866 fn f(foo: &Foo) { foo.foo(); }
867 "#,
868         );
869     }
870
871     #[test]
872     fn inserts_angle_brackets_for_generics() {
873         cov_mark::check!(inserts_angle_brackets_for_generics);
874         check_edit(
875             "Vec",
876             r#"
877 struct Vec<T> {}
878 fn foo(xs: Ve$0)
879 "#,
880             r#"
881 struct Vec<T> {}
882 fn foo(xs: Vec<$0>)
883 "#,
884         );
885         check_edit(
886             "Vec",
887             r#"
888 type Vec<T> = (T,);
889 fn foo(xs: Ve$0)
890 "#,
891             r#"
892 type Vec<T> = (T,);
893 fn foo(xs: Vec<$0>)
894 "#,
895         );
896         check_edit(
897             "Vec",
898             r#"
899 struct Vec<T = i128> {}
900 fn foo(xs: Ve$0)
901 "#,
902             r#"
903 struct Vec<T = i128> {}
904 fn foo(xs: Vec)
905 "#,
906         );
907         check_edit(
908             "Vec",
909             r#"
910 struct Vec<T> {}
911 fn foo(xs: Ve$0<i128>)
912 "#,
913             r#"
914 struct Vec<T> {}
915 fn foo(xs: Vec<i128>)
916 "#,
917         );
918     }
919
920     #[test]
921     fn active_param_relevance() {
922         check_relevance(
923             r#"
924 struct S { foo: i64, bar: u32, baz: u32 }
925 fn test(bar: u32) { }
926 fn foo(s: S) { test(s.$0) }
927 "#,
928             expect![[r#"
929                 fd bar [type+name]
930                 fd baz [type]
931                 fd foo []
932             "#]],
933         );
934     }
935
936     #[test]
937     fn record_field_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 foo(a: A) { B { bar: a.$0 }; }
943 "#,
944             expect![[r#"
945                 fd bar [type+name]
946                 fd baz [type]
947                 fd foo []
948             "#]],
949         )
950     }
951
952     #[test]
953     fn record_field_and_call_relevances() {
954         check_relevance(
955             r#"
956 struct A { foo: i64, bar: u32, baz: u32 }
957 struct B { x: (), y: f32, bar: u32 }
958 fn f(foo: i64) {  }
959 fn foo(a: A) { B { bar: f(a.$0) }; }
960 "#,
961             expect![[r#"
962                 fd foo [type+name]
963                 fd bar []
964                 fd baz []
965             "#]],
966         );
967         check_relevance(
968             r#"
969 struct A { foo: i64, bar: u32, baz: u32 }
970 struct B { x: (), y: f32, bar: u32 }
971 fn f(foo: i64) {  }
972 fn foo(a: A) { f(B { bar: a.$0 }); }
973 "#,
974             expect![[r#"
975                 fd bar [type+name]
976                 fd baz [type]
977                 fd foo []
978             "#]],
979         );
980     }
981
982     #[test]
983     fn prioritize_exact_ref_match() {
984         check_relevance(
985             r#"
986 struct WorldSnapshot { _f: () };
987 fn go(world: &WorldSnapshot) { go(w$0) }
988 "#,
989             expect![[r#"
990                 lc world [type+name+local]
991                 st WorldSnapshot []
992                 fn go(…) []
993             "#]],
994         );
995     }
996
997     #[test]
998     fn too_many_arguments() {
999         cov_mark::check!(too_many_arguments);
1000         check_relevance(
1001             r#"
1002 struct Foo;
1003 fn f(foo: &Foo) { f(foo, w$0) }
1004 "#,
1005             expect![[r#"
1006                 lc foo [local]
1007                 st Foo []
1008                 fn f(…) []
1009             "#]],
1010         );
1011     }
1012
1013     #[test]
1014     fn score_fn_type_and_name_match() {
1015         check_relevance(
1016             r#"
1017 struct A { bar: u8 }
1018 fn baz() -> u8 { 0 }
1019 fn bar() -> u8 { 0 }
1020 fn f() { A { bar: b$0 }; }
1021 "#,
1022             expect![[r#"
1023                 fn bar() [type+name]
1024                 fn baz() [type]
1025                 st A []
1026                 fn f() []
1027             "#]],
1028         );
1029     }
1030
1031     #[test]
1032     fn score_method_type_and_name_match() {
1033         check_relevance(
1034             r#"
1035 fn baz(aaa: u32){}
1036 struct Foo;
1037 impl Foo {
1038 fn aaa(&self) -> u32 { 0 }
1039 fn bbb(&self) -> u32 { 0 }
1040 fn ccc(&self) -> u64 { 0 }
1041 }
1042 fn f() {
1043     baz(Foo.$0
1044 }
1045 "#,
1046             expect![[r#"
1047                 me aaa() [type+name]
1048                 me bbb() [type]
1049                 me ccc() []
1050             "#]],
1051         );
1052     }
1053
1054     #[test]
1055     fn score_method_name_match_only() {
1056         check_relevance(
1057             r#"
1058 fn baz(aaa: u32){}
1059 struct Foo;
1060 impl Foo {
1061 fn aaa(&self) -> u64 { 0 }
1062 }
1063 fn f() {
1064     baz(Foo.$0
1065 }
1066 "#,
1067             expect![[r#"
1068                 me aaa() [name]
1069             "#]],
1070         );
1071     }
1072
1073     #[test]
1074     fn suggest_ref_mut() {
1075         cov_mark::check!(suggest_ref);
1076         check_relevance(
1077             r#"
1078 struct S;
1079 fn foo(s: &mut S) {}
1080 fn main() {
1081     let mut s = S;
1082     foo($0);
1083 }
1084             "#,
1085             expect![[r#"
1086                 lc s [name+local]
1087                 lc &mut s [type+name+local]
1088                 st S []
1089                 fn main() []
1090                 fn foo(…) []
1091             "#]],
1092         );
1093         check_relevance(
1094             r#"
1095 struct S;
1096 fn foo(s: &mut S) {}
1097 fn main() {
1098     let mut s = S;
1099     foo(&mut $0);
1100 }
1101             "#,
1102             expect![[r#"
1103                 lc s [type+name+local]
1104                 st S []
1105                 fn main() []
1106                 fn foo(…) []
1107             "#]],
1108         );
1109     }
1110
1111     #[test]
1112     fn suggest_deref() {
1113         check_relevance(
1114             r#"
1115 //- minicore: deref
1116 struct S;
1117 struct T(S);
1118
1119 impl core::ops::Deref for T {
1120     type Target = S;
1121
1122     fn deref(&self) -> &Self::Target {
1123         &self.0
1124     }
1125 }
1126
1127 fn foo(s: &S) {}
1128
1129 fn main() {
1130     let t = T(S);
1131     let m = 123;
1132
1133     foo($0);
1134 }
1135             "#,
1136             expect![[r#"
1137                 lc m [local]
1138                 lc t [local]
1139                 lc &t [type+local]
1140                 st T []
1141                 st S []
1142                 fn main() []
1143                 fn foo(…) []
1144                 md core []
1145                 tt Sized []
1146             "#]],
1147         )
1148     }
1149
1150     #[test]
1151     fn suggest_deref_mut() {
1152         check_relevance(
1153             r#"
1154 //- minicore: deref_mut
1155 struct S;
1156 struct T(S);
1157
1158 impl core::ops::Deref for T {
1159     type Target = S;
1160
1161     fn deref(&self) -> &Self::Target {
1162         &self.0
1163     }
1164 }
1165
1166 impl core::ops::DerefMut for T {
1167     fn deref_mut(&mut self) -> &mut Self::Target {
1168         &mut self.0
1169     }
1170 }
1171
1172 fn foo(s: &mut S) {}
1173
1174 fn main() {
1175     let t = T(S);
1176     let m = 123;
1177
1178     foo($0);
1179 }
1180             "#,
1181             expect![[r#"
1182                 lc m [local]
1183                 lc t [local]
1184                 lc &mut t [type+local]
1185                 st T []
1186                 st S []
1187                 fn main() []
1188                 fn foo(…) []
1189                 md core []
1190                 tt Sized []
1191             "#]],
1192         )
1193     }
1194
1195     #[test]
1196     fn locals() {
1197         check_relevance(
1198             r#"
1199 fn foo(bar: u32) {
1200     let baz = 0;
1201
1202     f$0
1203 }
1204 "#,
1205             expect![[r#"
1206                 lc baz [local]
1207                 lc bar [local]
1208                 fn foo(…) []
1209             "#]],
1210         );
1211     }
1212
1213     #[test]
1214     fn enum_owned() {
1215         check_relevance(
1216             r#"
1217 enum Foo { A, B }
1218 fn foo() {
1219     bar($0);
1220 }
1221 fn bar(t: Foo) {}
1222 "#,
1223             expect![[r#"
1224                 ev Foo::A [type]
1225                 ev Foo::B [type]
1226                 en Foo []
1227                 fn bar(…) []
1228                 fn foo() []
1229             "#]],
1230         );
1231     }
1232
1233     #[test]
1234     fn enum_ref() {
1235         check_relevance(
1236             r#"
1237 enum Foo { A, B }
1238 fn foo() {
1239     bar($0);
1240 }
1241 fn bar(t: &Foo) {}
1242 "#,
1243             expect![[r#"
1244                 ev Foo::A []
1245                 ev &Foo::A [type]
1246                 ev Foo::B []
1247                 ev &Foo::B [type]
1248                 en Foo []
1249                 fn bar(…) []
1250                 fn foo() []
1251             "#]],
1252         );
1253     }
1254
1255     #[test]
1256     fn suggest_deref_fn_ret() {
1257         check_relevance(
1258             r#"
1259 //- minicore: deref
1260 struct S;
1261 struct T(S);
1262
1263 impl core::ops::Deref for T {
1264     type Target = S;
1265
1266     fn deref(&self) -> &Self::Target {
1267         &self.0
1268     }
1269 }
1270
1271 fn foo(s: &S) {}
1272 fn bar() -> T {}
1273
1274 fn main() {
1275     foo($0);
1276 }
1277 "#,
1278             expect![[r#"
1279                 st T []
1280                 st S []
1281                 fn main() []
1282                 fn bar() []
1283                 fn &bar() [type]
1284                 fn foo(…) []
1285                 md core []
1286                 tt Sized []
1287             "#]],
1288         )
1289     }
1290
1291     #[test]
1292     fn struct_field_method_ref() {
1293         check(
1294             r#"
1295 struct Foo { bar: u32 }
1296 impl Foo { fn baz(&self) -> u32 { 0 } }
1297
1298 fn foo(f: Foo) { let _: &u32 = f.b$0 }
1299 "#,
1300             // FIXME
1301             // Ideally we'd also suggest &f.bar and &f.baz() as exact
1302             // type matches. See #8058.
1303             expect![[r#"
1304                 [
1305                     CompletionItem {
1306                         label: "bar",
1307                         source_range: 98..99,
1308                         delete: 98..99,
1309                         insert: "bar",
1310                         kind: SymbolKind(
1311                             Field,
1312                         ),
1313                         detail: "u32",
1314                     },
1315                     CompletionItem {
1316                         label: "baz()",
1317                         source_range: 98..99,
1318                         delete: 98..99,
1319                         insert: "baz()$0",
1320                         kind: Method,
1321                         lookup: "baz",
1322                         detail: "fn(&self) -> u32",
1323                     },
1324                 ]
1325             "#]],
1326         );
1327     }
1328
1329     #[test]
1330     fn generic_enum() {
1331         check_relevance(
1332             r#"
1333 enum Foo<T> { A(T), B }
1334 // bar() should not be an exact type match
1335 // because the generic parameters are different
1336 fn bar() -> Foo<u8> { Foo::B }
1337 // FIXME baz() should be an exact type match
1338 // because the types could unify, but it currently
1339 // is not. This is due to the T here being
1340 // TyKind::Placeholder rather than TyKind::Missing.
1341 fn baz<T>() -> Foo<T> { Foo::B }
1342 fn foo() {
1343     let foo: Foo<u32> = Foo::B;
1344     let _: Foo<u32> = f$0;
1345 }
1346 "#,
1347             expect![[r#"
1348                 lc foo [type+local]
1349                 ev Foo::A(…) [type_could_unify]
1350                 ev Foo::B [type_could_unify]
1351                 fn foo() []
1352                 en Foo []
1353                 fn baz() []
1354                 fn bar() []
1355             "#]],
1356         );
1357     }
1358
1359     #[test]
1360     fn postfix_completion_relevance() {
1361         check_relevance_for_kinds(
1362             &[CompletionKind::Postfix, CompletionKind::Magic],
1363             r#"
1364 mod ops {
1365     pub trait Not {
1366         type Output;
1367         fn not(self) -> Self::Output;
1368     }
1369
1370     impl Not for bool {
1371         type Output = bool;
1372         fn not(self) -> bool { if self { false } else { true }}
1373     }
1374 }
1375
1376 fn main() {
1377     let _: bool = (9 > 2).not$0;
1378 }
1379 "#,
1380             expect![[r#"
1381                 sn not [snippet]
1382                 me not() (use ops::Not) [type_could_unify]
1383                 sn if []
1384                 sn while []
1385                 sn ref []
1386                 sn refm []
1387                 sn match []
1388                 sn box []
1389                 sn ok []
1390                 sn err []
1391                 sn some []
1392                 sn dbg []
1393                 sn dbgr []
1394                 sn call []
1395             "#]],
1396         );
1397     }
1398 }