aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/body
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/body')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs177
-rw-r--r--crates/ra_hir_def/src/body/scope.rs20
2 files changed, 145 insertions, 52 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index f159f80af..3ced648e5 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -5,7 +5,7 @@ use either::Either;
5use hir_expand::{ 5use hir_expand::{
6 hygiene::Hygiene, 6 hygiene::Hygiene,
7 name::{name, AsName, Name}, 7 name::{name, AsName, Name},
8 HirFileId, MacroDefId, MacroDefKind, 8 AstId, HirFileId, MacroDefId, MacroDefKind,
9}; 9};
10use ra_arena::Arena; 10use ra_arena::Arena;
11use ra_syntax::{ 11use ra_syntax::{
@@ -27,6 +27,7 @@ use crate::{
27 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 27 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
28 }, 28 },
29 item_scope::BuiltinShadowMode, 29 item_scope::BuiltinShadowMode,
30 item_tree::{FileItemTreeId, ItemTree, ItemTreeNode},
30 path::{GenericArgs, Path}, 31 path::{GenericArgs, Path},
31 type_ref::{Mutability, Rawness, TypeRef}, 32 type_ref::{Mutability, Rawness, TypeRef},
32 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, 33 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
@@ -35,6 +36,8 @@ use crate::{
35 36
36use super::{ExprSource, PatSource}; 37use super::{ExprSource, PatSource};
37use ast::AstChildren; 38use ast::AstChildren;
39use rustc_hash::FxHashMap;
40use std::sync::Arc;
38 41
39pub(crate) struct LowerCtx { 42pub(crate) struct LowerCtx {
40 hygiene: Hygiene, 43 hygiene: Hygiene,
@@ -60,10 +63,10 @@ pub(super) fn lower(
60 params: Option<ast::ParamList>, 63 params: Option<ast::ParamList>,
61 body: Option<ast::Expr>, 64 body: Option<ast::Expr>,
62) -> (Body, BodySourceMap) { 65) -> (Body, BodySourceMap) {
66 let item_tree = db.item_tree(expander.current_file_id);
63 ExprCollector { 67 ExprCollector {
64 db, 68 db,
65 def, 69 def,
66 expander,
67 source_map: BodySourceMap::default(), 70 source_map: BodySourceMap::default(),
68 body: Body { 71 body: Body {
69 exprs: Arena::default(), 72 exprs: Arena::default(),
@@ -72,6 +75,12 @@ pub(super) fn lower(
72 body_expr: dummy_expr_id(), 75 body_expr: dummy_expr_id(),
73 item_scope: Default::default(), 76 item_scope: Default::default(),
74 }, 77 },
78 item_trees: {
79 let mut map = FxHashMap::default();
80 map.insert(expander.current_file_id, item_tree);
81 map
82 },
83 expander,
75 } 84 }
76 .collect(params, body) 85 .collect(params, body)
77} 86}
@@ -82,6 +91,8 @@ struct ExprCollector<'a> {
82 expander: Expander, 91 expander: Expander,
83 body: Body, 92 body: Body,
84 source_map: BodySourceMap, 93 source_map: BodySourceMap,
94
95 item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
85} 96}
86 97
87impl ExprCollector<'_> { 98impl ExprCollector<'_> {
@@ -533,6 +544,9 @@ impl ExprCollector<'_> {
533 self.source_map 544 self.source_map
534 .expansions 545 .expansions
535 .insert(macro_call, self.expander.current_file_id); 546 .insert(macro_call, self.expander.current_file_id);
547
548 let item_tree = self.db.item_tree(self.expander.current_file_id);
549 self.item_trees.insert(self.expander.current_file_id, item_tree);
536 let id = self.collect_expr(expansion); 550 let id = self.collect_expr(expansion);
537 self.expander.exit(self.db, mark); 551 self.expander.exit(self.db, mark);
538 id 552 id
@@ -547,6 +561,19 @@ impl ExprCollector<'_> {
547 } 561 }
548 } 562 }
549 563
564 fn find_inner_item<S: ItemTreeNode>(&self, id: AstId<ast::ModuleItem>) -> FileItemTreeId<S> {
565 let tree = &self.item_trees[&id.file_id];
566
567 // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes
568
569 // Root file (non-macro).
570 tree.all_inner_items()
571 .chain(tree.top_level_items().iter().copied())
572 .filter_map(|mod_item| mod_item.downcast::<S>())
573 .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value)
574 .unwrap_or_else(|| panic!("couldn't find inner item for {:?}", id))
575 }
576
550 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { 577 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
551 if let Some(expr) = expr { 578 if let Some(expr) = expr {
552 self.collect_expr(expr) 579 self.collect_expr(expr)
@@ -578,56 +605,102 @@ impl ExprCollector<'_> {
578 605
579 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 606 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
580 let container = ContainerId::DefWithBodyId(self.def); 607 let container = ContainerId::DefWithBodyId(self.def);
581 for item in block.items() { 608
582 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 609 let items = block
583 ast::ModuleItem::FnDef(def) => { 610 .items()
584 let ast_id = self.expander.ast_id(&def); 611 .filter_map(|item| {
585 ( 612 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
586 FunctionLoc { container: container.into(), ast_id }.intern(self.db).into(), 613 ast::ModuleItem::FnDef(def) => {
587 def.name(), 614 let ast_id = self.expander.ast_id(&def);
588 ) 615 let id = self.find_inner_item(ast_id.map(|id| id.upcast()));
589 } 616 (
590 ast::ModuleItem::TypeAliasDef(def) => { 617 FunctionLoc { container: container.into(), id: ast_id.with_value(id) }
591 let ast_id = self.expander.ast_id(&def); 618 .intern(self.db)
592 ( 619 .into(),
593 TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into(), 620 def.name(),
594 def.name(), 621 )
595 ) 622 }
596 } 623 ast::ModuleItem::TypeAliasDef(def) => {
597 ast::ModuleItem::ConstDef(def) => { 624 let ast_id = self.expander.ast_id(&def);
598 let ast_id = self.expander.ast_id(&def); 625 let id = self.find_inner_item(ast_id.map(|id| id.upcast()));
599 ( 626 (
600 ConstLoc { container: container.into(), ast_id }.intern(self.db).into(), 627 TypeAliasLoc { container: container.into(), id: ast_id.with_value(id) }
601 def.name(), 628 .intern(self.db)
602 ) 629 .into(),
603 } 630 def.name(),
604 ast::ModuleItem::StaticDef(def) => { 631 )
605 let ast_id = self.expander.ast_id(&def); 632 }
606 (StaticLoc { container, ast_id }.intern(self.db).into(), def.name()) 633 ast::ModuleItem::ConstDef(def) => {
607 } 634 let ast_id = self.expander.ast_id(&def);
608 ast::ModuleItem::StructDef(def) => { 635 let id = self.find_inner_item(ast_id.map(|id| id.upcast()));
609 let ast_id = self.expander.ast_id(&def); 636 (
610 (StructLoc { container, ast_id }.intern(self.db).into(), def.name()) 637 ConstLoc { container: container.into(), id: ast_id.with_value(id) }
611 } 638 .intern(self.db)
612 ast::ModuleItem::EnumDef(def) => { 639 .into(),
613 let ast_id = self.expander.ast_id(&def); 640 def.name(),
614 (EnumLoc { container, ast_id }.intern(self.db).into(), def.name()) 641 )
615 } 642 }
616 ast::ModuleItem::UnionDef(def) => { 643 ast::ModuleItem::StaticDef(def) => {
617 let ast_id = self.expander.ast_id(&def); 644 let ast_id = self.expander.ast_id(&def);
618 (UnionLoc { container, ast_id }.intern(self.db).into(), def.name()) 645 let id = self.find_inner_item(ast_id.map(|id| id.upcast()));
619 } 646 (
620 ast::ModuleItem::TraitDef(def) => { 647 StaticLoc { container, id: ast_id.with_value(id) }
621 let ast_id = self.expander.ast_id(&def); 648 .intern(self.db)
622 (TraitLoc { container, ast_id }.intern(self.db).into(), def.name()) 649 .into(),
623 } 650 def.name(),
624 ast::ModuleItem::ExternBlock(_) => continue, // FIXME: collect from extern blocks 651 )
625 ast::ModuleItem::ImplDef(_) 652 }
626 | ast::ModuleItem::UseItem(_) 653 ast::ModuleItem::StructDef(def) => {
627 | ast::ModuleItem::ExternCrateItem(_) 654 let ast_id = self.expander.ast_id(&def);
628 | ast::ModuleItem::Module(_) 655 let id = self.find_inner_item(ast_id.map(|id| id.upcast()));
629 | ast::ModuleItem::MacroCall(_) => continue, 656 (
630 }; 657 StructLoc { container, id: ast_id.with_value(id) }
658 .intern(self.db)
659 .into(),
660 def.name(),
661 )
662 }
663 ast::ModuleItem::EnumDef(def) => {
664 let ast_id = self.expander.ast_id(&def);
665 let id = self.find_inner_item(ast_id.map(|id| id.upcast()));
666 (
667 EnumLoc { container, id: ast_id.with_value(id) }.intern(self.db).into(),
668 def.name(),
669 )
670 }
671 ast::ModuleItem::UnionDef(def) => {
672 let ast_id = self.expander.ast_id(&def);
673 let id = self.find_inner_item(ast_id.map(|id| id.upcast()));
674 (
675 UnionLoc { container, id: ast_id.with_value(id) }
676 .intern(self.db)
677 .into(),
678 def.name(),
679 )
680 }
681 ast::ModuleItem::TraitDef(def) => {
682 let ast_id = self.expander.ast_id(&def);
683 let id = self.find_inner_item(ast_id.map(|id| id.upcast()));
684 (
685 TraitLoc { container, id: ast_id.with_value(id) }
686 .intern(self.db)
687 .into(),
688 def.name(),
689 )
690 }
691 ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks
692 ast::ModuleItem::ImplDef(_)
693 | ast::ModuleItem::UseItem(_)
694 | ast::ModuleItem::ExternCrateItem(_)
695 | ast::ModuleItem::Module(_)
696 | ast::ModuleItem::MacroCall(_) => return None,
697 };
698
699 Some((def, name))
700 })
701 .collect::<Vec<_>>();
702
703 for (def, name) in items {
631 self.body.item_scope.define_def(def); 704 self.body.item_scope.define_def(def);
632 if let Some(name) = name { 705 if let Some(name) = name {
633 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 706 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
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;