Attempt to implement ranking of rules when none matches perfectly (wip)

This commit is contained in:
Florian Diebold 2020-03-13 15:18:17 +01:00 committed by Florian Diebold
parent b973158aeb
commit 6305d094ac
3 changed files with 51 additions and 11 deletions

View file

@ -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",
},
]
"###
);
}

View file

@ -14,24 +14,27 @@ pub(crate) fn expand(
rules: &crate::MacroRules,
input: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
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<tt::Subtree> {
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.

View file

@ -65,7 +65,7 @@ macro_rules! bail {
};
}
pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> ExpandResult<Bindings> {
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<B
err = Some(err!("leftover tokens"));
}
(res, err)
((res, src.len()), err)
}
fn match_subtree(