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