From 6305d094ac61ed6e437537b93f4e587b415678c9 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 13 Mar 2020 15:18:17 +0100 Subject: Attempt to implement ranking of rules when none matches perfectly (wip) --- crates/ra_ide/src/completion/complete_scope.rs | 39 +++++++++++++++++++++++++- crates/ra_mbe/src/mbe_expander.rs | 19 +++++++------ crates/ra_mbe/src/mbe_expander/matcher.rs | 4 +-- 3 files changed, 51 insertions(+), 11 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index 5ffff5a1c..2733922f8 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 { } " ), - @"[]" + @r###" + [ + CompletionItem { + label: "m!", + source_range: [145; 145), + delete: [145; 145), + insert: "m!($0)", + kind: Macro, + detail: "macro_rules! m", + }, + CompletionItem { + label: "quux(…)", + source_range: [145; 145), + delete: [145; 145), + insert: "quux(${1:x})$0", + kind: Function, + lookup: "quux", + detail: "fn quux(x: i32)", + trigger_call_info: true, + }, + CompletionItem { + label: "x", + source_range: [145; 145), + delete: [145; 145), + insert: "x", + kind: Binding, + detail: "i32", + }, + CompletionItem { + label: "y", + source_range: [145; 145), + delete: [145; 145), + insert: "y", + kind: Binding, + detail: "i32", + }, + ] + "### ); } diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index da3952428..5083d5410 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs @@ -14,24 +14,27 @@ pub(crate) fn expand( rules: &crate::MacroRules, input: &tt::Subtree, ) -> ExpandResult { - let (mut result, mut err) = (tt::Subtree::default(), Some(ExpandError::NoMatchingRule)); + let (mut result, mut left_over, mut err) = (tt::Subtree::default(), usize::max_value(), Some(ExpandError::NoMatchingRule)); for rule in &rules.rules { - let (res, e) = expand_rule(rule, input); + let ((res, left), e) = expand_rule(rule, input); if e.is_none() { // if we find a rule that applies without errors, we're done return (res, None); } - // TODO decide which result is better - result = res; - err = e; + // use the rule if we matched more tokens + if left < left_over { + result = res; + err = e; + left_over = left; + } } (result, err) } -fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> ExpandResult { - let (bindings, bindings_err) = dbg!(matcher::match_(&rule.lhs, input)); +fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> ExpandResult<(tt::Subtree, usize)> { + let ((bindings, left_over), bindings_err) = dbg!(matcher::match_(&rule.lhs, input)); let (res, transcribe_err) = dbg!(transcriber::transcribe(&rule.rhs, &bindings)); - (res, bindings_err.or(transcribe_err)) + ((res, left_over), bindings_err.or(transcribe_err)) } /// The actual algorithm for expansion is not too hard, but is pretty tricky. diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index f9d4952c6..52f1ac252 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs @@ -65,7 +65,7 @@ macro_rules! bail { }; } -pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> ExpandResult { +pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> ExpandResult<(Bindings, usize)> { assert!(pattern.delimiter == None); let mut res = Bindings::default(); @@ -77,7 +77,7 @@ pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> ExpandResult