From b28c54a2c239acd73f2eea80fda9ee3960d2c046 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 13 Aug 2020 16:28:27 +0200 Subject: Rename ra_hir_def -> hir_def --- crates/hir_def/src/child_by_source.rs | 177 ++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 crates/hir_def/src/child_by_source.rs (limited to 'crates/hir_def/src/child_by_source.rs') diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs new file mode 100644 index 000000000..dcb00a1d9 --- /dev/null +++ b/crates/hir_def/src/child_by_source.rs @@ -0,0 +1,177 @@ +//! When *constructing* `hir`, we start at some parent syntax node and recursively +//! lower the children. +//! +//! This modules allows one to go in the opposite direction: start with a syntax +//! node for a *child*, and get its hir. + +use either::Either; + +use crate::{ + db::DefDatabase, + dyn_map::DynMap, + item_scope::ItemScope, + keys, + src::{HasChildSource, HasSource}, + AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, ModuleDefId, + ModuleId, TraitId, VariantId, +}; + +pub trait ChildBySource { + fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap; +} + +impl ChildBySource for TraitId { + fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { + let mut res = DynMap::default(); + + let data = db.trait_data(*self); + for (_name, item) in data.items.iter() { + match *item { + AssocItemId::FunctionId(func) => { + let src = func.lookup(db).source(db); + res[keys::FUNCTION].insert(src, func) + } + AssocItemId::ConstId(konst) => { + let src = konst.lookup(db).source(db); + res[keys::CONST].insert(src, konst) + } + AssocItemId::TypeAliasId(ty) => { + let src = ty.lookup(db).source(db); + res[keys::TYPE_ALIAS].insert(src, ty) + } + } + } + + res + } +} + +impl ChildBySource for ImplId { + fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { + let mut res = DynMap::default(); + + let data = db.impl_data(*self); + for &item in data.items.iter() { + match item { + AssocItemId::FunctionId(func) => { + let src = func.lookup(db).source(db); + res[keys::FUNCTION].insert(src, func) + } + AssocItemId::ConstId(konst) => { + let src = konst.lookup(db).source(db); + res[keys::CONST].insert(src, konst) + } + AssocItemId::TypeAliasId(ty) => { + let src = ty.lookup(db).source(db); + res[keys::TYPE_ALIAS].insert(src, ty) + } + } + } + + res + } +} + +impl ChildBySource for ModuleId { + fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { + let crate_def_map = db.crate_def_map(self.krate); + let module_data = &crate_def_map[self.local_id]; + module_data.scope.child_by_source(db) + } +} + +impl ChildBySource for ItemScope { + fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { + let mut res = DynMap::default(); + self.declarations().for_each(|item| add_module_def(db, &mut res, item)); + self.impls().for_each(|imp| add_impl(db, &mut res, imp)); + return res; + + fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { + match item { + ModuleDefId::FunctionId(func) => { + let src = func.lookup(db).source(db); + map[keys::FUNCTION].insert(src, func) + } + ModuleDefId::ConstId(konst) => { + let src = konst.lookup(db).source(db); + map[keys::CONST].insert(src, konst) + } + ModuleDefId::StaticId(statik) => { + let src = statik.lookup(db).source(db); + map[keys::STATIC].insert(src, statik) + } + ModuleDefId::TypeAliasId(ty) => { + let src = ty.lookup(db).source(db); + map[keys::TYPE_ALIAS].insert(src, ty) + } + ModuleDefId::TraitId(trait_) => { + let src = trait_.lookup(db).source(db); + map[keys::TRAIT].insert(src, trait_) + } + ModuleDefId::AdtId(adt) => match adt { + AdtId::StructId(strukt) => { + let src = strukt.lookup(db).source(db); + map[keys::STRUCT].insert(src, strukt) + } + AdtId::UnionId(union_) => { + let src = union_.lookup(db).source(db); + map[keys::UNION].insert(src, union_) + } + AdtId::EnumId(enum_) => { + let src = enum_.lookup(db).source(db); + map[keys::ENUM].insert(src, enum_) + } + }, + _ => (), + } + } + fn add_impl(db: &dyn DefDatabase, map: &mut DynMap, imp: ImplId) { + let src = imp.lookup(db).source(db); + map[keys::IMPL].insert(src, imp) + } + } +} + +impl ChildBySource for VariantId { + fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { + let mut res = DynMap::default(); + + let arena_map = self.child_source(db); + let arena_map = arena_map.as_ref(); + for (local_id, source) in arena_map.value.iter() { + let id = FieldId { parent: *self, local_id }; + match source { + Either::Left(source) => { + res[keys::TUPLE_FIELD].insert(arena_map.with_value(source.clone()), id) + } + Either::Right(source) => { + res[keys::RECORD_FIELD].insert(arena_map.with_value(source.clone()), id) + } + } + } + res + } +} + +impl ChildBySource for EnumId { + fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { + let mut res = DynMap::default(); + + let arena_map = self.child_source(db); + let arena_map = arena_map.as_ref(); + for (local_id, source) in arena_map.value.iter() { + let id = EnumVariantId { parent: *self, local_id }; + res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id) + } + + res + } +} + +impl ChildBySource for DefWithBodyId { + fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { + let body = db.body(*self); + body.item_scope.child_by_source(db) + } +} -- cgit v1.2.3