From 3c2cb89087c87f29ad3bc3856625b83017b7a294 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 6 Jan 2019 14:05:03 +0300 Subject: add parent & resolve_path --- crates/ra_hir/src/code_model_api.rs | 10 ++++++- crates/ra_hir/src/code_model_impl.rs | 56 +++++++++++++++++++++++++++++++++++- crates/ra_hir/src/module.rs | 2 +- crates/ra_hir/src/module/nameres.rs | 4 +-- 4 files changed, 67 insertions(+), 5 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 6bbc80e17..236cb3ab4 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -1,7 +1,7 @@ use ra_db::{CrateId, Cancelable, FileId}; use ra_syntax::ast; -use crate::{Name, db::HirDatabase, DefId}; +use crate::{Name, db::HirDatabase, DefId, Path, PerNs}; /// hir::Crate describes a single crate. It's the main inteface with which /// crate's dependencies interact. Mostly, it should be just a proxy for the @@ -52,4 +52,12 @@ impl Module { pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable> { self.child_impl(db, name) } + /// Finds a parent module. + pub fn parent(&self, db: &impl HirDatabase) -> Cancelable> { + self.parent_impl(db) + } + + pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> Cancelable> { + self.resolve_path_impl(db, path) + } } diff --git a/crates/ra_hir/src/code_model_impl.rs b/crates/ra_hir/src/code_model_impl.rs index 83ee8186e..678758956 100644 --- a/crates/ra_hir/src/code_model_impl.rs +++ b/crates/ra_hir/src/code_model_impl.rs @@ -1,7 +1,7 @@ use ra_db::{CrateId, Cancelable, FileId}; use ra_syntax::{AstNode, ast}; -use crate::{HirFileId, db::HirDatabase, Crate, CrateDependency, AsName, DefId, DefLoc, DefKind, Name}; +use crate::{HirFileId, db::HirDatabase, Crate, CrateDependency, AsName, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def}; use crate::code_model_api::Module; @@ -102,4 +102,58 @@ impl Module { let module = Module::new(def_id); Ok(Some(module)) } + pub fn parent_impl(&self, db: &impl HirDatabase) -> Cancelable> { + let loc = self.def_id.loc(db); + let module_tree = db.module_tree(loc.source_root_id)?; + let parent_id = ctry!(loc.module_id.parent(&module_tree)); + let def_loc = DefLoc { + module_id: parent_id, + source_item_id: parent_id.source(&module_tree).0, + ..loc + }; + let def_id = def_loc.id(db); + let module = Module::new(def_id); + Ok(Some(module)) + } + pub fn resolve_path_impl( + &self, + db: &impl HirDatabase, + path: &Path, + ) -> Cancelable> { + let mut curr_per_ns = PerNs::types( + match path.kind { + PathKind::Crate => self.crate_root(db)?, + PathKind::Self_ | PathKind::Plain => self.clone(), + PathKind::Super => { + if let Some(p) = self.parent(db)? { + p + } else { + return Ok(PerNs::none()); + } + } + } + .def_id, + ); + + let segments = &path.segments; + for name in segments.iter() { + let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { + r + } else { + return Ok(PerNs::none()); + }; + let module = match curr.resolve(db)? { + Def::Module(it) => it, + // TODO here would be the place to handle enum variants... + _ => return Ok(PerNs::none()), + }; + let scope = module.scope(db)?; + curr_per_ns = if let Some(r) = scope.get(&name) { + r.def_id + } else { + return Ok(PerNs::none()); + }; + } + Ok(curr_per_ns) + } } diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module.rs index f0b673908..11e3f6782 100644 --- a/crates/ra_hir/src/module.rs +++ b/crates/ra_hir/src/module.rs @@ -251,7 +251,7 @@ impl ModuleId { fn parent_link(self, tree: &ModuleTree) -> Option { tree.mods[self].parent } - fn parent(self, tree: &ModuleTree) -> Option { + pub(crate) fn parent(self, tree: &ModuleTree) -> Option { let link = self.parent_link(tree)?; Some(tree.links[link].owner) } diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 059301b05..dac524384 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs @@ -177,11 +177,11 @@ impl PerNs { } pub fn take_types(self) -> Option { - self.types + self.take(Namespace::Types) } pub fn take_values(self) -> Option { - self.values + self.take(Namespace::Values) } pub fn get(&self, namespace: Namespace) -> Option<&T> { -- cgit v1.2.3