From 9bb11aee44f377fdf2ce7bed5c09ccbcf30f9b57 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 00:31:12 +0300 Subject: populate resolve from unresolved imports --- crates/ra_analysis/src/descriptors/module/mod.rs | 13 ++- .../ra_analysis/src/descriptors/module/nameres.rs | 100 ++++++++++++++++++--- 2 files changed, 97 insertions(+), 16 deletions(-) (limited to 'crates') 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 { /// The root of the tree this module is part of pub fn crate_root(&self) -> ModuleDescriptor { - generate(Some(self.clone()), |it| it.parent()) - .last() - .unwrap() + let root_id = self.module_id.crate_root(&self.tree); + ModuleDescriptor { + module_id: root_id, + ..self.clone() + } } /// `name` is `None` for the crate's root module @@ -205,6 +207,11 @@ impl ModuleId { let link = self.parent_link(tree)?; Some(tree.link(link).owner) } + fn crate_root(self, tree: &ModuleTree) -> ModuleId { + generate(Some(self), move |it| it.parent(tree)) + .last() + .unwrap() + } fn child(self, tree: &ModuleTree, name: &str) -> Option { let link = tree .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 { #[derive(Debug, Default)] struct ModuleItems { - items: FxHashMap, + items: FxHashMap, import_resolutions: FxHashMap, } +/// Resolution is basically `DefId` atm, but it should account for stuff like +/// multiple namespaces, ambiguity and errors. +#[derive(Debug, Clone)] +struct Resolution { + /// None for unresolved + def_id: Option, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] enum Namespace { Types, @@ -221,22 +229,27 @@ where { fn resolve(&mut self) { for (&module_id, items) in self.input.iter() { - self.populate_module( - module_id, - items, - ) + self.populate_module(module_id, items) + } + + for &module_id in self.input.keys() { + self.resolve_imports(module_id); } } - fn populate_module( - &mut self, - module_id: ModuleId, - input: &InputModuleItems, - ) { + fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) { let file_id = module_id.source(&self.module_tree).file_id(); let mut module_items = ModuleItems::default(); + for import in input.imports.iter() { + if let Some((_, name)) = import.segments.last() { + module_items + .items + .insert(name.clone(), Resolution { def_id: None }); + } + } + for item in input.items.iter() { if item.kind == MODULE { // handle submodules separatelly @@ -245,7 +258,10 @@ where let ptr = item.ptr.into_global(file_id); let def_loc = DefLoc::Item { ptr }; let def_id = self.db.id_maps().def_id(def_loc); - module_items.items.insert(item.name.clone(), def_id); + let resolution = Resolution { + def_id: Some(def_id), + }; + module_items.items.insert(item.name.clone(), resolution); } for (name, mod_id) in module_id.children(&self.module_tree) { @@ -254,11 +270,69 @@ where source_root: self.source_root, }; let def_id = self.db.id_maps().def_id(def_loc); - module_items.items.insert(name, def_id); + let resolution = Resolution { + def_id: Some(def_id), + }; + module_items.items.insert(name, resolution); } self.result.per_module.insert(module_id, module_items); } -} + fn resolve_imports(&mut self, module_id: ModuleId) { + for import in self.input[&module_id].imports.iter() { + self.resolve_import(module_id, import); + } + } + + fn resolve_import(&mut self, module_id: ModuleId, import: &Path) { + let mut curr = match import.kind { + // TODO: handle extern crates + PathKind::Abs => return, + PathKind::Self_ => module_id, + PathKind::Super => { + match module_id.parent(&self.module_tree) { + Some(it) => it, + // TODO: error + None => return, + } + } + PathKind::Crate => module_id.crate_root(&self.module_tree), + }; + + for (i, (ptr, name)) in import.segments.iter().enumerate() { + let is_last = i == import.segments.len() - 1; + + let def_id = match self.result.per_module[&curr].items.get(name) { + None => return, + Some(res) => match res.def_id { + Some(it) => it, + None => return, + }, + }; + + self.update(module_id, |items| { + items.import_resolutions.insert(*ptr, def_id); + }); + if !is_last { + curr = match self.db.id_maps().def_loc(def_id) { + DefLoc::Module { id, .. } => id, + _ => return, + } + } else { + self.update(module_id, |items| { + let res = Resolution { + def_id: Some(def_id), + }; + items.items.insert(name.clone(), res); + }) + } + } + } + + fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleItems)) { + let module_items = self.result.per_module.get_mut(&module_id).unwrap(); + f(module_items) + } +} -- cgit v1.2.3