aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/expand_macro.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/expand_macro.rs')
-rw-r--r--crates/ra_ide_api/src/expand_macro.rs60
1 files changed, 56 insertions, 4 deletions
diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs
index 7dbf33a16..0b540b8cd 100644
--- a/crates/ra_ide_api/src/expand_macro.rs
+++ b/crates/ra_ide_api/src/expand_macro.rs
@@ -40,16 +40,23 @@ fn expand_macro_recur(
40 let analyzer = hir::SourceAnalyzer::new(db, source, None); 40 let analyzer = hir::SourceAnalyzer::new(db, source, None);
41 let expansion = analyzer.expand(db, macro_call)?; 41 let expansion = analyzer.expand(db, macro_call)?;
42 let macro_file_id = expansion.file_id(); 42 let macro_file_id = expansion.file_id();
43 let expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?; 43 let mut expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?;
44 44
45 let children = expanded.descendants().filter_map(ast::MacroCall::cast); 45 let children = expanded.descendants().filter_map(ast::MacroCall::cast);
46 let mut replaces = FxHashMap::default(); 46 let mut replaces = FxHashMap::default();
47 47
48 for child in children.into_iter() { 48 for child in children.into_iter() {
49 let node = hir::Source::new(macro_file_id, &child); 49 let node = hir::Source::new(macro_file_id, &child);
50 let new_node = expand_macro_recur(db, source, node)?; 50 if let Some(new_node) = expand_macro_recur(db, source, node) {
51 51 // Replace the whole node if it is root
52 replaces.insert(child.syntax().clone().into(), new_node.into()); 52 // `replace_descendants` will not replace the parent node
53 // but `SyntaxNode::descendants include itself
54 if expanded == *child.syntax() {
55 expanded = new_node;
56 } else {
57 replaces.insert(child.syntax().clone().into(), new_node.into());
58 }
59 }
53 } 60 }
54 61
55 Some(replace_descendants(&expanded, &replaces)) 62 Some(replace_descendants(&expanded, &replaces))
@@ -217,4 +224,49 @@ fn some_thing() -> u32 {
217} 224}
218"###); 225"###);
219 } 226 }
227
228 #[test]
229 fn macro_expand_match_ast_inside_let_statement() {
230 let res = check_expand_macro(
231 r#"
232 //- /lib.rs
233 macro_rules! match_ast {
234 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
235 (match ($node:expr) {}) => {{}};
236 }
237
238 fn main() {
239 let p = f(|it| {
240 let res = mat<|>ch_ast! { match c {}};
241 Some(res)
242 })?;
243 }
244 "#,
245 );
246
247 assert_eq!(res.name, "match_ast");
248 assert_snapshot!(res.expansion, @r###"{}"###);
249 }
250
251 #[test]
252 fn macro_expand_inner_macro_fail_to_expand() {
253 let res = check_expand_macro(
254 r#"
255 //- /lib.rs
256 macro_rules! bar {
257 (BAD) => {};
258 }
259 macro_rules! foo {
260 () => {bar!()};
261 }
262
263 fn main() {
264 let res = fo<|>o!();
265 }
266 "#,
267 );
268
269 assert_eq!(res.name, "foo");
270 assert_snapshot!(res.expansion, @r###"bar!()"###);
271 }
220} 272}