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