diff options
Diffstat (limited to 'crates/ra_mbe/src')
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 118 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 36 | ||||
-rw-r--r-- | crates/ra_mbe/src/tests.rs | 18 |
4 files changed, 74 insertions, 102 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 52c3d03b5..f07f000ff 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -41,8 +41,8 @@ pub enum ExpandError { | |||
41 | } | 41 | } |
42 | 42 | ||
43 | pub use crate::syntax_bridge::{ | 43 | pub use crate::syntax_bridge::{ |
44 | ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_ast_item_list, token_tree_to_expr, | 44 | ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_items, |
45 | token_tree_to_macro_items, token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty, | 45 | token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | /// This struct contains AST for a single `macro_rules` definition. What might | 48 | /// This struct contains AST for a single `macro_rules` definition. What might |
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index 01641fdee..78df96880 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -81,21 +81,26 @@ struct Bindings { | |||
81 | 81 | ||
82 | #[derive(Debug)] | 82 | #[derive(Debug)] |
83 | enum Binding { | 83 | enum Binding { |
84 | Simple(tt::TokenTree), | 84 | Fragment(Fragment), |
85 | Nested(Vec<Binding>), | 85 | Nested(Vec<Binding>), |
86 | Empty, | 86 | Empty, |
87 | } | 87 | } |
88 | 88 | ||
89 | #[derive(Debug, Clone)] | ||
90 | enum Fragment { | ||
91 | /// token fragments are just copy-pasted into the output | ||
92 | Tokens(tt::TokenTree), | ||
93 | /// Ast fragments are inserted with fake delimiters, so as to make things | ||
94 | /// like `$i * 2` where `$i = 1 + 1` work as expectd. | ||
95 | Ast(tt::TokenTree), | ||
96 | } | ||
97 | |||
89 | impl Bindings { | 98 | impl Bindings { |
90 | fn push_optional(&mut self, name: &SmolStr) { | 99 | fn push_optional(&mut self, name: &SmolStr) { |
91 | // FIXME: Do we have a better way to represent an empty token ? | 100 | // FIXME: Do we have a better way to represent an empty token ? |
92 | // Insert an empty subtree for empty token | 101 | // Insert an empty subtree for empty token |
93 | self.inner.insert( | 102 | let tt = tt::Subtree { delimiter: tt::Delimiter::None, token_trees: vec![] }.into(); |
94 | name.clone(), | 103 | self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt))); |
95 | Binding::Simple( | ||
96 | tt::Subtree { delimiter: tt::Delimiter::None, token_trees: vec![] }.into(), | ||
97 | ), | ||
98 | ); | ||
99 | } | 104 | } |
100 | 105 | ||
101 | fn push_empty(&mut self, name: &SmolStr) { | 106 | fn push_empty(&mut self, name: &SmolStr) { |
@@ -106,13 +111,13 @@ impl Bindings { | |||
106 | self.inner.contains_key(name) | 111 | self.inner.contains_key(name) |
107 | } | 112 | } |
108 | 113 | ||
109 | fn get(&self, name: &SmolStr, nesting: &[usize]) -> Result<&tt::TokenTree, ExpandError> { | 114 | fn get(&self, name: &SmolStr, nesting: &[usize]) -> Result<&Fragment, ExpandError> { |
110 | let mut b = self.inner.get(name).ok_or_else(|| { | 115 | let mut b = self.inner.get(name).ok_or_else(|| { |
111 | ExpandError::BindingError(format!("could not find binding `{}`", name)) | 116 | ExpandError::BindingError(format!("could not find binding `{}`", name)) |
112 | })?; | 117 | })?; |
113 | for &idx in nesting.iter() { | 118 | for &idx in nesting.iter() { |
114 | b = match b { | 119 | b = match b { |
115 | Binding::Simple(_) => break, | 120 | Binding::Fragment(_) => break, |
116 | Binding::Nested(bs) => bs.get(idx).ok_or_else(|| { | 121 | Binding::Nested(bs) => bs.get(idx).ok_or_else(|| { |
117 | ExpandError::BindingError(format!("could not find nested binding `{}`", name)) | 122 | ExpandError::BindingError(format!("could not find nested binding `{}`", name)) |
118 | })?, | 123 | })?, |
@@ -125,7 +130,7 @@ impl Bindings { | |||
125 | }; | 130 | }; |
126 | } | 131 | } |
127 | match b { | 132 | match b { |
128 | Binding::Simple(it) => Ok(it), | 133 | Binding::Fragment(it) => Ok(it), |
129 | Binding::Nested(_) => Err(ExpandError::BindingError(format!( | 134 | Binding::Nested(_) => Err(ExpandError::BindingError(format!( |
130 | "expected simple binding, found nested binding `{}`", | 135 | "expected simple binding, found nested binding `{}`", |
131 | name | 136 | name |
@@ -195,8 +200,8 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, | |||
195 | crate::Leaf::Var(crate::Var { text, kind }) => { | 200 | crate::Leaf::Var(crate::Var { text, kind }) => { |
196 | let kind = kind.as_ref().ok_or(ExpandError::UnexpectedToken)?; | 201 | let kind = kind.as_ref().ok_or(ExpandError::UnexpectedToken)?; |
197 | match match_meta_var(kind.as_str(), input)? { | 202 | match match_meta_var(kind.as_str(), input)? { |
198 | Some(tt) => { | 203 | Some(fragment) => { |
199 | res.inner.insert(text.clone(), Binding::Simple(tt)); | 204 | res.inner.insert(text.clone(), Binding::Fragment(fragment)); |
200 | } | 205 | } |
201 | None => res.push_optional(text), | 206 | None => res.push_optional(text), |
202 | } | 207 | } |
@@ -292,7 +297,7 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, | |||
292 | Ok(res) | 297 | Ok(res) |
293 | } | 298 | } |
294 | 299 | ||
295 | fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<tt::TokenTree>, ExpandError> { | 300 | fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<Fragment>, ExpandError> { |
296 | let fragment = match kind { | 301 | let fragment = match kind { |
297 | "path" => Path, | 302 | "path" => Path, |
298 | "expr" => Expr, | 303 | "expr" => Expr, |
@@ -303,7 +308,7 @@ fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<tt::TokenTr | |||
303 | "meta" => MetaItem, | 308 | "meta" => MetaItem, |
304 | "item" => Item, | 309 | "item" => Item, |
305 | _ => { | 310 | _ => { |
306 | let binding = match kind { | 311 | let tt = match kind { |
307 | "ident" => { | 312 | "ident" => { |
308 | let ident = input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone(); | 313 | let ident = input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone(); |
309 | tt::Leaf::from(ident).into() | 314 | tt::Leaf::from(ident).into() |
@@ -321,11 +326,12 @@ fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<tt::TokenTr | |||
321 | }, | 326 | }, |
322 | _ => return Err(ExpandError::UnexpectedToken), | 327 | _ => return Err(ExpandError::UnexpectedToken), |
323 | }; | 328 | }; |
324 | return Ok(Some(binding)); | 329 | return Ok(Some(Fragment::Tokens(tt))); |
325 | } | 330 | } |
326 | }; | 331 | }; |
327 | let binding = input.eat_fragment(fragment).ok_or(ExpandError::UnexpectedToken)?; | 332 | let tt = input.eat_fragment(fragment).ok_or(ExpandError::UnexpectedToken)?; |
328 | Ok(Some(binding)) | 333 | let fragment = if kind == "expr" { Fragment::Ast(tt) } else { Fragment::Tokens(tt) }; |
334 | Ok(Some(fragment)) | ||
329 | } | 335 | } |
330 | 336 | ||
331 | #[derive(Debug)] | 337 | #[derive(Debug)] |
@@ -339,45 +345,20 @@ fn expand_subtree( | |||
339 | template: &crate::Subtree, | 345 | template: &crate::Subtree, |
340 | ctx: &mut ExpandCtx, | 346 | ctx: &mut ExpandCtx, |
341 | ) -> Result<tt::Subtree, ExpandError> { | 347 | ) -> Result<tt::Subtree, ExpandError> { |
342 | let token_trees = template | 348 | let mut buf: Vec<tt::TokenTree> = Vec::new(); |
343 | .token_trees | 349 | for tt in template.token_trees.iter() { |
344 | .iter() | 350 | let tt = expand_tt(tt, ctx)?; |
345 | .map(|it| expand_tt(it, ctx)) | 351 | push_fragment(&mut buf, tt); |
346 | .filter(|it| { | ||
347 | // Filter empty subtree | ||
348 | if let Ok(tt::TokenTree::Subtree(subtree)) = it { | ||
349 | subtree.delimiter != tt::Delimiter::None || !subtree.token_trees.is_empty() | ||
350 | } else { | ||
351 | true | ||
352 | } | ||
353 | }) | ||
354 | .collect::<Result<Vec<_>, ExpandError>>()?; | ||
355 | |||
356 | Ok(tt::Subtree { token_trees, delimiter: template.delimiter }) | ||
357 | } | ||
358 | |||
359 | /// Reduce single token subtree to single token | ||
360 | /// In `tt` matcher case, all tt tokens will be braced by a Delimiter::None | ||
361 | /// which makes all sort of problems. | ||
362 | fn reduce_single_token(mut subtree: tt::Subtree) -> tt::TokenTree { | ||
363 | if subtree.delimiter != tt::Delimiter::None || subtree.token_trees.len() != 1 { | ||
364 | return subtree.into(); | ||
365 | } | 352 | } |
366 | 353 | ||
367 | match subtree.token_trees.pop().unwrap() { | 354 | Ok(tt::Subtree { delimiter: template.delimiter, token_trees: buf }) |
368 | tt::TokenTree::Subtree(subtree) => reduce_single_token(subtree), | ||
369 | tt::TokenTree::Leaf(token) => token.into(), | ||
370 | } | ||
371 | } | 355 | } |
372 | 356 | ||
373 | fn expand_tt( | 357 | fn expand_tt(template: &crate::TokenTree, ctx: &mut ExpandCtx) -> Result<Fragment, ExpandError> { |
374 | template: &crate::TokenTree, | ||
375 | ctx: &mut ExpandCtx, | ||
376 | ) -> Result<tt::TokenTree, ExpandError> { | ||
377 | let res: tt::TokenTree = match template { | 358 | let res: tt::TokenTree = match template { |
378 | crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(), | 359 | crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(), |
379 | crate::TokenTree::Repeat(repeat) => { | 360 | crate::TokenTree::Repeat(repeat) => { |
380 | let mut token_trees: Vec<tt::TokenTree> = Vec::new(); | 361 | let mut buf: Vec<tt::TokenTree> = Vec::new(); |
381 | ctx.nesting.push(0); | 362 | ctx.nesting.push(0); |
382 | // Dirty hack to make macro-expansion terminate. | 363 | // Dirty hack to make macro-expansion terminate. |
383 | // This should be replaced by a propper macro-by-example implementation | 364 | // This should be replaced by a propper macro-by-example implementation |
@@ -418,23 +399,23 @@ fn expand_tt( | |||
418 | 399 | ||
419 | let idx = ctx.nesting.pop().unwrap(); | 400 | let idx = ctx.nesting.pop().unwrap(); |
420 | ctx.nesting.push(idx + 1); | 401 | ctx.nesting.push(idx + 1); |
421 | token_trees.push(reduce_single_token(t)); | 402 | push_subtree(&mut buf, t); |
422 | 403 | ||
423 | if let Some(ref sep) = repeat.separator { | 404 | if let Some(ref sep) = repeat.separator { |
424 | match sep { | 405 | match sep { |
425 | crate::Separator::Ident(ident) => { | 406 | crate::Separator::Ident(ident) => { |
426 | has_seps = 1; | 407 | has_seps = 1; |
427 | token_trees.push(tt::Leaf::from(ident.clone()).into()); | 408 | buf.push(tt::Leaf::from(ident.clone()).into()); |
428 | } | 409 | } |
429 | crate::Separator::Literal(lit) => { | 410 | crate::Separator::Literal(lit) => { |
430 | has_seps = 1; | 411 | has_seps = 1; |
431 | token_trees.push(tt::Leaf::from(lit.clone()).into()); | 412 | buf.push(tt::Leaf::from(lit.clone()).into()); |
432 | } | 413 | } |
433 | 414 | ||
434 | crate::Separator::Puncts(puncts) => { | 415 | crate::Separator::Puncts(puncts) => { |
435 | has_seps = puncts.len(); | 416 | has_seps = puncts.len(); |
436 | for punct in puncts { | 417 | for punct in puncts { |
437 | token_trees.push(tt::Leaf::from(*punct).into()); | 418 | buf.push(tt::Leaf::from(*punct).into()); |
438 | } | 419 | } |
439 | } | 420 | } |
440 | } | 421 | } |
@@ -450,16 +431,16 @@ fn expand_tt( | |||
450 | 431 | ||
451 | ctx.nesting.pop().unwrap(); | 432 | ctx.nesting.pop().unwrap(); |
452 | for _ in 0..has_seps { | 433 | for _ in 0..has_seps { |
453 | token_trees.pop(); | 434 | buf.pop(); |
454 | } | 435 | } |
455 | 436 | ||
456 | if crate::RepeatKind::OneOrMore == repeat.kind && counter == 0 { | 437 | if crate::RepeatKind::OneOrMore == repeat.kind && counter == 0 { |
457 | return Err(ExpandError::UnexpectedToken); | 438 | return Err(ExpandError::UnexpectedToken); |
458 | } | 439 | } |
459 | 440 | ||
460 | // Check if it is a singel token subtree without any delimiter | 441 | // Check if it is a single token subtree without any delimiter |
461 | // e.g {Delimiter:None> ['>'] /Delimiter:None>} | 442 | // e.g {Delimiter:None> ['>'] /Delimiter:None>} |
462 | reduce_single_token(tt::Subtree { token_trees, delimiter: tt::Delimiter::None }) | 443 | tt::Subtree { delimiter: tt::Delimiter::None, token_trees: buf }.into() |
463 | } | 444 | } |
464 | crate::TokenTree::Leaf(leaf) => match leaf { | 445 | crate::TokenTree::Leaf(leaf) => match leaf { |
465 | crate::Leaf::Ident(ident) => { | 446 | crate::Leaf::Ident(ident) => { |
@@ -500,20 +481,15 @@ fn expand_tt( | |||
500 | } | 481 | } |
501 | .into() | 482 | .into() |
502 | } else { | 483 | } else { |
503 | let tkn = ctx.bindings.get(&v.text, &ctx.nesting)?.clone(); | 484 | let fragment = ctx.bindings.get(&v.text, &ctx.nesting)?.clone(); |
504 | ctx.var_expanded = true; | 485 | ctx.var_expanded = true; |
505 | 486 | return Ok(fragment); | |
506 | if let tt::TokenTree::Subtree(subtree) = tkn { | ||
507 | reduce_single_token(subtree) | ||
508 | } else { | ||
509 | tkn | ||
510 | } | ||
511 | } | 487 | } |
512 | } | 488 | } |
513 | crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal { text: l.text.clone() }).into(), | 489 | crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal { text: l.text.clone() }).into(), |
514 | }, | 490 | }, |
515 | }; | 491 | }; |
516 | Ok(res) | 492 | Ok(Fragment::Tokens(res)) |
517 | } | 493 | } |
518 | 494 | ||
519 | #[cfg(test)] | 495 | #[cfg(test)] |
@@ -586,3 +562,17 @@ mod tests { | |||
586 | expand_rule(&rules.rules[0], &invocation_tt) | 562 | expand_rule(&rules.rules[0], &invocation_tt) |
587 | } | 563 | } |
588 | } | 564 | } |
565 | |||
566 | fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) { | ||
567 | match fragment { | ||
568 | Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt), | ||
569 | Fragment::Tokens(tt) | Fragment::Ast(tt) => buf.push(tt), | ||
570 | } | ||
571 | } | ||
572 | |||
573 | fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) { | ||
574 | match tt.delimiter { | ||
575 | tt::Delimiter::None => buf.extend(tt.token_trees), | ||
576 | _ => buf.push(tt.into()), | ||
577 | } | ||
578 | } | ||
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index a380b1cfd..2d035307b 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -46,31 +46,19 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke | |||
46 | // * TraitItems(SmallVec<[ast::TraitItem; 1]>) | 46 | // * TraitItems(SmallVec<[ast::TraitItem; 1]>) |
47 | // * ImplItems(SmallVec<[ast::ImplItem; 1]>) | 47 | // * ImplItems(SmallVec<[ast::ImplItem; 1]>) |
48 | // * ForeignItems(SmallVec<[ast::ForeignItem; 1]> | 48 | // * ForeignItems(SmallVec<[ast::ForeignItem; 1]> |
49 | // | ||
50 | // | ||
51 | |||
52 | fn token_tree_to_syntax_node<F>(tt: &tt::Subtree, f: F) -> Result<Parse<SyntaxNode>, ExpandError> | ||
53 | where | ||
54 | F: Fn(&mut dyn ra_parser::TokenSource, &mut dyn ra_parser::TreeSink), | ||
55 | { | ||
56 | let tokens = [tt.clone().into()]; | ||
57 | let buffer = TokenBuffer::new(&tokens); | ||
58 | let mut token_source = SubtreeTokenSource::new(&buffer); | ||
59 | let mut tree_sink = TtTreeSink::new(buffer.begin()); | ||
60 | f(&mut token_source, &mut tree_sink); | ||
61 | if tree_sink.roots.len() != 1 { | ||
62 | return Err(ExpandError::ConversionError); | ||
63 | } | ||
64 | //FIXME: would be cool to report errors | ||
65 | let parse = tree_sink.inner.finish(); | ||
66 | Ok(parse) | ||
67 | } | ||
68 | 49 | ||
69 | fn fragment_to_syntax_node( | 50 | fn fragment_to_syntax_node( |
70 | tt: &tt::Subtree, | 51 | tt: &tt::Subtree, |
71 | fragment_kind: FragmentKind, | 52 | fragment_kind: FragmentKind, |
72 | ) -> Result<Parse<SyntaxNode>, ExpandError> { | 53 | ) -> Result<Parse<SyntaxNode>, ExpandError> { |
73 | let tokens = [tt.clone().into()]; | 54 | let tmp; |
55 | let tokens = match tt { | ||
56 | tt::Subtree { delimiter: tt::Delimiter::None, token_trees } => token_trees.as_slice(), | ||
57 | _ => { | ||
58 | tmp = [tt.clone().into()]; | ||
59 | &tmp[..] | ||
60 | } | ||
61 | }; | ||
74 | let buffer = TokenBuffer::new(&tokens); | 62 | let buffer = TokenBuffer::new(&tokens); |
75 | let mut token_source = SubtreeTokenSource::new(&buffer); | 63 | let mut token_source = SubtreeTokenSource::new(&buffer); |
76 | let mut tree_sink = TtTreeSink::new(buffer.begin()); | 64 | let mut tree_sink = TtTreeSink::new(buffer.begin()); |
@@ -108,17 +96,11 @@ pub fn token_tree_to_macro_stmts(tt: &tt::Subtree) -> Result<Parse<ast::MacroStm | |||
108 | } | 96 | } |
109 | 97 | ||
110 | /// Parses the token tree (result of macro expansion) as a sequence of items | 98 | /// Parses the token tree (result of macro expansion) as a sequence of items |
111 | pub fn token_tree_to_macro_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> { | 99 | pub fn token_tree_to_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> { |
112 | let parse = fragment_to_syntax_node(tt, Items)?; | 100 | let parse = fragment_to_syntax_node(tt, Items)?; |
113 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 101 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
114 | } | 102 | } |
115 | 103 | ||
116 | /// Parses the token tree (result of macro expansion) as a sequence of items | ||
117 | pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> Parse<ast::SourceFile> { | ||
118 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse).unwrap(); | ||
119 | parse.cast().unwrap() | ||
120 | } | ||
121 | |||
122 | impl TokenMap { | 104 | impl TokenMap { |
123 | pub fn relative_range_of(&self, tt: tt::TokenId) -> Option<TextRange> { | 105 | pub fn relative_range_of(&self, tt: tt::TokenId) -> Option<TextRange> { |
124 | let idx = tt.0 as usize; | 106 | let idx = tt.0 as usize; |
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 034ea639b..312fa4626 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | use ra_syntax::{ast, AstNode, NodeOrToken}; | 1 | use ra_syntax::{ast, AstNode, NodeOrToken}; |
2 | use test_utils::assert_eq_text; | ||
2 | 3 | ||
3 | use super::*; | 4 | use super::*; |
4 | 5 | ||
@@ -69,7 +70,7 @@ pub(crate) fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree { | |||
69 | 70 | ||
70 | pub(crate) fn expand_to_items(rules: &MacroRules, invocation: &str) -> ast::MacroItems { | 71 | pub(crate) fn expand_to_items(rules: &MacroRules, invocation: &str) -> ast::MacroItems { |
71 | let expanded = expand(rules, invocation); | 72 | let expanded = expand(rules, invocation); |
72 | token_tree_to_macro_items(&expanded).unwrap().tree() | 73 | token_tree_to_items(&expanded).unwrap().tree() |
73 | } | 74 | } |
74 | 75 | ||
75 | #[allow(unused)] | 76 | #[allow(unused)] |
@@ -152,11 +153,10 @@ pub(crate) fn assert_expansion( | |||
152 | 153 | ||
153 | // wrap the given text to a macro call | 154 | // wrap the given text to a macro call |
154 | let expected = text_to_tokentree(&expected); | 155 | let expected = text_to_tokentree(&expected); |
155 | |||
156 | let (expanded_tree, expected_tree) = match kind { | 156 | let (expanded_tree, expected_tree) = match kind { |
157 | MacroKind::Items => { | 157 | MacroKind::Items => { |
158 | let expanded_tree = token_tree_to_macro_items(&expanded).unwrap().tree(); | 158 | let expanded_tree = token_tree_to_items(&expanded).unwrap().tree(); |
159 | let expected_tree = token_tree_to_macro_items(&expected).unwrap().tree(); | 159 | let expected_tree = token_tree_to_items(&expected).unwrap().tree(); |
160 | 160 | ||
161 | ( | 161 | ( |
162 | debug_dump_ignore_spaces(expanded_tree.syntax()).trim().to_string(), | 162 | debug_dump_ignore_spaces(expanded_tree.syntax()).trim().to_string(), |
@@ -178,7 +178,7 @@ pub(crate) fn assert_expansion( | |||
178 | let expected_tree = expected_tree.replace("C_C__C", "$crate"); | 178 | let expected_tree = expected_tree.replace("C_C__C", "$crate"); |
179 | assert_eq!( | 179 | assert_eq!( |
180 | expanded_tree, expected_tree, | 180 | expanded_tree, expected_tree, |
181 | "left => {}\nright => {}", | 181 | "\nleft:\n{}\nright:\n{}", |
182 | expanded_tree, expected_tree, | 182 | expanded_tree, expected_tree, |
183 | ); | 183 | ); |
184 | 184 | ||
@@ -410,7 +410,7 @@ fn test_expand_to_item_list() { | |||
410 | ", | 410 | ", |
411 | ); | 411 | ); |
412 | let expansion = expand(&rules, "structs!(Foo, Bar);"); | 412 | let expansion = expand(&rules, "structs!(Foo, Bar);"); |
413 | let tree = token_tree_to_macro_items(&expansion).unwrap().tree(); | 413 | let tree = token_tree_to_items(&expansion).unwrap().tree(); |
414 | assert_eq!( | 414 | assert_eq!( |
415 | format!("{:#?}", tree.syntax()).trim(), | 415 | format!("{:#?}", tree.syntax()).trim(), |
416 | r#" | 416 | r#" |
@@ -667,9 +667,9 @@ fn test_expr_order() { | |||
667 | } | 667 | } |
668 | "#, | 668 | "#, |
669 | ); | 669 | ); |
670 | 670 | let dump = format!("{:#?}", expand_to_items(&rules, "foo! { 1 + 1 }").syntax()); | |
671 | assert_eq!( | 671 | assert_eq_text!( |
672 | format!("{:#?}", expand_to_items(&rules, "foo! { 1 + 1 }").syntax()).trim(), | 672 | dump.trim(), |
673 | r#"MACRO_ITEMS@[0; 15) | 673 | r#"MACRO_ITEMS@[0; 15) |
674 | FN_DEF@[0; 15) | 674 | FN_DEF@[0; 15) |
675 | FN_KW@[0; 2) "fn" | 675 | FN_KW@[0; 2) "fn" |