aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion/presentation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion/presentation.rs')
-rw-r--r--crates/ra_ide/src/completion/presentation.rs1675
1 files changed, 693 insertions, 982 deletions
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 4fdc2f0bb..9a94ff476 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -1,4 +1,5 @@
1//! This modules takes care of rendering various definitions as completion items. 1//! This modules takes care of rendering various definitions as completion items.
2//! It also handles scoring (sorting) completions.
2 3
3use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type}; 4use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type};
4use ra_syntax::ast::NameOwner; 5use ra_syntax::ast::NameOwner;
@@ -10,7 +11,7 @@ use crate::{
10 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind, 11 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
11 CompletionKind, Completions, 12 CompletionKind, Completions,
12 }, 13 },
13 display::{const_label, macro_label, type_label, FunctionSignature}, 14 display::{const_label, function_declaration, macro_label, type_label},
14 CompletionScore, RootDatabase, 15 CompletionScore, RootDatabase,
15}; 16};
16 17
@@ -78,11 +79,10 @@ impl Completions {
78 return self.add_macro(ctx, Some(local_name), *mac); 79 return self.add_macro(ctx, Some(local_name), *mac);
79 } 80 }
80 ScopeDef::Unknown => { 81 ScopeDef::Unknown => {
81 return self.add(CompletionItem::new( 82 return self.add(
82 CompletionKind::Reference, 83 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), local_name)
83 ctx.source_range(), 84 .kind(CompletionItemKind::UnresolvedReference),
84 local_name, 85 );
85 ));
86 } 86 }
87 }; 87 };
88 88
@@ -173,6 +173,7 @@ impl Completions {
173 builder 173 builder
174 .insert_snippet(cap, format!("{}!{}$0{}", name, bra, ket)) 174 .insert_snippet(cap, format!("{}!{}$0{}", name, bra, ket))
175 .label(format!("{}!{}…{}", name, bra, ket)) 175 .label(format!("{}!{}…{}", name, bra, ket))
176 .lookup_by(format!("{}!", name))
176 } 177 }
177 None if needs_bang => builder.insert_text(format!("{}!", name)), 178 None if needs_bang => builder.insert_text(format!("{}!", name)),
178 _ => { 179 _ => {
@@ -194,7 +195,6 @@ impl Completions {
194 195
195 let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); 196 let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string());
196 let ast_node = func.source(ctx.db).value; 197 let ast_node = func.source(ctx.db).value;
197 let function_signature = FunctionSignature::from(&ast_node);
198 198
199 let mut builder = 199 let mut builder =
200 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) 200 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone())
@@ -205,13 +205,14 @@ impl Completions {
205 }) 205 })
206 .set_documentation(func.docs(ctx.db)) 206 .set_documentation(func.docs(ctx.db))
207 .set_deprecated(is_deprecated(func, ctx.db)) 207 .set_deprecated(is_deprecated(func, ctx.db))
208 .detail(function_signature.to_string()); 208 .detail(function_declaration(&ast_node));
209 209
210 let params = function_signature 210 let params = ast_node
211 .parameter_names 211 .param_list()
212 .iter() 212 .into_iter()
213 .skip(if function_signature.has_self_param { 1 } else { 0 }) 213 .flat_map(|it| it.params())
214 .map(|name| name.trim_start_matches('_').into()) 214 .flat_map(|it| it.pat())
215 .map(|pat| pat.to_string().trim_start_matches('_').into())
215 .collect(); 216 .collect();
216 217
217 builder = builder.add_call_parens(ctx, name, Params::Named(params)); 218 builder = builder.add_call_parens(ctx, name, Params::Named(params));
@@ -314,6 +315,7 @@ impl Completions {
314 } 315 }
315 316
316 if variant_kind == StructKind::Tuple { 317 if variant_kind == StructKind::Tuple {
318 mark::hit!(inserts_parens_for_tuple_enums);
317 let params = Params::Anonymous(variant.fields(ctx.db).len()); 319 let params = Params::Anonymous(variant.fields(ctx.db).len());
318 res = res.add_call_parens(ctx, qualified_name, params) 320 res = res.add_call_parens(ctx, qualified_name, params)
319 } 321 }
@@ -327,17 +329,12 @@ pub(crate) fn compute_score(
327 ty: &Type, 329 ty: &Type,
328 name: &str, 330 name: &str,
329) -> Option<CompletionScore> { 331) -> Option<CompletionScore> {
330 // FIXME: this should not fall back to string equality.
331 let ty = &ty.display(ctx.db).to_string();
332 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { 332 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
333 mark::hit!(test_struct_field_completion_in_record_lit); 333 mark::hit!(record_field_type_match);
334 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; 334 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?;
335 ( 335 (struct_field.name(ctx.db).to_string(), struct_field.signature_ty(ctx.db))
336 struct_field.name(ctx.db).to_string(),
337 struct_field.signature_ty(ctx.db).display(ctx.db).to_string(),
338 )
339 } else if let Some(active_parameter) = &ctx.active_parameter { 336 } else if let Some(active_parameter) = &ctx.active_parameter {
340 mark::hit!(test_struct_field_completion_in_func_call); 337 mark::hit!(active_param_type_match);
341 (active_parameter.name.clone(), active_parameter.ty.clone()) 338 (active_parameter.name.clone(), active_parameter.ty.clone())
342 } else { 339 } else {
343 return None; 340 return None;
@@ -382,13 +379,22 @@ impl Builder {
382 if !ctx.config.add_call_parenthesis { 379 if !ctx.config.add_call_parenthesis {
383 return self; 380 return self;
384 } 381 }
385 if ctx.use_item_syntax.is_some() || ctx.is_call { 382 if ctx.use_item_syntax.is_some() {
383 mark::hit!(no_parens_in_use_item);
384 return self;
385 }
386 if ctx.is_pattern_call {
387 mark::hit!(dont_duplicate_pattern_parens);
388 return self;
389 }
390 if ctx.is_call {
386 return self; 391 return self;
387 } 392 }
388 393
389 // Don't add parentheses if the expected type is some function reference. 394 // Don't add parentheses if the expected type is some function reference.
390 if let Some(ty) = &ctx.expected_type { 395 if let Some(ty) = &ctx.expected_type {
391 if ty.is_fn() { 396 if ty.is_fn() {
397 mark::hit!(no_call_parens_if_fn_ptr_needed);
392 return self; 398 return self;
393 } 399 }
394 } 400 }
@@ -413,7 +419,10 @@ impl Builder {
413 .sep_by(", "); 419 .sep_by(", ");
414 format!("{}({})$0", name, function_params_snippet) 420 format!("{}({})$0", name, function_params_snippet)
415 } 421 }
416 _ => format!("{}($0)", name), 422 _ => {
423 mark::hit!(suppress_arg_snippets);
424 format!("{}($0)", name)
425 }
417 }; 426 };
418 427
419 (snippet, format!("{}(…)", name)) 428 (snippet, format!("{}(…)", name))
@@ -456,1064 +465,766 @@ fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static s
456 465
457#[cfg(test)] 466#[cfg(test)]
458mod tests { 467mod tests {
459 use insta::assert_debug_snapshot; 468 use std::cmp::Reverse;
469
470 use expect::{expect, Expect};
460 use test_utils::mark; 471 use test_utils::mark;
461 472
462 use crate::completion::{ 473 use crate::{
463 test_utils::{do_completion, do_completion_with_options}, 474 completion::{
464 CompletionConfig, CompletionItem, CompletionKind, 475 test_utils::{
476 check_edit, check_edit_with_config, do_completion, get_all_completion_items,
477 },
478 CompletionConfig, CompletionKind,
479 },
480 CompletionScore,
465 }; 481 };
466 482
467 fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> { 483 fn check(ra_fixture: &str, expect: Expect) {
468 do_completion(ra_fixture, CompletionKind::Reference) 484 let actual = do_completion(ra_fixture, CompletionKind::Reference);
485 expect.assert_debug_eq(&actual);
469 } 486 }
470 487
471 fn do_reference_completion_with_options( 488 fn check_scores(ra_fixture: &str, expect: Expect) {
472 ra_fixture: &str, 489 fn display_score(score: Option<CompletionScore>) -> &'static str {
473 options: CompletionConfig, 490 match score {
474 ) -> Vec<CompletionItem> { 491 Some(CompletionScore::TypeMatch) => "[type]",
475 do_completion_with_options(ra_fixture, CompletionKind::Reference, &options) 492 Some(CompletionScore::TypeAndNameMatch) => "[type+name]",
493 None => "[]".into(),
494 }
495 }
496
497 let mut completions = get_all_completion_items(CompletionConfig::default(), ra_fixture);
498 completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string()));
499 let actual = completions
500 .into_iter()
501 .filter(|it| it.completion_kind == CompletionKind::Reference)
502 .map(|it| {
503 let tag = it.kind().unwrap().tag();
504 let score = display_score(it.score());
505 format!("{} {} {}\n", tag, it.label(), score)
506 })
507 .collect::<String>();
508 expect.assert_eq(&actual);
476 } 509 }
477 510
478 #[test] 511 #[test]
479 fn enum_detail_includes_names_for_record() { 512 fn enum_detail_includes_record_fields() {
480 assert_debug_snapshot!( 513 check(
481 do_reference_completion(
482 r#" 514 r#"
483 enum Foo { 515enum Foo { Foo { x: i32, y: i32 } }
484 Foo {x: i32, y: i32} 516
485 } 517fn main() { Foo::Fo<|> }
486 518"#,
487 fn main() { Foo::Fo<|> } 519 expect![[r#"
488 "#, 520 [
489 ), 521 CompletionItem {
490 @r###" 522 label: "Foo",
491 [ 523 source_range: 54..56,
492 CompletionItem { 524 delete: 54..56,
493 label: "Foo", 525 insert: "Foo",
494 source_range: 56..58, 526 kind: EnumVariant,
495 delete: 56..58, 527 detail: "{ x: i32, y: i32 }",
496 insert: "Foo", 528 },
497 kind: EnumVariant, 529 ]
498 detail: "{ x: i32, y: i32 }", 530 "#]],
499 },
500 ]
501 "###
502 ); 531 );
503 } 532 }
504 533
505 #[test] 534 #[test]
506 fn enum_detail_doesnt_include_names_for_tuple() { 535 fn enum_detail_doesnt_include_tuple_fields() {
507 assert_debug_snapshot!( 536 check(
508 do_reference_completion(
509 r#" 537 r#"
510 enum Foo { 538enum Foo { Foo (i32, i32) }
511 Foo (i32, i32) 539
512 } 540fn main() { Foo::Fo<|> }
513 541"#,
514 fn main() { Foo::Fo<|> } 542 expect![[r#"
515 "#, 543 [
516 ), 544 CompletionItem {
517 @r###" 545 label: "Foo(…)",
518 [ 546 source_range: 46..48,
519 CompletionItem { 547 delete: 46..48,
520 label: "Foo(…)", 548 insert: "Foo($0)",
521 source_range: 50..52, 549 kind: EnumVariant,
522 delete: 50..52, 550 lookup: "Foo",
523 insert: "Foo($0)", 551 detail: "(i32, i32)",
524 kind: EnumVariant, 552 trigger_call_info: true,
525 lookup: "Foo", 553 },
526 detail: "(i32, i32)", 554 ]
527 trigger_call_info: true, 555 "#]],
528 },
529 ]
530 "###
531 ); 556 );
532 } 557 }
533 558
534 #[test] 559 #[test]
535 fn enum_detail_just_parentheses_for_unit() { 560 fn enum_detail_just_parentheses_for_unit() {
536 assert_debug_snapshot!( 561 check(
537 do_reference_completion(
538 r#" 562 r#"
539 enum Foo { 563enum Foo { Foo }
540 Foo 564
541 } 565fn main() { Foo::Fo<|> }
542 566"#,
543 fn main() { Foo::Fo<|> } 567 expect![[r#"
544 "#, 568 [
545 ), 569 CompletionItem {
546 @r###" 570 label: "Foo",
547 [ 571 source_range: 35..37,
548 CompletionItem { 572 delete: 35..37,
549 label: "Foo", 573 insert: "Foo",
550 source_range: 39..41, 574 kind: EnumVariant,
551 delete: 39..41, 575 detail: "()",
552 insert: "Foo", 576 },
553 kind: EnumVariant, 577 ]
554 detail: "()", 578 "#]],
555 },
556 ]
557 "###
558 ); 579 );
559 } 580 }
560 581
561 #[test] 582 #[test]
562 fn sets_deprecated_flag_in_completion_items() { 583 fn sets_deprecated_flag_in_completion_items() {
563 assert_debug_snapshot!( 584 check(
564 do_reference_completion( 585 r#"
565 r#" 586#[deprecated]
566 #[deprecated] 587fn something_deprecated() {}
567 fn something_deprecated() {} 588#[deprecated(since = "1.0.0")]
568 589fn something_else_deprecated() {}
569 #[deprecated(since = "1.0.0")] 590
570 fn something_else_deprecated() {} 591fn main() { som<|> }
571 592"#,
572 fn main() { som<|> } 593 expect![[r#"
573 "#, 594 [
574 ), 595 CompletionItem {
575 @r###" 596 label: "main()",
576 [ 597 source_range: 121..124,
577 CompletionItem { 598 delete: 121..124,
578 label: "main()", 599 insert: "main()$0",
579 source_range: 122..125, 600 kind: Function,
580 delete: 122..125, 601 lookup: "main",
581 insert: "main()$0", 602 detail: "fn main()",
582 kind: Function, 603 },
583 lookup: "main", 604 CompletionItem {
584 detail: "fn main()", 605 label: "something_deprecated()",
585 }, 606 source_range: 121..124,
586 CompletionItem { 607 delete: 121..124,
587 label: "something_deprecated()", 608 insert: "something_deprecated()$0",
588 source_range: 122..125, 609 kind: Function,
589 delete: 122..125, 610 lookup: "something_deprecated",
590 insert: "something_deprecated()$0", 611 detail: "fn something_deprecated()",
591 kind: Function, 612 deprecated: true,
592 lookup: "something_deprecated", 613 },
593 detail: "fn something_deprecated()", 614 CompletionItem {
594 deprecated: true, 615 label: "something_else_deprecated()",
595 }, 616 source_range: 121..124,
596 CompletionItem { 617 delete: 121..124,
597 label: "something_else_deprecated()", 618 insert: "something_else_deprecated()$0",
598 source_range: 122..125, 619 kind: Function,
599 delete: 122..125, 620 lookup: "something_else_deprecated",
600 insert: "something_else_deprecated()$0", 621 detail: "fn something_else_deprecated()",
601 kind: Function, 622 deprecated: true,
602 lookup: "something_else_deprecated", 623 },
603 detail: "fn something_else_deprecated()", 624 ]
604 deprecated: true, 625 "#]],
605 }, 626 );
606 ] 627
607 "### 628 check(
629 r#"
630struct A { #[deprecated] the_field: u32 }
631fn foo() { A { the<|> } }
632"#,
633 expect![[r#"
634 [
635 CompletionItem {
636 label: "the_field",
637 source_range: 57..60,
638 delete: 57..60,
639 insert: "the_field",
640 kind: Field,
641 detail: "u32",
642 deprecated: true,
643 },
644 ]
645 "#]],
646 );
647 }
648
649 #[test]
650 fn renders_docs() {
651 check(
652 r#"
653struct S {
654 /// Field docs
655 foo:
656}
657impl S {
658 /// Method docs
659 fn bar(self) { self.<|> }
660}"#,
661 expect![[r#"
662 [
663 CompletionItem {
664 label: "bar()",
665 source_range: 94..94,
666 delete: 94..94,
667 insert: "bar()$0",
668 kind: Method,
669 lookup: "bar",
670 detail: "fn bar(self)",
671 documentation: Documentation(
672 "Method docs",
673 ),
674 },
675 CompletionItem {
676 label: "foo",
677 source_range: 94..94,
678 delete: 94..94,
679 insert: "foo",
680 kind: Field,
681 detail: "{unknown}",
682 documentation: Documentation(
683 "Field docs",
684 ),
685 },
686 ]
687 "#]],
608 ); 688 );
689
690 check(
691 r#"
692use self::my<|>;
693
694/// mod docs
695mod my { }
696
697/// enum docs
698enum E {
699 /// variant docs
700 V
701}
702use self::E::*;
703"#,
704 expect![[r#"
705 [
706 CompletionItem {
707 label: "E",
708 source_range: 10..12,
709 delete: 10..12,
710 insert: "E",
711 kind: Enum,
712 documentation: Documentation(
713 "enum docs",
714 ),
715 },
716 CompletionItem {
717 label: "V",
718 source_range: 10..12,
719 delete: 10..12,
720 insert: "V",
721 kind: EnumVariant,
722 detail: "()",
723 documentation: Documentation(
724 "variant docs",
725 ),
726 },
727 CompletionItem {
728 label: "my",
729 source_range: 10..12,
730 delete: 10..12,
731 insert: "my",
732 kind: Module,
733 documentation: Documentation(
734 "mod docs",
735 ),
736 },
737 ]
738 "#]],
739 )
740 }
741
742 #[test]
743 fn dont_render_attrs() {
744 check(
745 r#"
746struct S;
747impl S {
748 #[inline]
749 fn the_method(&self) { }
750}
751fn foo(s: S) { s.<|> }
752"#,
753 expect![[r#"
754 [
755 CompletionItem {
756 label: "the_method()",
757 source_range: 81..81,
758 delete: 81..81,
759 insert: "the_method()$0",
760 kind: Method,
761 lookup: "the_method",
762 detail: "fn the_method(&self)",
763 },
764 ]
765 "#]],
766 )
609 } 767 }
610 768
611 #[test] 769 #[test]
612 fn inserts_parens_for_function_calls() { 770 fn inserts_parens_for_function_calls() {
613 mark::check!(inserts_parens_for_function_calls); 771 mark::check!(inserts_parens_for_function_calls);
614 assert_debug_snapshot!( 772 check_edit(
615 do_reference_completion( 773 "no_args",
616 r" 774 r#"
617 fn no_args() {} 775fn no_args() {}
618 fn main() { no_<|> } 776fn main() { no_<|> }
619 " 777"#,
620 ), 778 r#"
621 @r###" 779fn no_args() {}
622 [ 780fn main() { no_args()$0 }
623 CompletionItem { 781"#,
624 label: "main()",
625 source_range: 28..31,
626 delete: 28..31,
627 insert: "main()$0",
628 kind: Function,
629 lookup: "main",
630 detail: "fn main()",
631 },
632 CompletionItem {
633 label: "no_args()",
634 source_range: 28..31,
635 delete: 28..31,
636 insert: "no_args()$0",
637 kind: Function,
638 lookup: "no_args",
639 detail: "fn no_args()",
640 },
641 ]
642 "###
643 );
644 assert_debug_snapshot!(
645 do_reference_completion(
646 r"
647 fn with_args(x: i32, y: String) {}
648 fn main() { with_<|> }
649 "
650 ),
651 @r###"
652 [
653 CompletionItem {
654 label: "main()",
655 source_range: 47..52,
656 delete: 47..52,
657 insert: "main()$0",
658 kind: Function,
659 lookup: "main",
660 detail: "fn main()",
661 },
662 CompletionItem {
663 label: "with_args(…)",
664 source_range: 47..52,
665 delete: 47..52,
666 insert: "with_args(${1:x}, ${2:y})$0",
667 kind: Function,
668 lookup: "with_args",
669 detail: "fn with_args(x: i32, y: String)",
670 trigger_call_info: true,
671 },
672 ]
673 "###
674 ); 782 );
675 assert_debug_snapshot!( 783
676 do_reference_completion( 784 check_edit(
677 r" 785 "with_args",
678 fn with_ignored_args(_foo: i32, ___bar: bool, ho_ge_: String) {} 786 r#"
679 fn main() { with_<|> } 787fn with_args(x: i32, y: String) {}
680 " 788fn main() { with_<|> }
681 ), 789"#,
682 @r###" 790 r#"
683 [ 791fn with_args(x: i32, y: String) {}
684 CompletionItem { 792fn main() { with_args(${1:x}, ${2:y})$0 }
685 label: "main()", 793"#,
686 source_range: 77..82,
687 delete: 77..82,
688 insert: "main()$0",
689 kind: Function,
690 lookup: "main",
691 detail: "fn main()",
692 },
693 CompletionItem {
694 label: "with_ignored_args(…)",
695 source_range: 77..82,
696 delete: 77..82,
697 insert: "with_ignored_args(${1:foo}, ${2:bar}, ${3:ho_ge_})$0",
698 kind: Function,
699 lookup: "with_ignored_args",
700 detail: "fn with_ignored_args(_foo: i32, ___bar: bool, ho_ge_: String)",
701 trigger_call_info: true,
702 },
703 ]
704 "###
705 ); 794 );
706 assert_debug_snapshot!( 795
707 do_reference_completion( 796 check_edit(
708 r" 797 "foo",
709 struct S {} 798 r#"
710 impl S { 799struct S;
711 fn foo(&self) {} 800impl S {
712 } 801 fn foo(&self) {}
713 fn bar(s: &S) { 802}
714 s.f<|> 803fn bar(s: &S) { s.f<|> }
715 } 804"#,
716 " 805 r#"
717 ), 806struct S;
718 @r###" 807impl S {
719 [ 808 fn foo(&self) {}
720 CompletionItem { 809}
721 label: "foo()", 810fn bar(s: &S) { s.foo()$0 }
722 source_range: 66..67, 811"#,
723 delete: 66..67,
724 insert: "foo()$0",
725 kind: Method,
726 lookup: "foo",
727 detail: "fn foo(&self)",
728 },
729 ]
730 "###
731 ); 812 );
732 assert_debug_snapshot!( 813
733 do_reference_completion( 814 check_edit(
734 r" 815 "foo",
735 struct S {} 816 r#"
736 impl S { 817struct S {}
737 fn foo_ignored_args(&self, _a: bool, b: i32) {} 818impl S {
738 } 819 fn foo(&self, x: i32) {}
739 fn bar(s: &S) { 820}
740 s.f<|> 821fn bar(s: &S) {
741 } 822 s.f<|>
742 " 823}
743 ), 824"#,
744 @r###" 825 r#"
745 [ 826struct S {}
746 CompletionItem { 827impl S {
747 label: "foo_ignored_args(…)", 828 fn foo(&self, x: i32) {}
748 source_range: 97..98, 829}
749 delete: 97..98, 830fn bar(s: &S) {
750 insert: "foo_ignored_args(${1:a}, ${2:b})$0", 831 s.foo(${1:x})$0
751 kind: Method, 832}
752 lookup: "foo_ignored_args", 833"#,
753 detail: "fn foo_ignored_args(&self, _a: bool, b: i32)",
754 trigger_call_info: true,
755 },
756 ]
757 "###
758 ); 834 );
759 } 835 }
760 836
761 #[test] 837 #[test]
762 fn inserts_parens_for_tuple_enums() { 838 fn suppress_arg_snippets() {
763 assert_debug_snapshot!( 839 mark::check!(suppress_arg_snippets);
764 do_reference_completion( 840 check_edit_with_config(
765 r" 841 CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() },
766 enum Option<T> { Some(T), None } 842 "with_args",
767 use Option::*; 843 r#"
768 fn main() -> Option<i32> { 844fn with_args(x: i32, y: String) {}
769 Som<|> 845fn main() { with_<|> }
770 } 846"#,
771 " 847 r#"
772 ), 848fn with_args(x: i32, y: String) {}
773 @r###" 849fn main() { with_args($0) }
774 [ 850"#,
775 CompletionItem {
776 label: "None",
777 source_range: 79..82,
778 delete: 79..82,
779 insert: "None",
780 kind: EnumVariant,
781 detail: "()",
782 },
783 CompletionItem {
784 label: "Option",
785 source_range: 79..82,
786 delete: 79..82,
787 insert: "Option",
788 kind: Enum,
789 },
790 CompletionItem {
791 label: "Some(…)",
792 source_range: 79..82,
793 delete: 79..82,
794 insert: "Some($0)",
795 kind: EnumVariant,
796 lookup: "Some",
797 detail: "(T)",
798 trigger_call_info: true,
799 },
800 CompletionItem {
801 label: "main()",
802 source_range: 79..82,
803 delete: 79..82,
804 insert: "main()$0",
805 kind: Function,
806 lookup: "main",
807 detail: "fn main() -> Option<i32>",
808 },
809 ]
810 "###
811 );
812 assert_debug_snapshot!(
813 do_reference_completion(
814 r"
815 enum Option<T> { Some(T), None }
816 use Option::*;
817 fn main(value: Option<i32>) {
818 match value {
819 Som<|>
820 }
821 }
822 "
823 ),
824 @r###"
825 [
826 CompletionItem {
827 label: "None",
828 source_range: 104..107,
829 delete: 104..107,
830 insert: "None",
831 kind: EnumVariant,
832 detail: "()",
833 },
834 CompletionItem {
835 label: "Option",
836 source_range: 104..107,
837 delete: 104..107,
838 insert: "Option",
839 kind: Enum,
840 },
841 CompletionItem {
842 label: "Some(…)",
843 source_range: 104..107,
844 delete: 104..107,
845 insert: "Some($0)",
846 kind: EnumVariant,
847 lookup: "Some",
848 detail: "(T)",
849 trigger_call_info: true,
850 },
851 ]
852 "###
853 ); 851 );
854 } 852 }
855 853
856 #[test] 854 #[test]
857 fn no_call_parens_if_fn_ptr_needed() { 855 fn strips_underscores_from_args() {
858 assert_debug_snapshot!( 856 check_edit(
859 do_reference_completion( 857 "foo",
860 r" 858 r#"
861 fn somefn(with: u8, a: u8, lot: u8, of: u8, args: u8) {} 859fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {}
862 860fn main() { f<|> }
863 struct ManualVtable { 861"#,
864 method: fn(u8, u8, u8, u8, u8), 862 r#"
865 } 863fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {}
864fn main() { foo(${1:foo}, ${2:bar}, ${3:ho_ge_})$0 }
865"#,
866 );
867 }
866 868
867 fn main() -> ManualVtable { 869 #[test]
868 ManualVtable { 870 fn inserts_parens_for_tuple_enums() {
869 method: some<|> 871 mark::check!(inserts_parens_for_tuple_enums);
870 } 872 check_edit(
871 } 873 "Some",
872 " 874 r#"
873 ), 875enum Option<T> { Some(T), None }
874 @r###" 876use Option::*;
875 [ 877fn main() -> Option<i32> {
876 CompletionItem { 878 Som<|>
877 label: "ManualVtable", 879}
878 source_range: 182..186, 880"#,
879 delete: 182..186, 881 r#"
880 insert: "ManualVtable", 882enum Option<T> { Some(T), None }
881 kind: Struct, 883use Option::*;
882 }, 884fn main() -> Option<i32> {
883 CompletionItem { 885 Some($0)
884 label: "main", 886}
885 source_range: 182..186, 887"#,
886 delete: 182..186, 888 );
887 insert: "main", 889 check_edit(
888 kind: Function, 890 "Some",
889 detail: "fn main() -> ManualVtable", 891 r#"
890 }, 892enum Option<T> { Some(T), None }
891 CompletionItem { 893use Option::*;
892 label: "somefn", 894fn main(value: Option<i32>) {
893 source_range: 182..186, 895 match value {
894 delete: 182..186, 896 Som<|>
895 insert: "somefn", 897 }
896 kind: Function, 898}
897 detail: "fn somefn(with: u8, a: u8, lot: u8, of: u8, args: u8)", 899"#,
898 }, 900 r#"
899 ] 901enum Option<T> { Some(T), None }
900 "### 902use Option::*;
903fn main(value: Option<i32>) {
904 match value {
905 Some($0)
906 }
907}
908"#,
901 ); 909 );
902 } 910 }
903 911
904 #[test] 912 #[test]
905 fn arg_snippets_for_method_call() { 913 fn dont_duplicate_pattern_parens() {
906 assert_debug_snapshot!( 914 mark::check!(dont_duplicate_pattern_parens);
907 do_reference_completion( 915 check_edit(
908 r" 916 "Var",
909 struct S {} 917 r#"
910 impl S { 918enum E { Var(i32) }
911 fn foo(&self, x: i32) {} 919fn main() {
912 } 920 match E::Var(92) {
913 fn bar(s: &S) { 921 E::<|>(92) => (),
914 s.f<|> 922 }
915 } 923}
916 " 924"#,
917 ), 925 r#"
918 @r###" 926enum E { Var(i32) }
919 [ 927fn main() {
920 CompletionItem { 928 match E::Var(92) {
921 label: "foo(…)", 929 E::Var(92) => (),
922 source_range: 74..75, 930 }
923 delete: 74..75, 931}
924 insert: "foo(${1:x})$0", 932"#,
925 kind: Method, 933 );
926 lookup: "foo",
927 detail: "fn foo(&self, x: i32)",
928 trigger_call_info: true,
929 },
930 ]
931 "###
932 )
933 } 934 }
934 935
935 #[test] 936 #[test]
936 fn no_arg_snippets_for_method_call() { 937 fn no_call_parens_if_fn_ptr_needed() {
937 assert_debug_snapshot!( 938 mark::check!(no_call_parens_if_fn_ptr_needed);
938 do_reference_completion_with_options( 939 check_edit(
939 r" 940 "foo",
940 struct S {} 941 r#"
941 impl S { 942fn foo(foo: u8, bar: u8) {}
942 fn foo(&self, x: i32) {} 943struct ManualVtable { f: fn(u8, u8) }
943 } 944
944 fn bar(s: &S) { 945fn main() -> ManualVtable {
945 s.f<|> 946 ManualVtable { f: f<|> }
946 } 947}
947 ", 948"#,
948 CompletionConfig { 949 r#"
949 add_call_argument_snippets: false, 950fn foo(foo: u8, bar: u8) {}
950 .. Default::default() 951struct ManualVtable { f: fn(u8, u8) }
951 } 952
952 ), 953fn main() -> ManualVtable {
953 @r###" 954 ManualVtable { f: foo }
954 [ 955}
955 CompletionItem { 956"#,
956 label: "foo(…)", 957 );
957 source_range: 74..75,
958 delete: 74..75,
959 insert: "foo($0)",
960 kind: Method,
961 lookup: "foo",
962 detail: "fn foo(&self, x: i32)",
963 trigger_call_info: true,
964 },
965 ]
966 "###
967 )
968 } 958 }
969 959
970 #[test] 960 #[test]
971 fn dont_render_function_parens_in_use_item() { 961 fn no_parens_in_use_item() {
972 assert_debug_snapshot!( 962 mark::check!(no_parens_in_use_item);
973 do_reference_completion( 963 check_edit(
974 " 964 "foo",
975 //- /lib.rs 965 r#"
976 mod m { pub fn foo() {} } 966mod m { pub fn foo() {} }
977 use crate::m::f<|>; 967use crate::m::f<|>;
978 " 968"#,
979 ), 969 r#"
980 @r###" 970mod m { pub fn foo() {} }
981 [ 971use crate::m::foo;
982 CompletionItem { 972"#,
983 label: "foo",
984 source_range: 40..41,
985 delete: 40..41,
986 insert: "foo",
987 kind: Function,
988 detail: "pub fn foo()",
989 },
990 ]
991 "###
992 ); 973 );
993 } 974 }
994 975
995 #[test] 976 #[test]
996 fn dont_render_function_parens_if_already_call() { 977 fn no_parens_in_call() {
997 assert_debug_snapshot!( 978 check_edit(
998 do_reference_completion( 979 "foo",
999 " 980 r#"
1000 //- /lib.rs 981fn foo(x: i32) {}
1001 fn frobnicate() {} 982fn main() { f<|>(); }
1002 fn main() { 983"#,
1003 frob<|>(); 984 r#"
1004 } 985fn foo(x: i32) {}
1005 " 986fn main() { foo(); }
1006 ), 987"#,
1007 @r###"
1008 [
1009 CompletionItem {
1010 label: "frobnicate",
1011 source_range: 35..39,
1012 delete: 35..39,
1013 insert: "frobnicate",
1014 kind: Function,
1015 detail: "fn frobnicate()",
1016 },
1017 CompletionItem {
1018 label: "main",
1019 source_range: 35..39,
1020 delete: 35..39,
1021 insert: "main",
1022 kind: Function,
1023 detail: "fn main()",
1024 },
1025 ]
1026 "###
1027 ); 988 );
1028 assert_debug_snapshot!( 989 check_edit(
1029 do_reference_completion( 990 "foo",
1030 " 991 r#"
1031 //- /lib.rs 992struct Foo;
1032 struct Foo {} 993impl Foo { fn foo(&self){} }
1033 impl Foo { fn new() -> Foo {} } 994fn f(foo: &Foo) { foo.f<|>(); }
1034 fn main() { 995"#,
1035 Foo::ne<|>(); 996 r#"
1036 } 997struct Foo;
1037 " 998impl Foo { fn foo(&self){} }
1038 ), 999fn f(foo: &Foo) { foo.foo(); }
1039 @r###" 1000"#,
1040 [
1041 CompletionItem {
1042 label: "new",
1043 source_range: 67..69,
1044 delete: 67..69,
1045 insert: "new",
1046 kind: Function,
1047 detail: "fn new() -> Foo",
1048 },
1049 ]
1050 "###
1051 ); 1001 );
1052 } 1002 }
1053 1003
1054 #[test] 1004 #[test]
1055 fn inserts_angle_brackets_for_generics() { 1005 fn inserts_angle_brackets_for_generics() {
1056 mark::check!(inserts_angle_brackets_for_generics); 1006 mark::check!(inserts_angle_brackets_for_generics);
1057 assert_debug_snapshot!( 1007 check_edit(
1058 do_reference_completion( 1008 "Vec",
1059 r" 1009 r#"
1060 struct Vec<T> {} 1010struct Vec<T> {}
1061 fn foo(xs: Ve<|>) 1011fn foo(xs: Ve<|>)
1062 " 1012"#,
1063 ), 1013 r#"
1064 @r###" 1014struct Vec<T> {}
1065 [ 1015fn foo(xs: Vec<$0>)
1066 CompletionItem { 1016"#,
1067 label: "Vec<…>",
1068 source_range: 28..30,
1069 delete: 28..30,
1070 insert: "Vec<$0>",
1071 kind: Struct,
1072 lookup: "Vec",
1073 },
1074 CompletionItem {
1075 label: "foo(…)",
1076 source_range: 28..30,
1077 delete: 28..30,
1078 insert: "foo(${1:xs})$0",
1079 kind: Function,
1080 lookup: "foo",
1081 detail: "fn foo(xs: Ve)",
1082 trigger_call_info: true,
1083 },
1084 ]
1085 "###
1086 ); 1017 );
1087 assert_debug_snapshot!( 1018 check_edit(
1088 do_reference_completion( 1019 "Vec",
1089 r" 1020 r#"
1090 type Vec<T> = (T,); 1021type Vec<T> = (T,);
1091 fn foo(xs: Ve<|>) 1022fn foo(xs: Ve<|>)
1092 " 1023"#,
1093 ), 1024 r#"
1094 @r###" 1025type Vec<T> = (T,);
1095 [ 1026fn foo(xs: Vec<$0>)
1096 CompletionItem { 1027"#,
1097 label: "Vec<…>",
1098 source_range: 31..33,
1099 delete: 31..33,
1100 insert: "Vec<$0>",
1101 kind: TypeAlias,
1102 lookup: "Vec",
1103 },
1104 CompletionItem {
1105 label: "foo(…)",
1106 source_range: 31..33,
1107 delete: 31..33,
1108 insert: "foo(${1:xs})$0",
1109 kind: Function,
1110 lookup: "foo",
1111 detail: "fn foo(xs: Ve)",
1112 trigger_call_info: true,
1113 },
1114 ]
1115 "###
1116 ); 1028 );
1117 assert_debug_snapshot!( 1029 check_edit(
1118 do_reference_completion( 1030 "Vec",
1119 r" 1031 r#"
1120 struct Vec<T = i128> {} 1032struct Vec<T = i128> {}
1121 fn foo(xs: Ve<|>) 1033fn foo(xs: Ve<|>)
1122 " 1034"#,
1123 ), 1035 r#"
1124 @r###" 1036struct Vec<T = i128> {}
1125 [ 1037fn foo(xs: Vec)
1126 CompletionItem { 1038"#,
1127 label: "Vec",
1128 source_range: 35..37,
1129 delete: 35..37,
1130 insert: "Vec",
1131 kind: Struct,
1132 },
1133 CompletionItem {
1134 label: "foo(…)",
1135 source_range: 35..37,
1136 delete: 35..37,
1137 insert: "foo(${1:xs})$0",
1138 kind: Function,
1139 lookup: "foo",
1140 detail: "fn foo(xs: Ve)",
1141 trigger_call_info: true,
1142 },
1143 ]
1144 "###
1145 ); 1039 );
1146 assert_debug_snapshot!( 1040 check_edit(
1147 do_reference_completion( 1041 "Vec",
1148 r" 1042 r#"
1149 struct Vec<T> {} 1043struct Vec<T> {}
1150 fn foo(xs: Ve<|><i128>) 1044fn foo(xs: Ve<|><i128>)
1151 " 1045"#,
1152 ), 1046 r#"
1153 @r###" 1047struct Vec<T> {}
1154 [ 1048fn foo(xs: Vec<i128>)
1155 CompletionItem { 1049"#,
1156 label: "Vec",
1157 source_range: 28..30,
1158 delete: 28..30,
1159 insert: "Vec",
1160 kind: Struct,
1161 },
1162 CompletionItem {
1163 label: "foo(…)",
1164 source_range: 28..30,
1165 delete: 28..30,
1166 insert: "foo(${1:xs})$0",
1167 kind: Function,
1168 lookup: "foo",
1169 detail: "fn foo(xs: Ve<i128>)",
1170 trigger_call_info: true,
1171 },
1172 ]
1173 "###
1174 ); 1050 );
1175 } 1051 }
1176 1052
1177 #[test] 1053 #[test]
1178 fn dont_insert_macro_call_parens_unncessary() { 1054 fn dont_insert_macro_call_parens_unncessary() {
1179 mark::check!(dont_insert_macro_call_parens_unncessary); 1055 mark::check!(dont_insert_macro_call_parens_unncessary);
1180 assert_debug_snapshot!( 1056 check_edit(
1181 do_reference_completion( 1057 "frobnicate!",
1182 r" 1058 r#"
1183 //- /main.rs 1059//- /main.rs
1184 use foo::<|>; 1060use foo::<|>;
1185 1061//- /foo/lib.rs
1186 //- /foo/lib.rs 1062#[macro_export]
1187 #[macro_export] 1063macro_rules frobnicate { () => () }
1188 macro_rules frobnicate { 1064"#,
1189 () => () 1065 r#"
1190 } 1066use foo::frobnicate;
1191 " 1067"#,
1192 ),
1193 @r###"
1194 [
1195 CompletionItem {
1196 label: "frobnicate!",
1197 source_range: 9..9,
1198 delete: 9..9,
1199 insert: "frobnicate",
1200 kind: Macro,
1201 detail: "#[macro_export]\nmacro_rules! frobnicate",
1202 },
1203 ]
1204 "###
1205 ); 1068 );
1206 1069
1207 assert_debug_snapshot!( 1070 check_edit(
1208 do_reference_completion( 1071 "frobnicate!",
1209 r" 1072 r#"
1210 //- /main.rs 1073macro_rules frobnicate { () => () }
1211 macro_rules frobnicate { 1074fn main() { frob<|>!(); }
1212 () => () 1075"#,
1213 } 1076 r#"
1214 fn main() { 1077macro_rules frobnicate { () => () }
1215 frob<|>!(); 1078fn main() { frobnicate!(); }
1216 } 1079"#,
1217 "
1218 ),
1219 @r###"
1220 [
1221 CompletionItem {
1222 label: "frobnicate!",
1223 source_range: 56..60,
1224 delete: 56..60,
1225 insert: "frobnicate",
1226 kind: Macro,
1227 detail: "macro_rules! frobnicate",
1228 },
1229 CompletionItem {
1230 label: "main()",
1231 source_range: 56..60,
1232 delete: 56..60,
1233 insert: "main()$0",
1234 kind: Function,
1235 lookup: "main",
1236 detail: "fn main()",
1237 },
1238 ]
1239 "###
1240 ); 1080 );
1241 } 1081 }
1242 1082
1243 #[test] 1083 #[test]
1244 fn test_struct_field_completion_in_func_call() { 1084 fn active_param_score() {
1245 mark::check!(test_struct_field_completion_in_func_call); 1085 mark::check!(active_param_type_match);
1246 assert_debug_snapshot!( 1086 check_scores(
1247 do_reference_completion( 1087 r#"
1248 r" 1088struct S { foo: i64, bar: u32, baz: u32 }
1249 struct A { another_field: i64, the_field: u32, my_string: String } 1089fn test(bar: u32) { }
1250 fn test(my_param: u32) -> u32 { my_param } 1090fn foo(s: S) { test(s.<|>) }
1251 fn foo(a: A) { 1091"#,
1252 test(a.<|>) 1092 expect![[r#"
1253 } 1093 fd bar [type+name]
1254 ", 1094 fd baz [type]
1255 ), 1095 fd foo []
1256 @r###" 1096 "#]],
1257 [
1258 CompletionItem {
1259 label: "another_field",
1260 source_range: 136..136,
1261 delete: 136..136,
1262 insert: "another_field",
1263 kind: Field,
1264 detail: "i64",
1265 },
1266 CompletionItem {
1267 label: "my_string",
1268 source_range: 136..136,
1269 delete: 136..136,
1270 insert: "my_string",
1271 kind: Field,
1272 detail: "{unknown}",
1273 },
1274 CompletionItem {
1275 label: "the_field",
1276 source_range: 136..136,
1277 delete: 136..136,
1278 insert: "the_field",
1279 kind: Field,
1280 detail: "u32",
1281 score: TypeMatch,
1282 },
1283 ]
1284 "###
1285 ); 1097 );
1286 } 1098 }
1287 1099
1288 #[test] 1100 #[test]
1289 fn test_struct_field_completion_in_func_call_with_type_and_name() { 1101 fn record_field_scores() {
1290 assert_debug_snapshot!( 1102 mark::check!(record_field_type_match);
1291 do_reference_completion( 1103 check_scores(
1292 r" 1104 r#"
1293 struct A { another_field: i64, another_good_type: u32, the_field: u32 } 1105struct A { foo: i64, bar: u32, baz: u32 }
1294 fn test(the_field: u32) -> u32 { the_field } 1106struct B { x: (), y: f32, bar: u32 }
1295 fn foo(a: A) { 1107fn foo(a: A) { B { bar: a.<|> }; }
1296 test(a.<|>) 1108"#,
1297 } 1109 expect![[r#"
1298 ", 1110 fd bar [type+name]
1299 ), 1111 fd baz [type]
1300 @r###" 1112 fd foo []
1301 [ 1113 "#]],
1302 CompletionItem { 1114 )
1303 label: "another_field",
1304 source_range: 143..143,
1305 delete: 143..143,
1306 insert: "another_field",
1307 kind: Field,
1308 detail: "i64",
1309 },
1310 CompletionItem {
1311 label: "another_good_type",
1312 source_range: 143..143,
1313 delete: 143..143,
1314 insert: "another_good_type",
1315 kind: Field,
1316 detail: "u32",
1317 score: TypeMatch,
1318 },
1319 CompletionItem {
1320 label: "the_field",
1321 source_range: 143..143,
1322 delete: 143..143,
1323 insert: "the_field",
1324 kind: Field,
1325 detail: "u32",
1326 score: TypeAndNameMatch,
1327 },
1328 ]
1329 "###
1330 );
1331 } 1115 }
1332 1116
1333 #[test] 1117 #[test]
1334 fn test_struct_field_completion_in_record_lit() { 1118 fn record_field_and_call_scores() {
1335 mark::check!(test_struct_field_completion_in_record_lit); 1119 check_scores(
1336 assert_debug_snapshot!( 1120 r#"
1337 do_reference_completion( 1121struct A { foo: i64, bar: u32, baz: u32 }
1338 r" 1122struct B { x: (), y: f32, bar: u32 }
1339 struct A { another_field: i64, another_good_type: u32, the_field: u32 } 1123fn f(foo: i64) { }
1340 struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } 1124fn foo(a: A) { B { bar: f(a.<|>) }; }
1341 fn foo(a: A) { 1125"#,
1342 let b = B { 1126 expect![[r#"
1343 the_field: a.<|> 1127 fd foo [type+name]
1344 }; 1128 fd bar []
1345 } 1129 fd baz []
1346 ", 1130 "#]],
1347 ), 1131 );
1348 @r###" 1132 check_scores(
1349 [ 1133 r#"
1350 CompletionItem { 1134struct A { foo: i64, bar: u32, baz: u32 }
1351 label: "another_field", 1135struct B { x: (), y: f32, bar: u32 }
1352 source_range: 189..189, 1136fn f(foo: i64) { }
1353 delete: 189..189, 1137fn foo(a: A) { f(B { bar: a.<|> }); }
1354 insert: "another_field", 1138"#,
1355 kind: Field, 1139 expect![[r#"
1356 detail: "i64", 1140 fd bar [type+name]
1357 }, 1141 fd baz [type]
1358 CompletionItem { 1142 fd foo []
1359 label: "another_good_type", 1143 "#]],
1360 source_range: 189..189,
1361 delete: 189..189,
1362 insert: "another_good_type",
1363 kind: Field,
1364 detail: "u32",
1365 score: TypeMatch,
1366 },
1367 CompletionItem {
1368 label: "the_field",
1369 source_range: 189..189,
1370 delete: 189..189,
1371 insert: "the_field",
1372 kind: Field,
1373 detail: "u32",
1374 score: TypeAndNameMatch,
1375 },
1376 ]
1377 "###
1378 ); 1144 );
1379 } 1145 }
1380 1146
1381 #[test] 1147 #[test]
1382 fn test_struct_field_completion_in_record_lit_and_fn_call() { 1148 fn prioritize_exact_ref_match() {
1383 assert_debug_snapshot!( 1149 check_scores(
1384 do_reference_completion( 1150 r#"
1385 r" 1151struct WorldSnapshot { _f: () };
1386 struct A { another_field: i64, another_good_type: u32, the_field: u32 } 1152fn go(world: &WorldSnapshot) { go(w<|>) }
1387 struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } 1153"#,
1388 fn test(the_field: i64) -> i64 { the_field } 1154 expect![[r#"
1389 fn foo(a: A) { 1155 bn world [type+name]
1390 let b = B { 1156 st WorldSnapshot []
1391 the_field: test(a.<|>) 1157 fn go(…) []
1392 }; 1158 "#]],
1393 }
1394 ",
1395 ),
1396 @r###"
1397 [
1398 CompletionItem {
1399 label: "another_field",
1400 source_range: 239..239,
1401 delete: 239..239,
1402 insert: "another_field",
1403 kind: Field,
1404 detail: "i64",
1405 score: TypeMatch,
1406 },
1407 CompletionItem {
1408 label: "another_good_type",
1409 source_range: 239..239,
1410 delete: 239..239,
1411 insert: "another_good_type",
1412 kind: Field,
1413 detail: "u32",
1414 },
1415 CompletionItem {
1416 label: "the_field",
1417 source_range: 239..239,
1418 delete: 239..239,
1419 insert: "the_field",
1420 kind: Field,
1421 detail: "u32",
1422 },
1423 ]
1424 "###
1425 ); 1159 );
1426 } 1160 }
1427 1161
1428 #[test] 1162 #[test]
1429 fn test_struct_field_completion_in_fn_call_and_record_lit() { 1163 fn too_many_arguments() {
1430 assert_debug_snapshot!( 1164 mark::check!(too_many_arguments);
1431 do_reference_completion( 1165 check_scores(
1432 r" 1166 r#"
1433 struct A { another_field: i64, another_good_type: u32, the_field: u32 } 1167struct Foo;
1434 struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } 1168fn f(foo: &Foo) { f(foo, w<|>) }
1435 fn test(the_field: i64) -> i64 { the_field } 1169"#,
1436 fn foo(a: A) { 1170 expect![[r#"
1437 test(B { 1171 st Foo []
1438 the_field: a.<|> 1172 fn f(…) []
1439 }); 1173 bn foo []
1440 } 1174 "#]],
1441 ",
1442 ),
1443 @r###"
1444 [
1445 CompletionItem {
1446 label: "another_field",
1447 source_range: 231..231,
1448 delete: 231..231,
1449 insert: "another_field",
1450 kind: Field,
1451 detail: "i64",
1452 },
1453 CompletionItem {
1454 label: "another_good_type",
1455 source_range: 231..231,
1456 delete: 231..231,
1457 insert: "another_good_type",
1458 kind: Field,
1459 detail: "u32",
1460 score: TypeMatch,
1461 },
1462 CompletionItem {
1463 label: "the_field",
1464 source_range: 231..231,
1465 delete: 231..231,
1466 insert: "the_field",
1467 kind: Field,
1468 detail: "u32",
1469 score: TypeAndNameMatch,
1470 },
1471 ]
1472 "###
1473 ); 1175 );
1474 } 1176 }
1475 1177
1476 #[test] 1178 #[test]
1477 fn prioritize_exact_ref_match() { 1179 fn guesses_macro_braces() {
1478 assert_debug_snapshot!( 1180 check_edit(
1479 do_reference_completion( 1181 "vec!",
1480 r" 1182 r#"
1481 struct WorldSnapshot { _f: () }; 1183/// Creates a [`Vec`] containing the arguments.
1482 fn go(world: &WorldSnapshot) { 1184///
1483 go(w<|>) 1185/// ```
1484 } 1186/// let v = vec![1, 2, 3];
1485 ", 1187/// assert_eq!(v[0], 1);
1486 ), 1188/// assert_eq!(v[1], 2);
1487 @r###" 1189/// assert_eq!(v[2], 3);
1488 [ 1190/// ```
1489 CompletionItem { 1191macro_rules! vec { () => {} }
1490 label: "WorldSnapshot", 1192
1491 source_range: 71..72, 1193fn fn main() { v<|> }
1492 delete: 71..72, 1194"#,
1493 insert: "WorldSnapshot", 1195 r#"
1494 kind: Struct, 1196/// Creates a [`Vec`] containing the arguments.
1495 }, 1197///
1496 CompletionItem { 1198/// ```
1497 label: "go(…)", 1199/// let v = vec![1, 2, 3];
1498 source_range: 71..72, 1200/// assert_eq!(v[0], 1);
1499 delete: 71..72, 1201/// assert_eq!(v[1], 2);
1500 insert: "go(${1:world})$0", 1202/// assert_eq!(v[2], 3);
1501 kind: Function, 1203/// ```
1502 lookup: "go", 1204macro_rules! vec { () => {} }
1503 detail: "fn go(world: &WorldSnapshot)", 1205
1504 trigger_call_info: true, 1206fn fn main() { vec![$0] }
1505 }, 1207"#,
1506 CompletionItem {
1507 label: "world",
1508 source_range: 71..72,
1509 delete: 71..72,
1510 insert: "world",
1511 kind: Binding,
1512 detail: "&WorldSnapshot",
1513 score: TypeAndNameMatch,
1514 },
1515 ]
1516 "###
1517 ); 1208 );
1209
1210 check_edit(
1211 "foo!",
1212 r#"
1213/// Foo
1214///
1215/// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`,
1216/// call as `let _=foo! { hello world };`
1217macro_rules! foo { () => {} }
1218fn main() { <|> }
1219"#,
1220 r#"
1221/// Foo
1222///
1223/// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`,
1224/// call as `let _=foo! { hello world };`
1225macro_rules! foo { () => {} }
1226fn main() { foo! {$0} }
1227"#,
1228 )
1518 } 1229 }
1519} 1230}