mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Attempt to implement ranking of rules when none matches perfectly (wip)
This commit is contained in:
parent
b973158aeb
commit
6305d094ac
3 changed files with 51 additions and 11 deletions
|
@ -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",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"###
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,24 +14,27 @@ pub(crate) fn expand(
|
||||||
rules: &crate::MacroRules,
|
rules: &crate::MacroRules,
|
||||||
input: &tt::Subtree,
|
input: &tt::Subtree,
|
||||||
) -> ExpandResult<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 {
|
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 e.is_none() {
|
||||||
// if we find a rule that applies without errors, we're done
|
// if we find a rule that applies without errors, we're done
|
||||||
return (res, None);
|
return (res, None);
|
||||||
}
|
}
|
||||||
// TODO decide which result is better
|
// use the rule if we matched more tokens
|
||||||
result = res;
|
if left < left_over {
|
||||||
err = e;
|
result = res;
|
||||||
|
err = e;
|
||||||
|
left_over = left;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(result, err)
|
(result, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> ExpandResult<(tt::Subtree, usize)> {
|
||||||
let (bindings, bindings_err) = dbg!(matcher::match_(&rule.lhs, input));
|
let ((bindings, left_over), bindings_err) = dbg!(matcher::match_(&rule.lhs, input));
|
||||||
let (res, transcribe_err) = dbg!(transcriber::transcribe(&rule.rhs, &bindings));
|
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.
|
/// The actual algorithm for expansion is not too hard, but is pretty tricky.
|
||||||
|
|
|
@ -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);
|
assert!(pattern.delimiter == None);
|
||||||
|
|
||||||
let mut res = Bindings::default();
|
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"));
|
err = Some(err!("leftover tokens"));
|
||||||
}
|
}
|
||||||
|
|
||||||
(res, err)
|
((res, src.len()), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_subtree(
|
fn match_subtree(
|
||||||
|
|
Loading…
Reference in a new issue