|
1 |
| -use ra_syntax::{ast, AstNode, NodeOrToken}; |
| 1 | +use ra_syntax::{ast, AstNode, NodeOrToken, WalkEvent}; |
2 | 2 | use test_utils::assert_eq_text;
|
3 | 3 |
|
4 | 4 | use super::*;
|
@@ -78,159 +78,57 @@ macro_rules! impl_froms {
|
78 | 78 | impl_froms!(TokenTree: Leaf, Subtree);
|
79 | 79 | "#;
|
80 | 80 |
|
81 |
| - let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); |
82 |
| - let macro_definition = |
83 |
| - source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |
84 |
| - |
85 |
| - let source_file = ast::SourceFile::parse(macro_invocation).ok().unwrap(); |
86 |
| - let macro_invocation = |
87 |
| - source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |
88 |
| - |
89 |
| - let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()).unwrap(); |
90 |
| - let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); |
91 |
| - let rules = crate::MacroRules::parse(&definition_tt).unwrap(); |
92 |
| - let expansion = rules.expand(&invocation_tt).unwrap(); |
| 81 | + let rules = create_rules(macro_definition); |
| 82 | + let expansion = expand(&rules, macro_invocation); |
93 | 83 | assert_eq!(
|
94 | 84 | expansion.to_string(),
|
95 | 85 | "impl From <Leaf > for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree ::Leaf (it)}} \
|
96 | 86 | impl From <Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree ::Subtree (it)}}"
|
97 | 87 | )
|
98 | 88 | }
|
99 | 89 |
|
100 |
| -pub(crate) fn create_rules(macro_definition: &str) -> MacroRules { |
101 |
| - let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); |
102 |
| - let macro_definition = |
103 |
| - source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |
104 |
| - |
105 |
| - let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()).unwrap(); |
106 |
| - crate::MacroRules::parse(&definition_tt).unwrap() |
107 |
| -} |
108 |
| - |
109 |
| -pub(crate) fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree { |
110 |
| - let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); |
111 |
| - let macro_invocation = |
112 |
| - source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |
113 |
| - |
114 |
| - let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); |
115 |
| - |
116 |
| - rules.expand(&invocation_tt).unwrap() |
117 |
| -} |
118 |
| - |
119 |
| -pub(crate) fn expand_to_items(rules: &MacroRules, invocation: &str) -> ast::MacroItems { |
120 |
| - let expanded = expand(rules, invocation); |
121 |
| - token_tree_to_items(&expanded).unwrap().tree() |
122 |
| -} |
123 |
| - |
124 |
| -#[allow(unused)] |
125 |
| -pub(crate) fn expand_to_stmts(rules: &MacroRules, invocation: &str) -> ast::MacroStmts { |
126 |
| - let expanded = expand(rules, invocation); |
127 |
| - token_tree_to_macro_stmts(&expanded).unwrap().tree() |
128 |
| -} |
129 |
| - |
130 |
| -pub(crate) fn expand_to_expr(rules: &MacroRules, invocation: &str) -> ast::Expr { |
131 |
| - let expanded = expand(rules, invocation); |
132 |
| - token_tree_to_expr(&expanded).unwrap().tree() |
133 |
| -} |
134 |
| - |
135 |
| -pub(crate) fn text_to_tokentree(text: &str) -> tt::Subtree { |
136 |
| - // wrap the given text to a macro call |
137 |
| - let wrapped = format!("wrap_macro!( {} )", text); |
138 |
| - let wrapped = ast::SourceFile::parse(&wrapped); |
139 |
| - let wrapped = wrapped.tree().syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
140 |
| - let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0; |
141 |
| - wrapped.delimiter = tt::Delimiter::None; |
142 |
| - |
143 |
| - wrapped |
144 |
| -} |
145 |
| - |
146 |
| -pub(crate) enum MacroKind { |
147 |
| - Items, |
148 |
| - Stmts, |
149 |
| -} |
150 |
| - |
151 |
| -use ra_syntax::WalkEvent; |
152 |
| - |
153 |
| -pub fn debug_dump_ignore_spaces(node: &ra_syntax::SyntaxNode) -> String { |
154 |
| - use std::fmt::Write; |
155 |
| - |
156 |
| - let mut level = 0; |
157 |
| - let mut buf = String::new(); |
158 |
| - macro_rules! indent { |
159 |
| - () => { |
160 |
| - for _ in 0..level { |
161 |
| - buf.push_str(" "); |
162 |
| - } |
163 |
| - }; |
164 |
| - } |
165 |
| - |
166 |
| - for event in node.preorder_with_tokens() { |
167 |
| - match event { |
168 |
| - WalkEvent::Enter(element) => { |
169 |
| - match element { |
170 |
| - NodeOrToken::Node(node) => { |
171 |
| - indent!(); |
172 |
| - writeln!(buf, "{:?}", node.kind()).unwrap(); |
173 |
| - } |
174 |
| - NodeOrToken::Token(token) => match token.kind() { |
175 |
| - ra_syntax::SyntaxKind::WHITESPACE => {} |
176 |
| - _ => { |
177 |
| - indent!(); |
178 |
| - writeln!(buf, "{:?}", token.kind()).unwrap(); |
179 |
| - } |
180 |
| - }, |
181 |
| - } |
182 |
| - level += 1; |
| 90 | +#[test] |
| 91 | +fn test_expr_order() { |
| 92 | + let rules = create_rules( |
| 93 | + r#" |
| 94 | + macro_rules! foo { |
| 95 | + ($ i:expr) => { |
| 96 | + fn bar() { $ i * 2; } |
183 | 97 | }
|
184 |
| - WalkEvent::Leave(_) => level -= 1, |
185 | 98 | }
|
186 |
| - } |
187 |
| - |
188 |
| - buf |
189 |
| -} |
190 |
| - |
191 |
| -pub(crate) fn assert_expansion( |
192 |
| - kind: MacroKind, |
193 |
| - rules: &MacroRules, |
194 |
| - invocation: &str, |
195 |
| - expected: &str, |
196 |
| -) -> tt::Subtree { |
197 |
| - let expanded = expand(rules, invocation); |
198 |
| - assert_eq!(expanded.to_string(), expected); |
199 |
| - |
200 |
| - let expected = expected.replace("$crate", "C_C__C"); |
201 |
| - |
202 |
| - // wrap the given text to a macro call |
203 |
| - let expected = text_to_tokentree(&expected); |
204 |
| - let (expanded_tree, expected_tree) = match kind { |
205 |
| - MacroKind::Items => { |
206 |
| - let expanded_tree = token_tree_to_items(&expanded).unwrap().tree(); |
207 |
| - let expected_tree = token_tree_to_items(&expected).unwrap().tree(); |
208 |
| - |
209 |
| - ( |
210 |
| - debug_dump_ignore_spaces(expanded_tree.syntax()).trim().to_string(), |
211 |
| - debug_dump_ignore_spaces(expected_tree.syntax()).trim().to_string(), |
212 |
| - ) |
213 |
| - } |
214 |
| - |
215 |
| - MacroKind::Stmts => { |
216 |
| - let expanded_tree = token_tree_to_macro_stmts(&expanded).unwrap().tree(); |
217 |
| - let expected_tree = token_tree_to_macro_stmts(&expected).unwrap().tree(); |
218 |
| - |
219 |
| - ( |
220 |
| - debug_dump_ignore_spaces(expanded_tree.syntax()).trim().to_string(), |
221 |
| - debug_dump_ignore_spaces(expected_tree.syntax()).trim().to_string(), |
222 |
| - ) |
223 |
| - } |
224 |
| - }; |
225 |
| - |
226 |
| - let expected_tree = expected_tree.replace("C_C__C", "$crate"); |
227 |
| - assert_eq!( |
228 |
| - expanded_tree, expected_tree, |
229 |
| - "\nleft:\n{}\nright:\n{}", |
230 |
| - expanded_tree, expected_tree, |
| 99 | +"#, |
231 | 100 | );
|
| 101 | + let expanded = expand(&rules, "foo! { 1 + 1}"); |
| 102 | + let tree = token_tree_to_items(&expanded).unwrap().tree(); |
232 | 103 |
|
233 |
| - expanded |
| 104 | + let dump = format!("{:#?}", tree.syntax()); |
| 105 | + assert_eq_text!( |
| 106 | + dump.trim(), |
| 107 | + r#"MACRO_ITEMS@[0; 15) |
| 108 | + FN_DEF@[0; 15) |
| 109 | + FN_KW@[0; 2) "fn" |
| 110 | + NAME@[2; 5) |
| 111 | + IDENT@[2; 5) "bar" |
| 112 | + PARAM_LIST@[5; 7) |
| 113 | + L_PAREN@[5; 6) "(" |
| 114 | + R_PAREN@[6; 7) ")" |
| 115 | + BLOCK_EXPR@[7; 15) |
| 116 | + BLOCK@[7; 15) |
| 117 | + L_CURLY@[7; 8) "{" |
| 118 | + EXPR_STMT@[8; 14) |
| 119 | + BIN_EXPR@[8; 13) |
| 120 | + BIN_EXPR@[8; 11) |
| 121 | + LITERAL@[8; 9) |
| 122 | + INT_NUMBER@[8; 9) "1" |
| 123 | + PLUS@[9; 10) "+" |
| 124 | + LITERAL@[10; 11) |
| 125 | + INT_NUMBER@[10; 11) "1" |
| 126 | + STAR@[11; 12) "*" |
| 127 | + LITERAL@[12; 13) |
| 128 | + INT_NUMBER@[12; 13) "2" |
| 129 | + SEMI@[13; 14) ";" |
| 130 | + R_CURLY@[14; 15) "}""#, |
| 131 | + ); |
234 | 132 | }
|
235 | 133 |
|
236 | 134 | #[test]
|
@@ -704,47 +602,6 @@ fn test_expr() {
|
704 | 602 | );
|
705 | 603 | }
|
706 | 604 |
|
707 |
| -#[test] |
708 |
| -fn test_expr_order() { |
709 |
| - let rules = create_rules( |
710 |
| - r#" |
711 |
| - macro_rules! foo { |
712 |
| - ($ i:expr) => { |
713 |
| - fn bar() { $ i * 2; } |
714 |
| - } |
715 |
| - } |
716 |
| -"#, |
717 |
| - ); |
718 |
| - let dump = format!("{:#?}", expand_to_items(&rules, "foo! { 1 + 1 }").syntax()); |
719 |
| - assert_eq_text!( |
720 |
| - dump.trim(), |
721 |
| - r#"MACRO_ITEMS@[0; 15) |
722 |
| - FN_DEF@[0; 15) |
723 |
| - FN_KW@[0; 2) "fn" |
724 |
| - NAME@[2; 5) |
725 |
| - IDENT@[2; 5) "bar" |
726 |
| - PARAM_LIST@[5; 7) |
727 |
| - L_PAREN@[5; 6) "(" |
728 |
| - R_PAREN@[6; 7) ")" |
729 |
| - BLOCK_EXPR@[7; 15) |
730 |
| - BLOCK@[7; 15) |
731 |
| - L_CURLY@[7; 8) "{" |
732 |
| - EXPR_STMT@[8; 14) |
733 |
| - BIN_EXPR@[8; 13) |
734 |
| - BIN_EXPR@[8; 11) |
735 |
| - LITERAL@[8; 9) |
736 |
| - INT_NUMBER@[8; 9) "1" |
737 |
| - PLUS@[9; 10) "+" |
738 |
| - LITERAL@[10; 11) |
739 |
| - INT_NUMBER@[10; 11) "1" |
740 |
| - STAR@[11; 12) "*" |
741 |
| - LITERAL@[12; 13) |
742 |
| - INT_NUMBER@[12; 13) "2" |
743 |
| - SEMI@[13; 14) ";" |
744 |
| - R_CURLY@[14; 15) "}""#, |
745 |
| - ); |
746 |
| -} |
747 |
| - |
748 | 605 | #[test]
|
749 | 606 | fn test_last_expr() {
|
750 | 607 | let rules = create_rules(
|
@@ -1061,8 +918,11 @@ fn test_vec() {
|
1061 | 918 | r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#,
|
1062 | 919 | );
|
1063 | 920 |
|
| 921 | + let expansion = expand(&rules, r#"vec![1u32,2];"#); |
| 922 | + let tree = token_tree_to_expr(&expansion).unwrap().tree(); |
| 923 | + |
1064 | 924 | assert_eq!(
|
1065 |
| - format!("{:#?}", expand_to_expr(&rules, r#"vec![1u32,2];"#).syntax()).trim(), |
| 925 | + format!("{:#?}", tree.syntax()).trim(), |
1066 | 926 | r#"BLOCK_EXPR@[0; 45)
|
1067 | 927 | BLOCK@[0; 45)
|
1068 | 928 | L_CURLY@[0; 1) "{"
|
@@ -1502,3 +1362,117 @@ macro_rules! delegate_impl {
|
1502 | 1362 |
|
1503 | 1363 | assert_expansion(MacroKind::Items, &rules, r#"delegate_impl ! {[G , & 'a mut G , deref] pub trait Data : GraphBase {@ section type type NodeWeight ;}}"#, "impl <> Data for & \'a mut G where G : Data {}");
|
1504 | 1364 | }
|
| 1365 | + |
| 1366 | +pub(crate) fn create_rules(macro_definition: &str) -> MacroRules { |
| 1367 | + let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); |
| 1368 | + let macro_definition = |
| 1369 | + source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |
| 1370 | + |
| 1371 | + let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()).unwrap(); |
| 1372 | + crate::MacroRules::parse(&definition_tt).unwrap() |
| 1373 | +} |
| 1374 | + |
| 1375 | +pub(crate) fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree { |
| 1376 | + let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); |
| 1377 | + let macro_invocation = |
| 1378 | + source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |
| 1379 | + |
| 1380 | + let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); |
| 1381 | + |
| 1382 | + rules.expand(&invocation_tt).unwrap() |
| 1383 | +} |
| 1384 | + |
| 1385 | +pub(crate) enum MacroKind { |
| 1386 | + Items, |
| 1387 | + Stmts, |
| 1388 | +} |
| 1389 | + |
| 1390 | +pub(crate) fn assert_expansion( |
| 1391 | + kind: MacroKind, |
| 1392 | + rules: &MacroRules, |
| 1393 | + invocation: &str, |
| 1394 | + expected: &str, |
| 1395 | +) -> tt::Subtree { |
| 1396 | + let expanded = expand(rules, invocation); |
| 1397 | + assert_eq!(expanded.to_string(), expected); |
| 1398 | + |
| 1399 | + let expected = expected.replace("$crate", "C_C__C"); |
| 1400 | + |
| 1401 | + // wrap the given text to a macro call |
| 1402 | + let expected = { |
| 1403 | + let wrapped = format!("wrap_macro!( {} )", expected); |
| 1404 | + let wrapped = ast::SourceFile::parse(&wrapped); |
| 1405 | + let wrapped = wrapped.tree().syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
| 1406 | + let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0; |
| 1407 | + wrapped.delimiter = tt::Delimiter::None; |
| 1408 | + wrapped |
| 1409 | + }; |
| 1410 | + let (expanded_tree, expected_tree) = match kind { |
| 1411 | + MacroKind::Items => { |
| 1412 | + let expanded_tree = token_tree_to_items(&expanded).unwrap().tree(); |
| 1413 | + let expected_tree = token_tree_to_items(&expected).unwrap().tree(); |
| 1414 | + |
| 1415 | + ( |
| 1416 | + debug_dump_ignore_spaces(expanded_tree.syntax()).trim().to_string(), |
| 1417 | + debug_dump_ignore_spaces(expected_tree.syntax()).trim().to_string(), |
| 1418 | + ) |
| 1419 | + } |
| 1420 | + |
| 1421 | + MacroKind::Stmts => { |
| 1422 | + let expanded_tree = token_tree_to_macro_stmts(&expanded).unwrap().tree(); |
| 1423 | + let expected_tree = token_tree_to_macro_stmts(&expected).unwrap().tree(); |
| 1424 | + |
| 1425 | + ( |
| 1426 | + debug_dump_ignore_spaces(expanded_tree.syntax()).trim().to_string(), |
| 1427 | + debug_dump_ignore_spaces(expected_tree.syntax()).trim().to_string(), |
| 1428 | + ) |
| 1429 | + } |
| 1430 | + }; |
| 1431 | + |
| 1432 | + let expected_tree = expected_tree.replace("C_C__C", "$crate"); |
| 1433 | + assert_eq!( |
| 1434 | + expanded_tree, expected_tree, |
| 1435 | + "\nleft:\n{}\nright:\n{}", |
| 1436 | + expanded_tree, expected_tree, |
| 1437 | + ); |
| 1438 | + |
| 1439 | + expanded |
| 1440 | +} |
| 1441 | + |
| 1442 | +pub fn debug_dump_ignore_spaces(node: &ra_syntax::SyntaxNode) -> String { |
| 1443 | + use std::fmt::Write; |
| 1444 | + |
| 1445 | + let mut level = 0; |
| 1446 | + let mut buf = String::new(); |
| 1447 | + macro_rules! indent { |
| 1448 | + () => { |
| 1449 | + for _ in 0..level { |
| 1450 | + buf.push_str(" "); |
| 1451 | + } |
| 1452 | + }; |
| 1453 | + } |
| 1454 | + |
| 1455 | + for event in node.preorder_with_tokens() { |
| 1456 | + match event { |
| 1457 | + WalkEvent::Enter(element) => { |
| 1458 | + match element { |
| 1459 | + NodeOrToken::Node(node) => { |
| 1460 | + indent!(); |
| 1461 | + writeln!(buf, "{:?}", node.kind()).unwrap(); |
| 1462 | + } |
| 1463 | + NodeOrToken::Token(token) => match token.kind() { |
| 1464 | + ra_syntax::SyntaxKind::WHITESPACE => {} |
| 1465 | + _ => { |
| 1466 | + indent!(); |
| 1467 | + writeln!(buf, "{:?}", token.kind()).unwrap(); |
| 1468 | + } |
| 1469 | + }, |
| 1470 | + } |
| 1471 | + level += 1; |
| 1472 | + } |
| 1473 | + WalkEvent::Leave(_) => level -= 1, |
| 1474 | + } |
| 1475 | + } |
| 1476 | + |
| 1477 | + buf |
| 1478 | +} |
0 commit comments