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.rs680
1 files changed, 210 insertions, 470 deletions
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index b18279746..fd12673b2 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -383,12 +383,14 @@ impl Builder {
383 return self; 383 return self;
384 } 384 }
385 if ctx.use_item_syntax.is_some() || ctx.is_call { 385 if ctx.use_item_syntax.is_some() || ctx.is_call {
386 mark::hit!(no_parens_in_use_item);
386 return self; 387 return self;
387 } 388 }
388 389
389 // Don't add parentheses if the expected type is some function reference. 390 // Don't add parentheses if the expected type is some function reference.
390 if let Some(ty) = &ctx.expected_type { 391 if let Some(ty) = &ctx.expected_type {
391 if ty.is_fn() { 392 if ty.is_fn() {
393 mark::hit!(no_call_parens_if_fn_ptr_needed);
392 return self; 394 return self;
393 } 395 }
394 } 396 }
@@ -413,7 +415,10 @@ impl Builder {
413 .sep_by(", "); 415 .sep_by(", ");
414 format!("{}({})$0", name, function_params_snippet) 416 format!("{}({})$0", name, function_params_snippet)
415 } 417 }
416 _ => format!("{}($0)", name), 418 _ => {
419 mark::hit!(suppress_arg_snippets);
420 format!("{}($0)", name)
421 }
417 }; 422 };
418 423
419 (snippet, format!("{}(…)", name)) 424 (snippet, format!("{}(…)", name))
@@ -460,7 +465,7 @@ mod tests {
460 use test_utils::mark; 465 use test_utils::mark;
461 466
462 use crate::completion::{ 467 use crate::completion::{
463 test_utils::{do_completion, do_completion_with_options}, 468 test_utils::{check_edit, check_edit_with_config, do_completion},
464 CompletionConfig, CompletionItem, CompletionKind, 469 CompletionConfig, CompletionItem, CompletionKind,
465 }; 470 };
466 471
@@ -468,13 +473,6 @@ mod tests {
468 do_completion(ra_fixture, CompletionKind::Reference) 473 do_completion(ra_fixture, CompletionKind::Reference)
469 } 474 }
470 475
471 fn do_reference_completion_with_options(
472 ra_fixture: &str,
473 options: CompletionConfig,
474 ) -> Vec<CompletionItem> {
475 do_completion_with_options(ra_fixture, CompletionKind::Reference, &options)
476 }
477
478 #[test] 476 #[test]
479 fn enum_detail_includes_names_for_record() { 477 fn enum_detail_includes_names_for_record() {
480 assert_debug_snapshot!( 478 assert_debug_snapshot!(
@@ -606,448 +604,240 @@ mod tests {
606 ] 604 ]
607 "### 605 "###
608 ); 606 );
609 }
610 607
611 #[test] 608 assert_debug_snapshot!(do_reference_completion(
612 fn inserts_parens_for_function_calls() { 609 r#"
613 mark::check!(inserts_parens_for_function_calls); 610struct A {
614 assert_debug_snapshot!( 611 #[deprecated]
615 do_reference_completion( 612 the_field: u32,
616 r" 613}
617 fn no_args() {} 614fn foo() {
618 fn main() { no_<|> } 615 A { the<|> }
619 " 616}
620 ), 617"#,
621 @r###" 618 ),
622 [ 619 @r###"
623 CompletionItem {
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 [ 620 [
653 CompletionItem { 621 CompletionItem {
654 label: "main()", 622 label: "the_field",
655 source_range: 47..52, 623 source_range: 69..72,
656 delete: 47..52, 624 delete: 69..72,
657 insert: "main()$0", 625 insert: "the_field",
658 kind: Function, 626 kind: Field,
659 lookup: "main", 627 detail: "u32",
660 detail: "fn main()", 628 deprecated: true,
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 }, 629 },
672 ] 630 ]
673 "### 631 "###);
632 }
633
634 #[test]
635 fn inserts_parens_for_function_calls() {
636 mark::check!(inserts_parens_for_function_calls);
637 check_edit(
638 "no_args",
639 r#"
640fn no_args() {}
641fn main() { no_<|> }
642"#,
643 r#"
644fn no_args() {}
645fn main() { no_args()$0 }
646"#,
674 ); 647 );
675 assert_debug_snapshot!( 648
676 do_reference_completion( 649 check_edit(
677 r" 650 "with_args",
678 fn with_ignored_args(_foo: i32, ___bar: bool, ho_ge_: String) {} 651 r#"
679 fn main() { with_<|> } 652fn with_args(x: i32, y: String) {}
680 " 653fn main() { with_<|> }
681 ), 654"#,
682 @r###" 655 r#"
683 [ 656fn with_args(x: i32, y: String) {}
684 CompletionItem { 657fn main() { with_args(${1:x}, ${2:y})$0 }
685 label: "main()", 658"#,
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 ); 659 );
706 assert_debug_snapshot!( 660
707 do_reference_completion( 661 check_edit(
708 r" 662 "foo",
709 struct S {} 663 r#"
710 impl S { 664struct S;
711 fn foo(&self) {} 665impl S {
712 } 666 fn foo(&self) {}
713 fn bar(s: &S) { 667}
714 s.f<|> 668fn bar(s: &S) { s.f<|> }
715 } 669"#,
716 " 670 r#"
717 ), 671struct S;
718 @r###" 672impl S {
719 [ 673 fn foo(&self) {}
720 CompletionItem { 674}
721 label: "foo()", 675fn bar(s: &S) { s.foo()$0 }
722 source_range: 66..67, 676"#,
723 delete: 66..67,
724 insert: "foo()$0",
725 kind: Method,
726 lookup: "foo",
727 detail: "fn foo(&self)",
728 },
729 ]
730 "###
731 ); 677 );
732 assert_debug_snapshot!( 678
733 do_reference_completion( 679 check_edit(
734 r" 680 "foo",
735 struct S {} 681 r#"
736 impl S { 682struct S {}
737 fn foo_ignored_args(&self, _a: bool, b: i32) {} 683impl S {
738 } 684 fn foo(&self, x: i32) {}
739 fn bar(s: &S) { 685}
740 s.f<|> 686fn bar(s: &S) {
741 } 687 s.f<|>
742 " 688}
743 ), 689"#,
744 @r###" 690 r#"
745 [ 691struct S {}
746 CompletionItem { 692impl S {
747 label: "foo_ignored_args(…)", 693 fn foo(&self, x: i32) {}
748 source_range: 97..98, 694}
749 delete: 97..98, 695fn bar(s: &S) {
750 insert: "foo_ignored_args(${1:a}, ${2:b})$0", 696 s.foo(${1:x})$0
751 kind: Method, 697}
752 lookup: "foo_ignored_args", 698"#,
753 detail: "fn foo_ignored_args(&self, _a: bool, b: i32)",
754 trigger_call_info: true,
755 },
756 ]
757 "###
758 ); 699 );
759 } 700 }
760 701
761 #[test] 702 #[test]
762 fn inserts_parens_for_tuple_enums() { 703 fn suppress_arg_snippets() {
763 assert_debug_snapshot!( 704 mark::check!(suppress_arg_snippets);
764 do_reference_completion( 705 check_edit_with_config(
765 r" 706 "with_args",
766 enum Option<T> { Some(T), None } 707 r#"
767 use Option::*; 708fn with_args(x: i32, y: String) {}
768 fn main() -> Option<i32> { 709fn main() { with_<|> }
769 Som<|> 710"#,
770 } 711 r#"
771 " 712fn with_args(x: i32, y: String) {}
772 ), 713fn main() { with_args($0) }
773 @r###" 714"#,
774 [ 715 &CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() },
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 ); 716 );
854 } 717 }
855 718
856 #[test] 719 #[test]
857 fn no_call_parens_if_fn_ptr_needed() { 720 fn strips_underscores_from_args() {
858 assert_debug_snapshot!( 721 check_edit(
859 do_reference_completion( 722 "foo",
860 r" 723 r#"
861 fn somefn(with: u8, a: u8, lot: u8, of: u8, args: u8) {} 724fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {}
862 725fn main() { f<|> }
863 struct ManualVtable { 726"#,
864 method: fn(u8, u8, u8, u8, u8), 727 r#"
865 } 728fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {}
866 729fn main() { foo(${1:foo}, ${2:bar}, ${3:ho_ge_})$0 }
867 fn main() -> ManualVtable { 730"#,
868 ManualVtable {
869 method: some<|>
870 }
871 }
872 "
873 ),
874 @r###"
875 [
876 CompletionItem {
877 label: "ManualVtable",
878 source_range: 182..186,
879 delete: 182..186,
880 insert: "ManualVtable",
881 kind: Struct,
882 },
883 CompletionItem {
884 label: "main",
885 source_range: 182..186,
886 delete: 182..186,
887 insert: "main",
888 kind: Function,
889 detail: "fn main() -> ManualVtable",
890 },
891 CompletionItem {
892 label: "somefn",
893 source_range: 182..186,
894 delete: 182..186,
895 insert: "somefn",
896 kind: Function,
897 detail: "fn somefn(with: u8, a: u8, lot: u8, of: u8, args: u8)",
898 },
899 ]
900 "###
901 ); 731 );
902 } 732 }
903 733
904 #[test] 734 #[test]
905 fn arg_snippets_for_method_call() { 735 fn inserts_parens_for_tuple_enums() {
906 assert_debug_snapshot!( 736 check_edit(
907 do_reference_completion( 737 "Some",
908 r" 738 r#"
909 struct S {} 739enum Option<T> { Some(T), None }
910 impl S { 740use Option::*;
911 fn foo(&self, x: i32) {} 741fn main() -> Option<i32> {
912 } 742 Som<|>
913 fn bar(s: &S) { 743}
914 s.f<|> 744"#,
915 } 745 r#"
916 " 746enum Option<T> { Some(T), None }
917 ), 747use Option::*;
918 @r###" 748fn main() -> Option<i32> {
919 [ 749 Some($0)
920 CompletionItem { 750}
921 label: "foo(…)", 751"#,
922 source_range: 74..75, 752 );
923 delete: 74..75, 753 check_edit(
924 insert: "foo(${1:x})$0", 754 "Some",
925 kind: Method, 755 r#"
926 lookup: "foo", 756enum Option<T> { Some(T), None }
927 detail: "fn foo(&self, x: i32)", 757use Option::*;
928 trigger_call_info: true, 758fn main(value: Option<i32>) {
929 }, 759 match value {
930 ] 760 Som<|>
931 "### 761 }
932 ) 762}
763"#,
764 r#"
765enum Option<T> { Some(T), None }
766use Option::*;
767fn main(value: Option<i32>) {
768 match value {
769 Some($0)
770 }
771}
772"#,
773 );
933 } 774 }
934 775
935 #[test] 776 #[test]
936 fn no_arg_snippets_for_method_call() { 777 fn no_call_parens_if_fn_ptr_needed() {
937 assert_debug_snapshot!( 778 mark::check!(no_call_parens_if_fn_ptr_needed);
938 do_reference_completion_with_options( 779 check_edit(
939 r" 780 "foo",
940 struct S {} 781 r#"
941 impl S { 782fn foo(foo: u8, bar: u8) {}
942 fn foo(&self, x: i32) {} 783struct ManualVtable { f: fn(u8, u8) }
943 } 784
944 fn bar(s: &S) { 785fn main() -> ManualVtable {
945 s.f<|> 786 ManualVtable { f: f<|> }
946 } 787}
947 ", 788"#,
948 CompletionConfig { 789 r#"
949 add_call_argument_snippets: false, 790fn foo(foo: u8, bar: u8) {}
950 .. Default::default() 791struct ManualVtable { f: fn(u8, u8) }
951 } 792
952 ), 793fn main() -> ManualVtable {
953 @r###" 794 ManualVtable { f: foo }
954 [ 795}
955 CompletionItem { 796"#,
956 label: "foo(…)", 797 );
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 } 798 }
969 799
970 #[test] 800 #[test]
971 fn dont_render_function_parens_in_use_item() { 801 fn no_parens_in_use_item() {
972 assert_debug_snapshot!( 802 mark::check!(no_parens_in_use_item);
973 do_reference_completion( 803 check_edit(
974 " 804 "foo",
975 //- /lib.rs 805 r#"
976 mod m { pub fn foo() {} } 806mod m { pub fn foo() {} }
977 use crate::m::f<|>; 807use crate::m::f<|>;
978 " 808"#,
979 ), 809 r#"
980 @r###" 810mod m { pub fn foo() {} }
981 [ 811use crate::m::foo;
982 CompletionItem { 812"#,
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 ); 813 );
993 } 814 }
994 815
995 #[test] 816 #[test]
996 fn dont_render_function_parens_if_already_call() { 817 fn no_parens_in_call() {
997 assert_debug_snapshot!( 818 check_edit(
998 do_reference_completion( 819 "foo",
999 " 820 r#"
1000 //- /lib.rs 821fn foo(x: i32) {}
1001 fn frobnicate() {} 822fn main() { f<|>(); }
1002 fn main() { 823"#,
1003 frob<|>(); 824 r#"
1004 } 825fn foo(x: i32) {}
1005 " 826fn main() { foo(); }
1006 ), 827"#,
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 ); 828 );
1028 assert_debug_snapshot!( 829 check_edit(
1029 do_reference_completion( 830 "foo",
1030 " 831 r#"
1031 //- /lib.rs 832struct Foo;
1032 struct Foo {} 833impl Foo { fn foo(&self){} }
1033 impl Foo { fn new() -> Foo {} } 834fn f(foo: &Foo) { foo.f<|>(); }
1034 fn main() { 835"#,
1035 Foo::ne<|>(); 836 r#"
1036 } 837struct Foo;
1037 " 838impl Foo { fn foo(&self){} }
1038 ), 839fn f(foo: &Foo) { foo.foo(); }
1039 @r###" 840"#,
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 ); 841 );
1052 } 842 }
1053 843
@@ -1516,54 +1306,4 @@ mod tests {
1516 "### 1306 "###
1517 ); 1307 );
1518 } 1308 }
1519
1520 #[test]
1521 fn no_keyword_autocompletion_on_line_comments() {
1522 assert_debug_snapshot!(
1523 do_completion(
1524 r"
1525 fn test() {
1526 let x = 2; // A comment<|>
1527 }
1528 ",
1529 CompletionKind::Keyword
1530 ),
1531 @r###"
1532 []
1533 "###
1534 );
1535 }
1536
1537 #[test]
1538 fn no_keyword_autocompletion_on_multi_line_comments() {
1539 assert_debug_snapshot!(
1540 do_completion(
1541 r"
1542 /*
1543 Some multi-line comment<|>
1544 */
1545 ",
1546 CompletionKind::Keyword
1547 ),
1548 @r###"
1549 []
1550 "###
1551 );
1552 }
1553
1554 #[test]
1555 fn no_keyword_autocompletion_on_doc_comments() {
1556 assert_debug_snapshot!(
1557 do_completion(
1558 r"
1559 /// Some doc comment
1560 /// let test<|> = 1
1561 ",
1562 CompletionKind::Keyword
1563 ),
1564 @r###"
1565 []
1566 "###
1567 );
1568 }
1569} 1309}