diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl.rs | 56 | ||||
-rw-r--r-- | crates/ra_hir/src/module.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/module/nameres.rs | 4 |
4 files changed, 67 insertions, 5 deletions
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 @@ | |||
1 | use ra_db::{CrateId, Cancelable, FileId}; | 1 | use ra_db::{CrateId, Cancelable, FileId}; |
2 | use ra_syntax::ast; | 2 | use ra_syntax::ast; |
3 | 3 | ||
4 | use crate::{Name, db::HirDatabase, DefId}; | 4 | use crate::{Name, db::HirDatabase, DefId, Path, PerNs}; |
5 | 5 | ||
6 | /// hir::Crate describes a single crate. It's the main inteface with which | 6 | /// hir::Crate describes a single crate. It's the main inteface with which |
7 | /// crate's dependencies interact. Mostly, it should be just a proxy for the | 7 | /// crate's dependencies interact. Mostly, it should be just a proxy for the |
@@ -52,4 +52,12 @@ impl Module { | |||
52 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 52 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { |
53 | self.child_impl(db, name) | 53 | self.child_impl(db, name) |
54 | } | 54 | } |
55 | /// Finds a parent module. | ||
56 | pub fn parent(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { | ||
57 | self.parent_impl(db) | ||
58 | } | ||
59 | |||
60 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> Cancelable<PerNs<DefId>> { | ||
61 | self.resolve_path_impl(db, path) | ||
62 | } | ||
55 | } | 63 | } |
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 @@ | |||
1 | use ra_db::{CrateId, Cancelable, FileId}; | 1 | use ra_db::{CrateId, Cancelable, FileId}; |
2 | use ra_syntax::{AstNode, ast}; | 2 | use ra_syntax::{AstNode, ast}; |
3 | 3 | ||
4 | use crate::{HirFileId, db::HirDatabase, Crate, CrateDependency, AsName, DefId, DefLoc, DefKind, Name}; | 4 | use crate::{HirFileId, db::HirDatabase, Crate, CrateDependency, AsName, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def}; |
5 | 5 | ||
6 | use crate::code_model_api::Module; | 6 | use crate::code_model_api::Module; |
7 | 7 | ||
@@ -102,4 +102,58 @@ impl Module { | |||
102 | let module = Module::new(def_id); | 102 | let module = Module::new(def_id); |
103 | Ok(Some(module)) | 103 | Ok(Some(module)) |
104 | } | 104 | } |
105 | pub fn parent_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { | ||
106 | let loc = self.def_id.loc(db); | ||
107 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
108 | let parent_id = ctry!(loc.module_id.parent(&module_tree)); | ||
109 | let def_loc = DefLoc { | ||
110 | module_id: parent_id, | ||
111 | source_item_id: parent_id.source(&module_tree).0, | ||
112 | ..loc | ||
113 | }; | ||
114 | let def_id = def_loc.id(db); | ||
115 | let module = Module::new(def_id); | ||
116 | Ok(Some(module)) | ||
117 | } | ||
118 | pub fn resolve_path_impl( | ||
119 | &self, | ||
120 | db: &impl HirDatabase, | ||
121 | path: &Path, | ||
122 | ) -> Cancelable<PerNs<DefId>> { | ||
123 | let mut curr_per_ns = PerNs::types( | ||
124 | match path.kind { | ||
125 | PathKind::Crate => self.crate_root(db)?, | ||
126 | PathKind::Self_ | PathKind::Plain => self.clone(), | ||
127 | PathKind::Super => { | ||
128 | if let Some(p) = self.parent(db)? { | ||
129 | p | ||
130 | } else { | ||
131 | return Ok(PerNs::none()); | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | .def_id, | ||
136 | ); | ||
137 | |||
138 | let segments = &path.segments; | ||
139 | for name in segments.iter() { | ||
140 | let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { | ||
141 | r | ||
142 | } else { | ||
143 | return Ok(PerNs::none()); | ||
144 | }; | ||
145 | let module = match curr.resolve(db)? { | ||
146 | Def::Module(it) => it, | ||
147 | // TODO here would be the place to handle enum variants... | ||
148 | _ => return Ok(PerNs::none()), | ||
149 | }; | ||
150 | let scope = module.scope(db)?; | ||
151 | curr_per_ns = if let Some(r) = scope.get(&name) { | ||
152 | r.def_id | ||
153 | } else { | ||
154 | return Ok(PerNs::none()); | ||
155 | }; | ||
156 | } | ||
157 | Ok(curr_per_ns) | ||
158 | } | ||
105 | } | 159 | } |
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 { | |||
251 | fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { | 251 | fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { |
252 | tree.mods[self].parent | 252 | tree.mods[self].parent |
253 | } | 253 | } |
254 | fn parent(self, tree: &ModuleTree) -> Option<ModuleId> { | 254 | pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> { |
255 | let link = self.parent_link(tree)?; | 255 | let link = self.parent_link(tree)?; |
256 | Some(tree.links[link].owner) | 256 | Some(tree.links[link].owner) |
257 | } | 257 | } |
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<T> PerNs<T> { | |||
177 | } | 177 | } |
178 | 178 | ||
179 | pub fn take_types(self) -> Option<T> { | 179 | pub fn take_types(self) -> Option<T> { |
180 | self.types | 180 | self.take(Namespace::Types) |
181 | } | 181 | } |
182 | 182 | ||
183 | pub fn take_values(self) -> Option<T> { | 183 | pub fn take_values(self) -> Option<T> { |
184 | self.values | 184 | self.take(Namespace::Values) |
185 | } | 185 | } |
186 | 186 | ||
187 | pub fn get(&self, namespace: Namespace) -> Option<&T> { | 187 | pub fn get(&self, namespace: Namespace) -> Option<&T> { |