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.
This commit is contained in:
Jonas Schievink 2020-06-26 18:06:01 +02:00
parent 7f6694b12e
commit efe378d2b4
2 changed files with 28 additions and 14 deletions

View file

@ -561,7 +561,7 @@ impl ExprCollector<'_> {
} }
} }
fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> ItemTreeId<N> { fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
let id = self.expander.ast_id(ast); let id = self.expander.ast_id(ast);
let tree = &self.item_trees[&id.file_id]; let tree = &self.item_trees[&id.file_id];
@ -573,17 +573,18 @@ impl ExprCollector<'_> {
.chain(tree.top_level_items().iter().copied()) .chain(tree.top_level_items().iter().copied())
.filter_map(|mod_item| mod_item.downcast::<N>()) .filter_map(|mod_item| mod_item.downcast::<N>())
.find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast()) .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
.unwrap_or_else(|| { .or_else(|| {
panic!( log::debug!(
"couldn't find inner {} item for {:?} (AST: `{}` - {:?})", "couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
type_name::<N>(), type_name::<N>(),
id, id,
ast.syntax(), ast.syntax(),
ast.syntax(), ast.syntax(),
) );
}); None
})?;
ItemTreeId::new(id.file_id, item_tree_id) Some(ItemTreeId::new(id.file_id, item_tree_id))
} }
fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
@ -623,44 +624,44 @@ impl ExprCollector<'_> {
.filter_map(|item| { .filter_map(|item| {
let (def, name): (ModuleDefId, Option<ast::Name>) = match item { let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
ast::ModuleItem::FnDef(def) => { ast::ModuleItem::FnDef(def) => {
let id = self.find_inner_item(&def); let id = self.find_inner_item(&def)?;
( (
FunctionLoc { container: container.into(), id }.intern(self.db).into(), FunctionLoc { container: container.into(), id }.intern(self.db).into(),
def.name(), def.name(),
) )
} }
ast::ModuleItem::TypeAliasDef(def) => { ast::ModuleItem::TypeAliasDef(def) => {
let id = self.find_inner_item(&def); let id = self.find_inner_item(&def)?;
( (
TypeAliasLoc { container: container.into(), id }.intern(self.db).into(), TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
def.name(), def.name(),
) )
} }
ast::ModuleItem::ConstDef(def) => { ast::ModuleItem::ConstDef(def) => {
let id = self.find_inner_item(&def); let id = self.find_inner_item(&def)?;
( (
ConstLoc { container: container.into(), id }.intern(self.db).into(), ConstLoc { container: container.into(), id }.intern(self.db).into(),
def.name(), def.name(),
) )
} }
ast::ModuleItem::StaticDef(def) => { ast::ModuleItem::StaticDef(def) => {
let id = self.find_inner_item(&def); let id = self.find_inner_item(&def)?;
(StaticLoc { container, id }.intern(self.db).into(), def.name()) (StaticLoc { container, id }.intern(self.db).into(), def.name())
} }
ast::ModuleItem::StructDef(def) => { ast::ModuleItem::StructDef(def) => {
let id = self.find_inner_item(&def); let id = self.find_inner_item(&def)?;
(StructLoc { container, id }.intern(self.db).into(), def.name()) (StructLoc { container, id }.intern(self.db).into(), def.name())
} }
ast::ModuleItem::EnumDef(def) => { ast::ModuleItem::EnumDef(def) => {
let id = self.find_inner_item(&def); let id = self.find_inner_item(&def)?;
(EnumLoc { container, id }.intern(self.db).into(), def.name()) (EnumLoc { container, id }.intern(self.db).into(), def.name())
} }
ast::ModuleItem::UnionDef(def) => { ast::ModuleItem::UnionDef(def) => {
let id = self.find_inner_item(&def); let id = self.find_inner_item(&def)?;
(UnionLoc { container, id }.intern(self.db).into(), def.name()) (UnionLoc { container, id }.intern(self.db).into(), def.name())
} }
ast::ModuleItem::TraitDef(def) => { ast::ModuleItem::TraitDef(def) => {
let id = self.find_inner_item(&def); let id = self.find_inner_item(&def)?;
(TraitLoc { container, id }.intern(self.db).into(), def.name()) (TraitLoc { container, id }.intern(self.db).into(), def.name())
} }
ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks

View file

@ -337,6 +337,19 @@ fn foo() {
); );
} }
#[test]
fn broken_inner_item() {
do_check(
r"
fn foo() {
trait {}
<|>
}
",
&[],
);
}
fn do_check_local_name(ra_fixture: &str, expected_offset: u32) { fn do_check_local_name(ra_fixture: &str, expected_offset: u32) {
let (db, position) = TestDB::with_position(ra_fixture); let (db, position) = TestDB::with_position(ra_fixture);
let file_id = position.file_id; let file_id = position.file_id;