diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-03-17 09:41:30 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-17 09:41:30 +0000 |
commit | 6aa432d86b7e4fb691600032ebdf6f2301152447 (patch) | |
tree | aa012212c11e43a95547f553b5116922631f9896 /crates/ra_ide/src | |
parent | cf4ae9aa591729dde25a7df3fa5c22ca0fd94145 (diff) | |
parent | 6c20d7e979b967eb20207414c0a0bf875bbcb98d (diff) |
Merge #3580
3580: More error-resilient MBE expansion r=matklad a=flodiebold
This is the beginning of an attempt to make macro-by-example expansion more resilient, so that we still get an expansion even if no rule exactly matches, with the goal to make completion work better in macro calls.
The general idea is to make everything return `(T, Option<ExpandError>)` instead of `Result<T, ExpandError>`; and then to try each macro arm in turn, and somehow choose the 'best' matching rule if none matches without errors. Finding that 'best' match isn't done yet; I'm currently counting how many tokens were consumed from the args before an error, but it also needs to take into account whether there were further patterns that had nothing to match.
I'll continue this later, but I'm interested whether you think this is the right path, @matklad & @edwin0cheng.
Co-authored-by: Florian Diebold <[email protected]>
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 50 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_pattern.rs | 13 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_scope.rs | 92 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/expand_macro.rs | 2 |
5 files changed, 153 insertions, 6 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index f07611d88..82ec16913 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -720,7 +720,18 @@ mod tests { | |||
720 | } | 720 | } |
721 | ", | 721 | ", |
722 | ), | 722 | ), |
723 | @r###"[]"### | 723 | @r###" |
724 | [ | ||
725 | CompletionItem { | ||
726 | label: "the_field", | ||
727 | source_range: [156; 156), | ||
728 | delete: [156; 156), | ||
729 | insert: "the_field", | ||
730 | kind: Field, | ||
731 | detail: "u32", | ||
732 | }, | ||
733 | ] | ||
734 | "### | ||
724 | ); | 735 | ); |
725 | } | 736 | } |
726 | 737 | ||
@@ -752,6 +763,43 @@ mod tests { | |||
752 | } | 763 | } |
753 | 764 | ||
754 | #[test] | 765 | #[test] |
766 | fn macro_expansion_resilient() { | ||
767 | assert_debug_snapshot!( | ||
768 | do_ref_completion( | ||
769 | r" | ||
770 | macro_rules! dbg { | ||
771 | () => {}; | ||
772 | ($val:expr) => { | ||
773 | match $val { tmp => { tmp } } | ||
774 | }; | ||
775 | // Trailing comma with single argument is ignored | ||
776 | ($val:expr,) => { $crate::dbg!($val) }; | ||
777 | ($($val:expr),+ $(,)?) => { | ||
778 | ($($crate::dbg!($val)),+,) | ||
779 | }; | ||
780 | } | ||
781 | struct A { the_field: u32 } | ||
782 | fn foo(a: A) { | ||
783 | dbg!(a.<|>) | ||
784 | } | ||
785 | ", | ||
786 | ), | ||
787 | @r###" | ||
788 | [ | ||
789 | CompletionItem { | ||
790 | label: "the_field", | ||
791 | source_range: [552; 552), | ||
792 | delete: [552; 552), | ||
793 | insert: "the_field", | ||
794 | kind: Field, | ||
795 | detail: "u32", | ||
796 | }, | ||
797 | ] | ||
798 | "### | ||
799 | ); | ||
800 | } | ||
801 | |||
802 | #[test] | ||
755 | fn test_method_completion_3547() { | 803 | fn test_method_completion_3547() { |
756 | assert_debug_snapshot!( | 804 | assert_debug_snapshot!( |
757 | do_ref_completion( | 805 | do_ref_completion( |
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs index 6a1a66ef1..cb84bb934 100644 --- a/crates/ra_ide/src/completion/complete_pattern.rs +++ b/crates/ra_ide/src/completion/complete_pattern.rs | |||
@@ -89,7 +89,6 @@ mod tests { | |||
89 | 89 | ||
90 | #[test] | 90 | #[test] |
91 | fn completes_in_simple_macro_call() { | 91 | fn completes_in_simple_macro_call() { |
92 | // FIXME: doesn't work yet because of missing error recovery in macro expansion | ||
93 | let completions = complete( | 92 | let completions = complete( |
94 | r" | 93 | r" |
95 | macro_rules! m { ($e:expr) => { $e } } | 94 | macro_rules! m { ($e:expr) => { $e } } |
@@ -102,6 +101,16 @@ mod tests { | |||
102 | } | 101 | } |
103 | ", | 102 | ", |
104 | ); | 103 | ); |
105 | assert_debug_snapshot!(completions, @r###"[]"###); | 104 | assert_debug_snapshot!(completions, @r###" |
105 | [ | ||
106 | CompletionItem { | ||
107 | label: "E", | ||
108 | source_range: [151; 151), | ||
109 | delete: [151; 151), | ||
110 | insert: "E", | ||
111 | kind: Enum, | ||
112 | }, | ||
113 | ] | ||
114 | "###); | ||
106 | } | 115 | } |
107 | } | 116 | } |
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index 5ffff5a1c..81d3cc1b6 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs | |||
@@ -811,7 +811,44 @@ mod tests { | |||
811 | } | 811 | } |
812 | " | 812 | " |
813 | ), | 813 | ), |
814 | @"[]" | 814 | @r###" |
815 | [ | ||
816 | CompletionItem { | ||
817 | label: "m!", | ||
818 | source_range: [145; 145), | ||
819 | delete: [145; 145), | ||
820 | insert: "m!($0)", | ||
821 | kind: Macro, | ||
822 | detail: "macro_rules! m", | ||
823 | }, | ||
824 | CompletionItem { | ||
825 | label: "quux(…)", | ||
826 | source_range: [145; 145), | ||
827 | delete: [145; 145), | ||
828 | insert: "quux(${1:x})$0", | ||
829 | kind: Function, | ||
830 | lookup: "quux", | ||
831 | detail: "fn quux(x: i32)", | ||
832 | trigger_call_info: true, | ||
833 | }, | ||
834 | CompletionItem { | ||
835 | label: "x", | ||
836 | source_range: [145; 145), | ||
837 | delete: [145; 145), | ||
838 | insert: "x", | ||
839 | kind: Binding, | ||
840 | detail: "i32", | ||
841 | }, | ||
842 | CompletionItem { | ||
843 | label: "y", | ||
844 | source_range: [145; 145), | ||
845 | delete: [145; 145), | ||
846 | insert: "y", | ||
847 | kind: Binding, | ||
848 | detail: "i32", | ||
849 | }, | ||
850 | ] | ||
851 | "### | ||
815 | ); | 852 | ); |
816 | } | 853 | } |
817 | 854 | ||
@@ -869,6 +906,59 @@ mod tests { | |||
869 | } | 906 | } |
870 | 907 | ||
871 | #[test] | 908 | #[test] |
909 | fn completes_in_simple_macro_without_closing_parens() { | ||
910 | assert_debug_snapshot!( | ||
911 | do_reference_completion( | ||
912 | r" | ||
913 | macro_rules! m { ($e:expr) => { $e } } | ||
914 | fn quux(x: i32) { | ||
915 | let y = 92; | ||
916 | m!(x<|> | ||
917 | } | ||
918 | " | ||
919 | ), | ||
920 | @r###" | ||
921 | [ | ||
922 | CompletionItem { | ||
923 | label: "m!", | ||
924 | source_range: [145; 146), | ||
925 | delete: [145; 146), | ||
926 | insert: "m!($0)", | ||
927 | kind: Macro, | ||
928 | detail: "macro_rules! m", | ||
929 | }, | ||
930 | CompletionItem { | ||
931 | label: "quux(…)", | ||
932 | source_range: [145; 146), | ||
933 | delete: [145; 146), | ||
934 | insert: "quux(${1:x})$0", | ||
935 | kind: Function, | ||
936 | lookup: "quux", | ||
937 | detail: "fn quux(x: i32)", | ||
938 | trigger_call_info: true, | ||
939 | }, | ||
940 | CompletionItem { | ||
941 | label: "x", | ||
942 | source_range: [145; 146), | ||
943 | delete: [145; 146), | ||
944 | insert: "x", | ||
945 | kind: Binding, | ||
946 | detail: "i32", | ||
947 | }, | ||
948 | CompletionItem { | ||
949 | label: "y", | ||
950 | source_range: [145; 146), | ||
951 | delete: [145; 146), | ||
952 | insert: "y", | ||
953 | kind: Binding, | ||
954 | detail: "i32", | ||
955 | }, | ||
956 | ] | ||
957 | "### | ||
958 | ); | ||
959 | } | ||
960 | |||
961 | #[test] | ||
872 | fn completes_unresolved_uses() { | 962 | fn completes_unresolved_uses() { |
873 | assert_debug_snapshot!( | 963 | assert_debug_snapshot!( |
874 | do_reference_completion( | 964 | do_reference_completion( |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 3646fb8dc..54589a2a8 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -135,7 +135,7 @@ impl<'a> CompletionContext<'a> { | |||
135 | ), | 135 | ), |
136 | ) { | 136 | ) { |
137 | let new_offset = hypothetical_expansion.1.text_range().start(); | 137 | let new_offset = hypothetical_expansion.1.text_range().start(); |
138 | if new_offset >= actual_expansion.text_range().end() { | 138 | if new_offset > actual_expansion.text_range().end() { |
139 | break; | 139 | break; |
140 | } | 140 | } |
141 | original_file = actual_expansion; | 141 | original_file = actual_expansion; |
diff --git a/crates/ra_ide/src/expand_macro.rs b/crates/ra_ide/src/expand_macro.rs index f6667cb33..e58526f31 100644 --- a/crates/ra_ide/src/expand_macro.rs +++ b/crates/ra_ide/src/expand_macro.rs | |||
@@ -259,7 +259,7 @@ fn some_thing() -> u32 { | |||
259 | ); | 259 | ); |
260 | 260 | ||
261 | assert_eq!(res.name, "foo"); | 261 | assert_eq!(res.name, "foo"); |
262 | assert_snapshot!(res.expansion, @r###"bar!()"###); | 262 | assert_snapshot!(res.expansion, @r###""###); |
263 | } | 263 | } |
264 | 264 | ||
265 | #[test] | 265 | #[test] |