Merge #736
736: mbe: Add support matching for matching idents r=jrmuizel a=jrmuizel Factors out a helper and adds support for matching idents. Co-authored-by: Jeff Muizelaar <jrmuizel@gmail.com>
This commit is contained in:
commit
13a2bdb0a8
2 changed files with 49 additions and 24 deletions
|
@ -161,6 +161,18 @@ impl_froms!(TokenTree: Leaf, Subtree);
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_rules(macro_definition: &str) -> MacroRules {
|
||||||
|
let source_file = ast::SourceFile::parse(macro_definition);
|
||||||
|
let macro_definition = source_file
|
||||||
|
.syntax()
|
||||||
|
.descendants()
|
||||||
|
.find_map(ast::MacroCall::cast)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
|
||||||
|
crate::MacroRules::parse(&definition_tt).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) {
|
fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) {
|
||||||
let source_file = ast::SourceFile::parse(invocation);
|
let source_file = ast::SourceFile::parse(invocation);
|
||||||
let macro_invocation = source_file
|
let macro_invocation = source_file
|
||||||
|
@ -177,7 +189,8 @@ impl_froms!(TokenTree: Leaf, Subtree);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fail_match_pattern_by_first_token() {
|
fn test_fail_match_pattern_by_first_token() {
|
||||||
let macro_definition = r#"
|
let rules = create_rules(
|
||||||
|
r#"
|
||||||
macro_rules! foo {
|
macro_rules! foo {
|
||||||
($ i:ident) => (
|
($ i:ident) => (
|
||||||
mod $ i {}
|
mod $ i {}
|
||||||
|
@ -189,17 +202,8 @@ impl_froms!(TokenTree: Leaf, Subtree);
|
||||||
struct $ i;
|
struct $ i;
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
"#;
|
"#,
|
||||||
|
);
|
||||||
let source_file = ast::SourceFile::parse(macro_definition);
|
|
||||||
let macro_definition = source_file
|
|
||||||
.syntax()
|
|
||||||
.descendants()
|
|
||||||
.find_map(ast::MacroCall::cast)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
|
|
||||||
let rules = crate::MacroRules::parse(&definition_tt).unwrap();
|
|
||||||
|
|
||||||
assert_expansion(&rules, "foo! { foo }", "mod foo {}");
|
assert_expansion(&rules, "foo! { foo }", "mod foo {}");
|
||||||
assert_expansion(&rules, "foo! { = bar }", "fn bar () {}");
|
assert_expansion(&rules, "foo! { = bar }", "fn bar () {}");
|
||||||
|
@ -208,7 +212,8 @@ impl_froms!(TokenTree: Leaf, Subtree);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fail_match_pattern_by_last_token() {
|
fn test_fail_match_pattern_by_last_token() {
|
||||||
let macro_definition = r#"
|
let rules = create_rules(
|
||||||
|
r#"
|
||||||
macro_rules! foo {
|
macro_rules! foo {
|
||||||
($ i:ident) => (
|
($ i:ident) => (
|
||||||
mod $ i {}
|
mod $ i {}
|
||||||
|
@ -220,20 +225,35 @@ impl_froms!(TokenTree: Leaf, Subtree);
|
||||||
struct $ i;
|
struct $ i;
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
"#;
|
"#,
|
||||||
|
);
|
||||||
let source_file = ast::SourceFile::parse(macro_definition);
|
|
||||||
let macro_definition = source_file
|
|
||||||
.syntax()
|
|
||||||
.descendants()
|
|
||||||
.find_map(ast::MacroCall::cast)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
|
|
||||||
let rules = crate::MacroRules::parse(&definition_tt).unwrap();
|
|
||||||
|
|
||||||
assert_expansion(&rules, "foo! { foo }", "mod foo {}");
|
assert_expansion(&rules, "foo! { foo }", "mod foo {}");
|
||||||
assert_expansion(&rules, "foo! { bar = }", "fn bar () {}");
|
assert_expansion(&rules, "foo! { bar = }", "fn bar () {}");
|
||||||
assert_expansion(&rules, "foo! { Baz + }", "struct Baz ;");
|
assert_expansion(&rules, "foo! { Baz + }", "struct Baz ;");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fail_match_pattern_by_word_token() {
|
||||||
|
let rules = create_rules(
|
||||||
|
r#"
|
||||||
|
macro_rules! foo {
|
||||||
|
($ i:ident) => (
|
||||||
|
mod $ i {}
|
||||||
|
);
|
||||||
|
(spam $ i:ident) => (
|
||||||
|
fn $ i() {}
|
||||||
|
);
|
||||||
|
(eggs $ i:ident) => (
|
||||||
|
struct $ i;
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_expansion(&rules, "foo! { foo }", "mod foo {}");
|
||||||
|
assert_expansion(&rules, "foo! { spam bar }", "fn bar () {}");
|
||||||
|
assert_expansion(&rules, "foo! { eggs Baz }", "struct Baz ;");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Option<Bindings>
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
crate::Leaf::Ident(ident) => {
|
||||||
|
if input.eat_ident()?.text != ident.text {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
},
|
},
|
||||||
crate::TokenTree::Repeat(crate::Repeat {
|
crate::TokenTree::Repeat(crate::Repeat {
|
||||||
|
|
Loading…
Reference in a new issue