diff options
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/scope.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_tree.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_tree/lower.rs | 7 |
4 files changed, 44 insertions, 14 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index e7cf80676..bbde0b802 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -564,12 +564,14 @@ impl ExprCollector<'_> { | |||
564 | }); | 564 | }); |
565 | let tree = &self.item_trees[index].1; | 565 | let tree = &self.item_trees[index].1; |
566 | 566 | ||
567 | // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes | ||
568 | |||
567 | // Root file (non-macro). | 569 | // Root file (non-macro). |
568 | tree.all_inner_items() | 570 | tree.all_inner_items() |
569 | .chain(tree.top_level_items().iter().copied()) | 571 | .chain(tree.top_level_items().iter().copied()) |
570 | .filter_map(|mod_item| mod_item.downcast::<S>()) | 572 | .filter_map(|mod_item| mod_item.downcast::<S>()) |
571 | .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value) | 573 | .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value) |
572 | .unwrap() | 574 | .unwrap_or_else(|| panic!("couldn't find inner item for {:?}", id)) |
573 | } | 575 | } |
574 | 576 | ||
575 | fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { | 577 | fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 0b74199d9..81397b063 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -317,6 +317,26 @@ fn foo() { | |||
317 | ); | 317 | ); |
318 | } | 318 | } |
319 | 319 | ||
320 | #[test] | ||
321 | fn macro_inner_item() { | ||
322 | do_check( | ||
323 | r" | ||
324 | macro_rules! mac { | ||
325 | () => {{ | ||
326 | fn inner() {} | ||
327 | inner(); | ||
328 | }}; | ||
329 | } | ||
330 | |||
331 | fn foo() { | ||
332 | mac!(); | ||
333 | <|> | ||
334 | } | ||
335 | ", | ||
336 | &[], | ||
337 | ); | ||
338 | } | ||
339 | |||
320 | fn do_check_local_name(ra_fixture: &str, expected_offset: u32) { | 340 | fn do_check_local_name(ra_fixture: &str, expected_offset: u32) { |
321 | let (db, position) = TestDB::with_position(ra_fixture); | 341 | let (db, position) = TestDB::with_position(ra_fixture); |
322 | let file_id = position.file_id; | 342 | let file_id = position.file_id; |
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index efcb5dc60..a1a78fc5c 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs | |||
@@ -12,7 +12,7 @@ use std::{ | |||
12 | sync::Arc, | 12 | sync::Arc, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner}; | 15 | use ast::{AstNode, AttrsOwner, NameOwner, StructKind, TypeAscriptionOwner}; |
16 | use either::Either; | 16 | use either::Either; |
17 | use hir_expand::{ | 17 | use hir_expand::{ |
18 | ast_id_map::FileAstId, | 18 | ast_id_map::FileAstId, |
@@ -73,25 +73,28 @@ impl ItemTree { | |||
73 | }; | 73 | }; |
74 | 74 | ||
75 | let hygiene = Hygiene::new(db.upcast(), file_id); | 75 | let hygiene = Hygiene::new(db.upcast(), file_id); |
76 | let ctx = lower::Ctx::new(db, hygiene.clone(), file_id); | ||
76 | let mut top_attrs = None; | 77 | let mut top_attrs = None; |
77 | let (macro_storage, file_storage); | 78 | let mut item_tree = match_ast! { |
78 | let item_owner = match_ast! { | ||
79 | match syntax { | 79 | match syntax { |
80 | ast::MacroItems(items) => { | ||
81 | macro_storage = items; | ||
82 | ¯o_storage as &dyn ModuleItemOwner | ||
83 | }, | ||
84 | ast::SourceFile(file) => { | 80 | ast::SourceFile(file) => { |
85 | top_attrs = Some(Attrs::new(&file, &hygiene)); | 81 | top_attrs = Some(Attrs::new(&file, &hygiene)); |
86 | file_storage = file; | 82 | ctx.lower_module_items(&file) |
87 | &file_storage | 83 | }, |
84 | ast::MacroItems(items) => { | ||
85 | ctx.lower_module_items(&items) | ||
86 | }, | ||
87 | // Macros can expand to expressions. We return an empty item tree in this case, but | ||
88 | // still need to collect inner items. | ||
89 | ast::Expr(e) => { | ||
90 | ctx.lower_inner_items(e.syntax()) | ||
91 | }, | ||
92 | _ => { | ||
93 | panic!("cannot create item tree from {:?}", syntax); | ||
88 | }, | 94 | }, |
89 | _ => return Arc::new(Self::empty(file_id)), | ||
90 | } | 95 | } |
91 | }; | 96 | }; |
92 | 97 | ||
93 | let ctx = lower::Ctx::new(db, hygiene, file_id); | ||
94 | let mut item_tree = ctx.lower(item_owner); | ||
95 | item_tree.top_attrs = top_attrs.unwrap_or_default(); | 98 | item_tree.top_attrs = top_attrs.unwrap_or_default(); |
96 | Arc::new(item_tree) | 99 | Arc::new(item_tree) |
97 | } | 100 | } |
diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index 841c7a852..3bb437e81 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs | |||
@@ -52,7 +52,7 @@ impl Ctx { | |||
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | pub(super) fn lower(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree { | 55 | pub(super) fn lower_module_items(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree { |
56 | self.tree.top_level = item_owner | 56 | self.tree.top_level = item_owner |
57 | .items() | 57 | .items() |
58 | .flat_map(|item| self.lower_mod_item(&item, false)) | 58 | .flat_map(|item| self.lower_mod_item(&item, false)) |
@@ -61,6 +61,11 @@ impl Ctx { | |||
61 | self.tree | 61 | self.tree |
62 | } | 62 | } |
63 | 63 | ||
64 | pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { | ||
65 | self.collect_inner_items(within); | ||
66 | self.tree | ||
67 | } | ||
68 | |||
64 | fn lower_mod_item(&mut self, item: &ast::ModuleItem, inner: bool) -> Option<ModItems> { | 69 | fn lower_mod_item(&mut self, item: &ast::ModuleItem, inner: bool) -> Option<ModItems> { |
65 | assert!(inner || self.inner_items.is_empty()); | 70 | assert!(inner || self.inner_items.is_empty()); |
66 | 71 | ||