From 360de5ba71a631a118a088dba7c975e9ae592452 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 21 Dec 2019 05:02:31 +0800 Subject: Recursive collect macros in impl items --- crates/ra_hir_def/src/data.rs | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'crates/ra_hir_def') diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index b0a3f1784..6a65633ae 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -226,21 +226,39 @@ fn collect_impl_items_in_macros( let mut res = Vec::new(); for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) { - if let Some((mark, items)) = expander.enter_expand(db, m) { - let items: InFile = expander.to_source(items); - expander.exit(db, mark); - res.extend(collect_impl_items( - db, - items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), - items.file_id, - id, - )); - } + res.extend(collect_impl_items_in_macro(db, &mut expander, m, id)) } res } +fn collect_impl_items_in_macro( + db: &impl DefDatabase, + expander: &mut Expander, + m: ast::MacroCall, + id: ImplId, +) -> Vec { + if let Some((mark, items)) = expander.enter_expand(db, m) { + let items: InFile = expander.to_source(items); + let mut res = collect_impl_items( + db, + items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), + items.file_id, + id, + ); + // Recursive collect macros + // Note that ast::ModuleItem do not include ast::MacroCall + // We cannot use ModuleItemOwner::items here + for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { + res.extend(collect_impl_items_in_macro(db, expander, it, id)) + } + expander.exit(db, mark); + res + } else { + Vec::new() + } +} + fn collect_impl_items( db: &impl DefDatabase, impl_items: impl Iterator, -- cgit v1.2.3 From c1166697a74bca690443525ced8cd8bc08894779 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 21 Dec 2019 05:16:29 +0800 Subject: Add a limit for protect against infinite recursion --- crates/ra_hir_def/src/data.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir_def') diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 6a65633ae..1aa9a9b7d 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -225,8 +225,11 @@ fn collect_impl_items_in_macros( let mut expander = Expander::new(db, impl_block.file_id, module_id); let mut res = Vec::new(); + // We set a limit to protect against infinite recursion + let limit = 100; + for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) { - res.extend(collect_impl_items_in_macro(db, &mut expander, m, id)) + res.extend(collect_impl_items_in_macro(db, &mut expander, m, id, limit)) } res @@ -237,7 +240,12 @@ fn collect_impl_items_in_macro( expander: &mut Expander, m: ast::MacroCall, id: ImplId, + limit: usize, ) -> Vec { + if limit == 0 { + return Vec::new(); + } + if let Some((mark, items)) = expander.enter_expand(db, m) { let items: InFile = expander.to_source(items); let mut res = collect_impl_items( @@ -250,7 +258,7 @@ fn collect_impl_items_in_macro( // Note that ast::ModuleItem do not include ast::MacroCall // We cannot use ModuleItemOwner::items here for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { - res.extend(collect_impl_items_in_macro(db, expander, it, id)) + res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) } expander.exit(db, mark); res -- cgit v1.2.3