aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-06-26 17:06:01 +0100
committerJonas Schievink <[email protected]>2020-06-26 17:07:31 +0100
commitefe378d2b43b90f8cf549781e870bfa2ebe90fd0 (patch)
tree2b64c5197fa09129e1cfbce10947ec841d68fbea /crates/ra_hir_def
parent7f6694b12eaae4aa0359319e57abfced97344227 (diff)
Make find_inner_item fallible
The ItemTree does not collect incomplete items, such as traits with no name, so the (malformed) AST node might have no corresponding item.
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs29
-rw-r--r--crates/ra_hir_def/src/body/scope.rs13
2 files changed, 28 insertions, 14 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 961064d29..a7e2e0982 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -561,7 +561,7 @@ impl ExprCollector<'_> {
561 } 561 }
562 } 562 }
563 563
564 fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> ItemTreeId<N> { 564 fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
565 let id = self.expander.ast_id(ast); 565 let id = self.expander.ast_id(ast);
566 let tree = &self.item_trees[&id.file_id]; 566 let tree = &self.item_trees[&id.file_id];
567 567
@@ -573,17 +573,18 @@ impl ExprCollector<'_> {
573 .chain(tree.top_level_items().iter().copied()) 573 .chain(tree.top_level_items().iter().copied())
574 .filter_map(|mod_item| mod_item.downcast::<N>()) 574 .filter_map(|mod_item| mod_item.downcast::<N>())
575 .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast()) 575 .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
576 .unwrap_or_else(|| { 576 .or_else(|| {
577 panic!( 577 log::debug!(
578 "couldn't find inner {} item for {:?} (AST: `{}` - {:?})", 578 "couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
579 type_name::<N>(), 579 type_name::<N>(),
580 id, 580 id,
581 ast.syntax(), 581 ast.syntax(),
582 ast.syntax(), 582 ast.syntax(),
583 ) 583 );
584 }); 584 None
585 })?;
585 586
586 ItemTreeId::new(id.file_id, item_tree_id) 587 Some(ItemTreeId::new(id.file_id, item_tree_id))
587 } 588 }
588 589
589 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { 590 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
@@ -623,44 +624,44 @@ impl ExprCollector<'_> {
623 .filter_map(|item| { 624 .filter_map(|item| {
624 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 625 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
625 ast::ModuleItem::FnDef(def) => { 626 ast::ModuleItem::FnDef(def) => {
626 let id = self.find_inner_item(&def); 627 let id = self.find_inner_item(&def)?;
627 ( 628 (
628 FunctionLoc { container: container.into(), id }.intern(self.db).into(), 629 FunctionLoc { container: container.into(), id }.intern(self.db).into(),
629 def.name(), 630 def.name(),
630 ) 631 )
631 } 632 }
632 ast::ModuleItem::TypeAliasDef(def) => { 633 ast::ModuleItem::TypeAliasDef(def) => {
633 let id = self.find_inner_item(&def); 634 let id = self.find_inner_item(&def)?;
634 ( 635 (
635 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(), 636 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
636 def.name(), 637 def.name(),
637 ) 638 )
638 } 639 }
639 ast::ModuleItem::ConstDef(def) => { 640 ast::ModuleItem::ConstDef(def) => {
640 let id = self.find_inner_item(&def); 641 let id = self.find_inner_item(&def)?;
641 ( 642 (
642 ConstLoc { container: container.into(), id }.intern(self.db).into(), 643 ConstLoc { container: container.into(), id }.intern(self.db).into(),
643 def.name(), 644 def.name(),
644 ) 645 )
645 } 646 }
646 ast::ModuleItem::StaticDef(def) => { 647 ast::ModuleItem::StaticDef(def) => {
647 let id = self.find_inner_item(&def); 648 let id = self.find_inner_item(&def)?;
648 (StaticLoc { container, id }.intern(self.db).into(), def.name()) 649 (StaticLoc { container, id }.intern(self.db).into(), def.name())
649 } 650 }
650 ast::ModuleItem::StructDef(def) => { 651 ast::ModuleItem::StructDef(def) => {
651 let id = self.find_inner_item(&def); 652 let id = self.find_inner_item(&def)?;
652 (StructLoc { container, id }.intern(self.db).into(), def.name()) 653 (StructLoc { container, id }.intern(self.db).into(), def.name())
653 } 654 }
654 ast::ModuleItem::EnumDef(def) => { 655 ast::ModuleItem::EnumDef(def) => {
655 let id = self.find_inner_item(&def); 656 let id = self.find_inner_item(&def)?;
656 (EnumLoc { container, id }.intern(self.db).into(), def.name()) 657 (EnumLoc { container, id }.intern(self.db).into(), def.name())
657 } 658 }
658 ast::ModuleItem::UnionDef(def) => { 659 ast::ModuleItem::UnionDef(def) => {
659 let id = self.find_inner_item(&def); 660 let id = self.find_inner_item(&def)?;
660 (UnionLoc { container, id }.intern(self.db).into(), def.name()) 661 (UnionLoc { container, id }.intern(self.db).into(), def.name())
661 } 662 }
662 ast::ModuleItem::TraitDef(def) => { 663 ast::ModuleItem::TraitDef(def) => {
663 let id = self.find_inner_item(&def); 664 let id = self.find_inner_item(&def)?;
664 (TraitLoc { container, id }.intern(self.db).into(), def.name()) 665 (TraitLoc { container, id }.intern(self.db).into(), def.name())
665 } 666 }
666 ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks 667 ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 81397b063..99e876683 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -337,6 +337,19 @@ fn foo() {
337 ); 337 );
338 } 338 }
339 339
340 #[test]
341 fn broken_inner_item() {
342 do_check(
343 r"
344 fn foo() {
345 trait {}
346 <|>
347 }
348 ",
349 &[],
350 );
351 }
352
340 fn do_check_local_name(ra_fixture: &str, expected_offset: u32) { 353 fn do_check_local_name(ra_fixture: &str, expected_offset: u32) {
341 let (db, position) = TestDB::with_position(ra_fixture); 354 let (db, position) = TestDB::with_position(ra_fixture);
342 let file_id = position.file_id; 355 let file_id = position.file_id;