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 ++++++++++++++++++++++++++---------- crates/ra_hir_ty/src/tests/macros.rs | 23 ++++++++++++++++++++++ 2 files changed, 51 insertions(+), 10 deletions(-) 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, diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 7fdbf996f..69c695cc8 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -201,6 +201,29 @@ fn test() { S.foo()<|>; } assert_eq!(t, "u128"); } +#[test] +fn infer_impl_items_generated_by_macros_chain() { + let t = type_at( + r#" +//- /main.rs +macro_rules! m_inner { + () => {fn foo(&self) -> u128 {0}} +} +macro_rules! m { + () => {m_inner!();} +} + +struct S; +impl S { + m!(); +} + +fn test() { S.foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + #[test] fn infer_macro_with_dollar_crate_is_correct_in_expr() { let (db, pos) = TestDB::with_position( -- cgit v1.2.3