diff options
author | Jonas Schievink <[email protected]> | 2020-06-26 17:06:01 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2020-06-26 17:07:31 +0100 |
commit | efe378d2b43b90f8cf549781e870bfa2ebe90fd0 (patch) | |
tree | 2b64c5197fa09129e1cfbce10947ec841d68fbea /crates/ra_hir_def/src | |
parent | 7f6694b12eaae4aa0359319e57abfced97344227 (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/src')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/scope.rs | 13 |
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; |