From f4860870dae309f5287a287de0aa3a1a1b1de36b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 27 Nov 2018 16:55:56 +0300 Subject: [PATCH] scope-based resolve path --- .../src/completion/reference_completion.rs | 16 +++---- .../ra_analysis/src/descriptors/module/mod.rs | 47 +++++++++++++++---- .../src/descriptors/module/nameres.rs | 11 ++++- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs index 924d2440f6..a0af591783 100644 --- a/crates/ra_analysis/src/completion/reference_completion.rs +++ b/crates/ra_analysis/src/completion/reference_completion.rs @@ -42,8 +42,7 @@ pub(super) fn completions( let module_scope = module.scope(db)?; acc.extend( module_scope - .items - .iter() + .entries() .filter(|(_name, res)| { // Don't expose this item match res.import { @@ -162,14 +161,11 @@ fn complete_path( Some(it) => it, }; let module_scope = target_module.scope(db)?; - let completions = module_scope - .items - .iter() - .map(|(name, _res)| CompletionItem { - label: name.to_string(), - lookup: None, - snippet: None, - }); + let completions = module_scope.entries().map(|(name, _res)| CompletionItem { + label: name.to_string(), + lookup: None, + snippet: None, + }); acc.extend(completions); Ok(()) } diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index 6890d8b097..51bc84bf1c 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs @@ -17,6 +17,7 @@ use crate::{ descriptors::{Path, PathKind, DescriptorDatabase}, input::SourceRootId, arena::{Arena, Id}, + loc2id::DefLoc, }; pub(crate) use self::nameres::ModuleScope; @@ -76,6 +77,20 @@ impl ModuleDescriptor { Ok(res) } + fn new( + db: &impl DescriptorDatabase, + source_root_id: SourceRootId, + module_id: ModuleId, + ) -> Cancelable { + let module_tree = db._module_tree(source_root_id)?; + let res = ModuleDescriptor { + tree: module_tree, + source_root_id, + module_id, + }; + Ok(res) + } + /// Returns `mod foo;` or `mod foo {}` node whihc declared this module. /// Returns `None` for the root module pub fn parent_link_source( @@ -133,25 +148,37 @@ impl ModuleDescriptor { Ok(res) } - pub(crate) fn resolve_path(&self, db: &impl DescriptorDatabase, path: Path) -> Cancelable> { - let res = match self.do_resolve_path(path) { - None => return Ok(None), - Some(it) => it, + pub(crate) fn resolve_path( + &self, + db: &impl DescriptorDatabase, + path: Path, + ) -> Cancelable> { + macro_rules! ctry { + ($expr:expr) => { + match $expr { + None => return Ok(None), + Some(it) => it, + } + }; }; - Ok(Some(res)) - } - fn do_resolve_path(&self, path: Path) -> Option { let mut curr = match path.kind { PathKind::Crate => self.crate_root(), PathKind::Self_ | PathKind::Plain => self.clone(), - PathKind::Super => self.parent()?, + PathKind::Super => ctry!(self.parent()), }; + let segments = path.segments; for name in segments { - curr = curr.child(&name)?; + let scope = curr.scope(db)?; + let def_id = ctry!(ctry!(scope.get(&name)).def_id); + curr = match db.id_maps().def_loc(def_id) { + DefLoc::Module { id, source_root } => ModuleDescriptor::new(db, source_root, id)?, + _ => return Ok(None), + }; } - Some(curr) + + Ok(Some(curr)) } pub fn problems(&self, db: &impl DescriptorDatabase) -> Vec<(SyntaxNode, Problem)> { diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index d347a69b01..d2964f67f9 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -103,7 +103,16 @@ pub(crate) struct ItemMap { #[derive(Debug, Default, PartialEq, Eq, Clone)] pub(crate) struct ModuleScope { - pub(crate) items: FxHashMap, + items: FxHashMap, +} + +impl ModuleScope { + pub(crate) fn entries<'a>(&'a self) -> impl Iterator + 'a { + self.items.iter() + } + pub(crate) fn get(&self, name: &SmolStr) -> Option<&Resolution> { + self.items.get(name) + } } /// A set of items and imports declared inside a module, without relation to