From 2aebde6c0b47a1f2ce3d49af457683258d813cdc Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 28 Jan 2021 18:00:10 +0100 Subject: [PATCH] ItemTree: Treat items in `MacroStmts` as top-level --- crates/hir_def/src/item_tree.rs | 10 ++++++---- crates/hir_def/src/item_tree/lower.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 1e5c946604..42d9f09472 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -98,15 +98,17 @@ impl ItemTree { ctx.lower_module_items(&items) }, ast::MacroStmts(stmts) => { - ctx.lower_inner_items(stmts.syntax()) + // The produced statements can include items, which should be added as top-level + // items. + ctx.lower_macro_stmts(stmts) }, - // Macros can expand to expressions. We return an empty item tree in this case, but - // still need to collect inner items. ast::Expr(e) => { + // Macros can expand to expressions. We return an empty item tree in this case, but + // still need to collect inner items. ctx.lower_inner_items(e.syntax()) }, _ => { - panic!("cannot create item tree from {:?}", syntax); + panic!("cannot create item tree from {:?} {}", syntax, syntax); }, } }; diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 8a71376b99..acc001adda 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -61,6 +61,32 @@ impl Ctx { self.tree } + pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree { + self.tree.top_level = stmts + .statements() + .filter_map(|stmt| match stmt { + ast::Stmt::Item(item) => Some(item), + _ => None, + }) + .flat_map(|item| self.lower_mod_item(&item, false)) + .flat_map(|items| items.0) + .collect(); + + // Non-items need to have their inner items collected. + for stmt in stmts.statements() { + match stmt { + ast::Stmt::ExprStmt(_) | ast::Stmt::LetStmt(_) => { + self.collect_inner_items(stmt.syntax()) + } + _ => {} + } + } + if let Some(expr) = stmts.expr() { + self.collect_inner_items(expr.syntax()); + } + self.tree + } + pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { self.collect_inner_items(within); self.tree