diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 10 | ||||
-rw-r--r-- | 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 1e5c94660..42d9f0947 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -98,15 +98,17 @@ impl ItemTree { | |||
98 | ctx.lower_module_items(&items) | 98 | ctx.lower_module_items(&items) |
99 | }, | 99 | }, |
100 | ast::MacroStmts(stmts) => { | 100 | ast::MacroStmts(stmts) => { |
101 | ctx.lower_inner_items(stmts.syntax()) | 101 | // The produced statements can include items, which should be added as top-level |
102 | // items. | ||
103 | ctx.lower_macro_stmts(stmts) | ||
102 | }, | 104 | }, |
103 | // Macros can expand to expressions. We return an empty item tree in this case, but | ||
104 | // still need to collect inner items. | ||
105 | ast::Expr(e) => { | 105 | ast::Expr(e) => { |
106 | // Macros can expand to expressions. We return an empty item tree in this case, but | ||
107 | // still need to collect inner items. | ||
106 | ctx.lower_inner_items(e.syntax()) | 108 | ctx.lower_inner_items(e.syntax()) |
107 | }, | 109 | }, |
108 | _ => { | 110 | _ => { |
109 | panic!("cannot create item tree from {:?}", syntax); | 111 | panic!("cannot create item tree from {:?} {}", syntax, syntax); |
110 | }, | 112 | }, |
111 | } | 113 | } |
112 | }; | 114 | }; |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 8a71376b9..acc001add 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 { | |||
61 | self.tree | 61 | self.tree |
62 | } | 62 | } |
63 | 63 | ||
64 | pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree { | ||
65 | self.tree.top_level = stmts | ||
66 | .statements() | ||
67 | .filter_map(|stmt| match stmt { | ||
68 | ast::Stmt::Item(item) => Some(item), | ||
69 | _ => None, | ||
70 | }) | ||
71 | .flat_map(|item| self.lower_mod_item(&item, false)) | ||
72 | .flat_map(|items| items.0) | ||
73 | .collect(); | ||
74 | |||
75 | // Non-items need to have their inner items collected. | ||
76 | for stmt in stmts.statements() { | ||
77 | match stmt { | ||
78 | ast::Stmt::ExprStmt(_) | ast::Stmt::LetStmt(_) => { | ||
79 | self.collect_inner_items(stmt.syntax()) | ||
80 | } | ||
81 | _ => {} | ||
82 | } | ||
83 | } | ||
84 | if let Some(expr) = stmts.expr() { | ||
85 | self.collect_inner_items(expr.syntax()); | ||
86 | } | ||
87 | self.tree | ||
88 | } | ||
89 | |||
64 | pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { | 90 | pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { |
65 | self.collect_inner_items(within); | 91 | self.collect_inner_items(within); |
66 | self.tree | 92 | self.tree |