diff options
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/mod.rs | 13 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/nameres.rs | 100 |
2 files changed, 97 insertions, 16 deletions
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index f49e7f909..2d0bfa64c 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs | |||
@@ -103,9 +103,11 @@ impl ModuleDescriptor { | |||
103 | 103 | ||
104 | /// The root of the tree this module is part of | 104 | /// The root of the tree this module is part of |
105 | pub fn crate_root(&self) -> ModuleDescriptor { | 105 | pub fn crate_root(&self) -> ModuleDescriptor { |
106 | generate(Some(self.clone()), |it| it.parent()) | 106 | let root_id = self.module_id.crate_root(&self.tree); |
107 | .last() | 107 | ModuleDescriptor { |
108 | .unwrap() | 108 | module_id: root_id, |
109 | ..self.clone() | ||
110 | } | ||
109 | } | 111 | } |
110 | 112 | ||
111 | /// `name` is `None` for the crate's root module | 113 | /// `name` is `None` for the crate's root module |
@@ -205,6 +207,11 @@ impl ModuleId { | |||
205 | let link = self.parent_link(tree)?; | 207 | let link = self.parent_link(tree)?; |
206 | Some(tree.link(link).owner) | 208 | Some(tree.link(link).owner) |
207 | } | 209 | } |
210 | fn crate_root(self, tree: &ModuleTree) -> ModuleId { | ||
211 | generate(Some(self), move |it| it.parent(tree)) | ||
212 | .last() | ||
213 | .unwrap() | ||
214 | } | ||
208 | fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { | 215 | fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { |
209 | let link = tree | 216 | let link = tree |
210 | .module(self) | 217 | .module(self) |
diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 44059e5c3..058e64ad1 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs | |||
@@ -52,10 +52,18 @@ struct ItemMap { | |||
52 | 52 | ||
53 | #[derive(Debug, Default)] | 53 | #[derive(Debug, Default)] |
54 | struct ModuleItems { | 54 | struct ModuleItems { |
55 | items: FxHashMap<SmolStr, DefId>, | 55 | items: FxHashMap<SmolStr, Resolution>, |
56 | import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>, | 56 | import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>, |
57 | } | 57 | } |
58 | 58 | ||
59 | /// Resolution is basically `DefId` atm, but it should account for stuff like | ||
60 | /// multiple namespaces, ambiguity and errors. | ||
61 | #[derive(Debug, Clone)] | ||
62 | struct Resolution { | ||
63 | /// None for unresolved | ||
64 | def_id: Option<DefId>, | ||
65 | } | ||
66 | |||
59 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | 67 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
60 | enum Namespace { | 68 | enum Namespace { |
61 | Types, | 69 | Types, |
@@ -221,22 +229,27 @@ where | |||
221 | { | 229 | { |
222 | fn resolve(&mut self) { | 230 | fn resolve(&mut self) { |
223 | for (&module_id, items) in self.input.iter() { | 231 | for (&module_id, items) in self.input.iter() { |
224 | self.populate_module( | 232 | self.populate_module(module_id, items) |
225 | module_id, | 233 | } |
226 | items, | 234 | |
227 | ) | 235 | for &module_id in self.input.keys() { |
236 | self.resolve_imports(module_id); | ||
228 | } | 237 | } |
229 | } | 238 | } |
230 | 239 | ||
231 | fn populate_module( | 240 | fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) { |
232 | &mut self, | ||
233 | module_id: ModuleId, | ||
234 | input: &InputModuleItems, | ||
235 | ) { | ||
236 | let file_id = module_id.source(&self.module_tree).file_id(); | 241 | let file_id = module_id.source(&self.module_tree).file_id(); |
237 | 242 | ||
238 | let mut module_items = ModuleItems::default(); | 243 | let mut module_items = ModuleItems::default(); |
239 | 244 | ||
245 | for import in input.imports.iter() { | ||
246 | if let Some((_, name)) = import.segments.last() { | ||
247 | module_items | ||
248 | .items | ||
249 | .insert(name.clone(), Resolution { def_id: None }); | ||
250 | } | ||
251 | } | ||
252 | |||
240 | for item in input.items.iter() { | 253 | for item in input.items.iter() { |
241 | if item.kind == MODULE { | 254 | if item.kind == MODULE { |
242 | // handle submodules separatelly | 255 | // handle submodules separatelly |
@@ -245,7 +258,10 @@ where | |||
245 | let ptr = item.ptr.into_global(file_id); | 258 | let ptr = item.ptr.into_global(file_id); |
246 | let def_loc = DefLoc::Item { ptr }; | 259 | let def_loc = DefLoc::Item { ptr }; |
247 | let def_id = self.db.id_maps().def_id(def_loc); | 260 | let def_id = self.db.id_maps().def_id(def_loc); |
248 | module_items.items.insert(item.name.clone(), def_id); | 261 | let resolution = Resolution { |
262 | def_id: Some(def_id), | ||
263 | }; | ||
264 | module_items.items.insert(item.name.clone(), resolution); | ||
249 | } | 265 | } |
250 | 266 | ||
251 | for (name, mod_id) in module_id.children(&self.module_tree) { | 267 | for (name, mod_id) in module_id.children(&self.module_tree) { |
@@ -254,11 +270,69 @@ where | |||
254 | source_root: self.source_root, | 270 | source_root: self.source_root, |
255 | }; | 271 | }; |
256 | let def_id = self.db.id_maps().def_id(def_loc); | 272 | let def_id = self.db.id_maps().def_id(def_loc); |
257 | module_items.items.insert(name, def_id); | 273 | let resolution = Resolution { |
274 | def_id: Some(def_id), | ||
275 | }; | ||
276 | module_items.items.insert(name, resolution); | ||
258 | } | 277 | } |
259 | 278 | ||
260 | self.result.per_module.insert(module_id, module_items); | 279 | self.result.per_module.insert(module_id, module_items); |
261 | } | 280 | } |
262 | } | ||
263 | 281 | ||
282 | fn resolve_imports(&mut self, module_id: ModuleId) { | ||
283 | for import in self.input[&module_id].imports.iter() { | ||
284 | self.resolve_import(module_id, import); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | fn resolve_import(&mut self, module_id: ModuleId, import: &Path) { | ||
289 | let mut curr = match import.kind { | ||
290 | // TODO: handle extern crates | ||
291 | PathKind::Abs => return, | ||
292 | PathKind::Self_ => module_id, | ||
293 | PathKind::Super => { | ||
294 | match module_id.parent(&self.module_tree) { | ||
295 | Some(it) => it, | ||
296 | // TODO: error | ||
297 | None => return, | ||
298 | } | ||
299 | } | ||
300 | PathKind::Crate => module_id.crate_root(&self.module_tree), | ||
301 | }; | ||
302 | |||
303 | for (i, (ptr, name)) in import.segments.iter().enumerate() { | ||
304 | let is_last = i == import.segments.len() - 1; | ||
305 | |||
306 | let def_id = match self.result.per_module[&curr].items.get(name) { | ||
307 | None => return, | ||
308 | Some(res) => match res.def_id { | ||
309 | Some(it) => it, | ||
310 | None => return, | ||
311 | }, | ||
312 | }; | ||
313 | |||
314 | self.update(module_id, |items| { | ||
315 | items.import_resolutions.insert(*ptr, def_id); | ||
316 | }); | ||
264 | 317 | ||
318 | if !is_last { | ||
319 | curr = match self.db.id_maps().def_loc(def_id) { | ||
320 | DefLoc::Module { id, .. } => id, | ||
321 | _ => return, | ||
322 | } | ||
323 | } else { | ||
324 | self.update(module_id, |items| { | ||
325 | let res = Resolution { | ||
326 | def_id: Some(def_id), | ||
327 | }; | ||
328 | items.items.insert(name.clone(), res); | ||
329 | }) | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | |||
334 | fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleItems)) { | ||
335 | let module_items = self.result.per_module.get_mut(&module_id).unwrap(); | ||
336 | f(module_items) | ||
337 | } | ||
338 | } | ||