mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
By pass unbind $var while mbe expanding
This commit is contained in:
parent
e8e46100d6
commit
31909cc7d7
3 changed files with 39 additions and 7 deletions
|
@ -84,6 +84,10 @@ enum Binding {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bindings {
|
impl Bindings {
|
||||||
|
fn contains(&self, name: &SmolStr) -> bool {
|
||||||
|
self.inner.contains_key(name)
|
||||||
|
}
|
||||||
|
|
||||||
fn get(&self, name: &SmolStr, nesting: &[usize]) -> Result<&tt::TokenTree, ExpandError> {
|
fn get(&self, name: &SmolStr, nesting: &[usize]) -> Result<&tt::TokenTree, ExpandError> {
|
||||||
let mut b = self
|
let mut b = self
|
||||||
.inner
|
.inner
|
||||||
|
@ -458,6 +462,33 @@ fn expand_tt(
|
||||||
// FIXME: Properly handle $crate token
|
// FIXME: Properly handle $crate token
|
||||||
tt::Leaf::from(tt::Ident { text: "$crate".into(), id: TokenId::unspecified() })
|
tt::Leaf::from(tt::Ident { text: "$crate".into(), id: TokenId::unspecified() })
|
||||||
.into()
|
.into()
|
||||||
|
} else if !ctx.bindings.contains(&v.text) {
|
||||||
|
// Note that it is possible to have a `$var` inside a macro which is not bound.
|
||||||
|
// For example:
|
||||||
|
// ```
|
||||||
|
// macro_rules! foo {
|
||||||
|
// ($a:ident, $b:ident, $c:tt) => {
|
||||||
|
// macro_rules! bar {
|
||||||
|
// ($bi:ident) => {
|
||||||
|
// fn $bi() -> u8 {$c}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
// We just treat it a normal tokens
|
||||||
|
tt::Subtree {
|
||||||
|
delimiter: tt::Delimiter::None,
|
||||||
|
token_trees: vec![
|
||||||
|
tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone })
|
||||||
|
.into(),
|
||||||
|
tt::Leaf::from(tt::Ident {
|
||||||
|
text: v.text.clone(),
|
||||||
|
id: TokenId::unspecified(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
.into()
|
||||||
} else {
|
} else {
|
||||||
let tkn = ctx.bindings.get(&v.text, &ctx.nesting)?.clone();
|
let tkn = ctx.bindings.get(&v.text, &ctx.nesting)?.clone();
|
||||||
ctx.var_expanded = true;
|
ctx.var_expanded = true;
|
||||||
|
@ -484,11 +515,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_expand_rule() {
|
fn test_expand_rule() {
|
||||||
assert_err(
|
// FIXME: The missing $var check should be in parsing phase
|
||||||
"($i:ident) => ($j)",
|
// assert_err(
|
||||||
"foo!{a}",
|
// "($i:ident) => ($j)",
|
||||||
ExpandError::BindingError(String::from("could not find binding `j`")),
|
// "foo!{a}",
|
||||||
);
|
// ExpandError::BindingError(String::from("could not find binding `j`")),
|
||||||
|
// );
|
||||||
|
|
||||||
assert_err(
|
assert_err(
|
||||||
"($($i:ident);*) => ($i)",
|
"($($i:ident);*) => ($i)",
|
||||||
|
|
|
@ -952,7 +952,7 @@ macro_rules! foo {
|
||||||
MacroKind::Items,
|
MacroKind::Items,
|
||||||
&rules,
|
&rules,
|
||||||
r#"foo!(x,y, 1);"#,
|
r#"foo!(x,y, 1);"#,
|
||||||
r#"macro_rules ! bar {(bi : ident) => {fn bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#,
|
r#"macro_rules ! bar {($ bi : ident) => {fn $ bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue