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