From bcdcfa9df222667e6bfcbb1a8923bdc55bd57dc0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 20 Nov 2018 19:24:58 +0300 Subject: Some import resolution boilerplate --- .../ra_analysis/src/descriptors/module/nameres.rs | 156 +++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 crates/ra_analysis/src/descriptors/module/nameres.rs (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs new file mode 100644 index 000000000..137aa8b17 --- /dev/null +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -0,0 +1,156 @@ +//! Name resolution algorithm +use rustc_hash::FxHashMap; + +use ra_syntax::{ + SmolStr, SyntaxKind, + ast::{self, NameOwner} +}; + +use crate::{ + descriptors::module::ModuleId, + syntax_ptr::LocalSyntaxPtr, +}; + +/// A set of items and imports declared inside a module, without relation to +/// other modules. +/// +/// This stands in-between raw syntax and name resolution and alow us to avoid +/// recomputing name res: if `InputModuleItems` are the same, we can avoid +/// running name resolution. +#[derive(Debug, Default)] +struct InputModuleItems { + items: Vec, + glob_imports: Vec, + imports: Vec, +} + +#[derive(Debug, Clone)] +struct Path { + kind: PathKind, + segments: Vec, +} + +#[derive(Debug, Clone, Copy)] +enum PathKind { + Abs, + Self_, + Super, + Crate, +} + +#[derive(Debug)] +struct ItemMap { + per_module: FxHashMap, +} + +#[derive(Debug)] +struct ModuleItems { + items: FxHashMap>, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +enum Namespace { + Types, + Values, +} + +#[derive(Debug)] +struct PerNs { + types: Option, + values: Option, +} + +#[derive(Debug)] +struct ModuleItem { + ptr: LocalSyntaxPtr, + name: SmolStr, + kind: SyntaxKind, + vis: Vis, +} + +#[derive(Debug)] +enum Vis { + Priv, + Other, +} + +impl InputModuleItems { + fn new<'a>(items: impl Iterator>) -> InputModuleItems { + let mut res = InputModuleItems::default(); + for item in items { + res.add_item(item); + } + res + } + + fn add_item(&mut self, item: ast::ModuleItem) -> Option<()> { + match item { + ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(it)?), + ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(it)?), + ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?), + ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?), + ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?), + ast::ModuleItem::ImplItem(it) => { + // impls don't define items + } + ast::ModuleItem::UseItem(it) => self.add_use_item(it), + ast::ModuleItem::ExternCrateItem(it) => (), + ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?), + ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?), + ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?), + } + Some(()) + } + + fn add_use_item(&mut self, item: ast::UseItem) { + if let Some(tree) = item.use_tree() { + self.add_use_tree(None, tree); + } + } + + fn add_use_tree(&mut self, prefix: Option, tree: ast::UseTree) { + if let Some(use_tree_list) = tree.use_tree_list() { + let prefix = match tree.path() { + None => prefix, + Some(path) => match convert_path(prefix, path) { + Some(it) => Some(it), + None => return, // TODO: report errors somewhere + }, + }; + for tree in use_tree_list.use_trees() { + self.add_use_tree(prefix.clone(), tree); + } + } else { + if let Some(path) = tree.path() { + if let Some(path) = convert_path(prefix, path) { + if tree.has_star() { + &mut self.glob_imports + } else { + &mut self.imports + } + .push(path); + } + } + } + } +} + +fn convert_path(prefix: Option, path: ast::Path) -> Option { + prefix +} + +impl ModuleItem { + fn new<'a>(item: impl ast::NameOwner<'a>) -> Option { + let name = item.name()?.text(); + let ptr = LocalSyntaxPtr::new(item.syntax()); + let kind = item.syntax().kind(); + let vis = Vis::Other; + let res = ModuleItem { + ptr, + name, + kind, + vis, + }; + Some(res) + } +} -- cgit v1.2.3 From 8086107b6ac8555a226ceb294e2c633dfe36c6e1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 20 Nov 2018 19:40:37 +0300 Subject: implement path conversion --- .../ra_analysis/src/descriptors/module/nameres.rs | 45 +++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 137aa8b17..b65b6adb7 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -136,7 +136,50 @@ impl InputModuleItems { } fn convert_path(prefix: Option, path: ast::Path) -> Option { - prefix + let prefix = if let Some(qual) = path.qualifier() { + Some(convert_path(prefix, qual)?) + } else { + None + }; + let segment = path.segment()?; + let res = match segment.kind()? { + ast::PathSegmentKind::Name(name) => { + let mut res = prefix.unwrap_or_else(|| Path { + kind: PathKind::Abs, + segments: Vec::with_capacity(1), + }); + res.segments.push(name.text()); + res + } + ast::PathSegmentKind::CrateKw => { + if prefix.is_some() { + return None; + } + Path { + kind: PathKind::Crate, + segments: Vec::new(), + } + } + ast::PathSegmentKind::SelfKw => { + if prefix.is_some() { + return None; + } + Path { + kind: PathKind::Self_, + segments: Vec::new(), + } + } + ast::PathSegmentKind::SuperKw => { + if prefix.is_some() { + return None; + } + Path { + kind: PathKind::Super, + segments: Vec::new(), + } + } + }; + Some(res) } impl ModuleItem { -- cgit v1.2.3 From c54b51fdedd21b0367af7cb3fac3bc16d21b8cc1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 20 Nov 2018 21:12:15 +0300 Subject: add DefId --- crates/ra_analysis/src/descriptors/module/nameres.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index b65b6adb7..8002656d6 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -7,6 +7,7 @@ use ra_syntax::{ }; use crate::{ + loc2id::DefId, descriptors::module::ModuleId, syntax_ptr::LocalSyntaxPtr, }; @@ -45,7 +46,8 @@ struct ItemMap { #[derive(Debug)] struct ModuleItems { - items: FxHashMap>, + items: FxHashMap>, + import_resolutions: FxHashMap, } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -197,3 +199,14 @@ impl ModuleItem { Some(res) } } + +struct Resolver { + input: FxHashMap, + result: ModuleItems, +} + +impl Resolver { + fn resolve(&mut self){ + + } +} -- cgit v1.2.3 From 1cf92c3e286232be7e0d1370b88547ca0cb6f636 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 20 Nov 2018 21:17:14 +0300 Subject: remember spans with paths --- crates/ra_analysis/src/descriptors/module/nameres.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 8002656d6..18e8342b3 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -3,7 +3,7 @@ use rustc_hash::FxHashMap; use ra_syntax::{ SmolStr, SyntaxKind, - ast::{self, NameOwner} + ast::{self, NameOwner, AstNode} }; use crate::{ @@ -28,7 +28,7 @@ struct InputModuleItems { #[derive(Debug, Clone)] struct Path { kind: PathKind, - segments: Vec, + segments: Vec<(LocalSyntaxPtr, SmolStr)>, } #[derive(Debug, Clone, Copy)] @@ -150,7 +150,8 @@ fn convert_path(prefix: Option, path: ast::Path) -> Option { kind: PathKind::Abs, segments: Vec::with_capacity(1), }); - res.segments.push(name.text()); + let ptr = LocalSyntaxPtr::new(name.syntax()); + res.segments.push((ptr, name.text())); res } ast::PathSegmentKind::CrateKw => { -- cgit v1.2.3 From cc8163439f65138c0945c37d6bddc64ced2d2143 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 20 Nov 2018 21:50:22 +0300 Subject: populate modules --- .../ra_analysis/src/descriptors/module/nameres.rs | 74 +++++++++++++++++++--- 1 file changed, 64 insertions(+), 10 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 18e8342b3..6ff8e61f5 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -1,15 +1,21 @@ //! Name resolution algorithm +use std::sync::Arc; + use rustc_hash::FxHashMap; use ra_syntax::{ - SmolStr, SyntaxKind, + SmolStr, SyntaxKind::{self, *}, ast::{self, NameOwner, AstNode} }; use crate::{ - loc2id::DefId, - descriptors::module::ModuleId, - syntax_ptr::LocalSyntaxPtr, + loc2id::{DefId, DefLoc}, + descriptors::{ + DescriptorDatabase, + module::{ModuleId, ModuleTree}, + }, + syntax_ptr::{LocalSyntaxPtr, SyntaxPtr}, + input::SourceRootId, }; /// A set of items and imports declared inside a module, without relation to @@ -44,9 +50,9 @@ struct ItemMap { per_module: FxHashMap, } -#[derive(Debug)] +#[derive(Debug, Default)] struct ModuleItems { - items: FxHashMap>, + items: FxHashMap, import_resolutions: FxHashMap, } @@ -201,13 +207,61 @@ impl ModuleItem { } } -struct Resolver { +struct Resolver<'a, DB> { + db: &'a DB, + source_root: SourceRootId, + module_tree: Arc, input: FxHashMap, - result: ModuleItems, + result: ItemMap, +} + +impl<'a, DB> Resolver<'a, DB> +where + DB: DescriptorDatabase, +{ + fn resolve(&mut self) { + for (&module_id, items) in self.input.iter() { + populate_module( + self.db, + self.source_root, + &*self.module_tree, + &mut self.result, + module_id, + items, + ) + } + } } -impl Resolver { - fn resolve(&mut self){ +fn populate_module( + db: &impl DescriptorDatabase, + source_root: SourceRootId, + module_tree: &ModuleTree, + item_map: &mut ItemMap, + module_id: ModuleId, + input: &InputModuleItems, +) { + let file_id = module_id.source(module_tree).file_id(); + let mut module_items = ModuleItems::default(); + + for item in input.items.iter() { + if item.kind == MODULE { + // handle submodules separatelly + continue; + } + let ptr = item.ptr.into_global(file_id); + let def_loc = DefLoc::Item { ptr }; + let def_id = db.id_maps().def_id(def_loc); + module_items.items.insert(item.name.clone(), def_id); + } + + for (name, mod_id) in module_id.children(module_tree) { + let def_loc = DefLoc::Module { + id: mod_id, + source_root, + }; } + + item_map.per_module.insert(module_id, module_items); } -- cgit v1.2.3 From aab71bff8eb89fb65f4aba8e90df2ae586ecb0a6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 20 Nov 2018 23:36:53 +0300 Subject: move to method --- .../ra_analysis/src/descriptors/module/nameres.rs | 63 +++++++++++----------- 1 file changed, 30 insertions(+), 33 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 6ff8e61f5..44059e5c3 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -209,9 +209,9 @@ impl ModuleItem { struct Resolver<'a, DB> { db: &'a DB, + input: &'a FxHashMap, source_root: SourceRootId, module_tree: Arc, - input: FxHashMap, result: ItemMap, } @@ -221,47 +221,44 @@ where { fn resolve(&mut self) { for (&module_id, items) in self.input.iter() { - populate_module( - self.db, - self.source_root, - &*self.module_tree, - &mut self.result, + self.populate_module( module_id, items, ) } } -} -fn populate_module( - db: &impl DescriptorDatabase, - source_root: SourceRootId, - module_tree: &ModuleTree, - item_map: &mut ItemMap, - module_id: ModuleId, - input: &InputModuleItems, -) { - let file_id = module_id.source(module_tree).file_id(); + 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(); + let mut module_items = ModuleItems::default(); - for item in input.items.iter() { - if item.kind == MODULE { - // handle submodules separatelly - continue; + for item in input.items.iter() { + if item.kind == MODULE { + // handle submodules separatelly + continue; + } + 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 ptr = item.ptr.into_global(file_id); - let def_loc = DefLoc::Item { ptr }; - let def_id = db.id_maps().def_id(def_loc); - module_items.items.insert(item.name.clone(), def_id); - } - for (name, mod_id) in module_id.children(module_tree) { - let def_loc = DefLoc::Module { - id: mod_id, - source_root, - }; - } + for (name, mod_id) in module_id.children(&self.module_tree) { + let def_loc = DefLoc::Module { + id: mod_id, + source_root: self.source_root, + }; + let def_id = self.db.id_maps().def_id(def_loc); + module_items.items.insert(name, def_id); + } - item_map.per_module.insert(module_id, module_items); + self.result.per_module.insert(module_id, module_items); + } } + + -- cgit v1.2.3 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 --- .../ra_analysis/src/descriptors/module/nameres.rs | 100 ++++++++++++++++++--- 1 file changed, 87 insertions(+), 13 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') 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 From 36aad851383c7fd1ca5ffaa99ba8cc96b85378c1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 00:39:50 +0300 Subject: add item map query --- crates/ra_analysis/src/descriptors/module/nameres.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 058e64ad1..657e5bd1c 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -9,6 +9,7 @@ use ra_syntax::{ }; use crate::{ + Cancelable, loc2id::{DefId, DefLoc}, descriptors::{ DescriptorDatabase, @@ -45,12 +46,21 @@ enum PathKind { Crate, } -#[derive(Debug)] -struct ItemMap { +pub(crate) fn item_map( + db: &impl DescriptorDatabase, + source_root: SourceRootId, +) -> Cancelable> { + unimplemented!() +} + +/// Item map is the result of the name resolution. Item map contains, for each +/// module, the set of visible items. +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct ItemMap { per_module: FxHashMap, } -#[derive(Debug, Default)] +#[derive(Debug, Default, PartialEq, Eq)] struct ModuleItems { items: FxHashMap, import_resolutions: FxHashMap, @@ -58,7 +68,7 @@ struct ModuleItems { /// Resolution is basically `DefId` atm, but it should account for stuff like /// multiple namespaces, ambiguity and errors. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] struct Resolution { /// None for unresolved def_id: Option, -- cgit v1.2.3 From 02c4f823485fb5302b8f8eb6fee84122ca73979c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 11:16:46 +0300 Subject: simple test for item map --- .../ra_analysis/src/descriptors/module/nameres.rs | 119 ++++++++++++++++++--- 1 file changed, 104 insertions(+), 15 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 657e5bd1c..2fae93c9d 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -5,7 +5,7 @@ use rustc_hash::FxHashMap; use ra_syntax::{ SmolStr, SyntaxKind::{self, *}, - ast::{self, NameOwner, AstNode} + ast::{self, NameOwner, AstNode, ModuleItemOwner} }; use crate::{ @@ -13,9 +13,9 @@ use crate::{ loc2id::{DefId, DefLoc}, descriptors::{ DescriptorDatabase, - module::{ModuleId, ModuleTree}, + module::{ModuleId, ModuleTree, ModuleSourceNode}, }, - syntax_ptr::{LocalSyntaxPtr, SyntaxPtr}, + syntax_ptr::{LocalSyntaxPtr}, input::SourceRootId, }; @@ -25,20 +25,20 @@ use crate::{ /// This stands in-between raw syntax and name resolution and alow us to avoid /// recomputing name res: if `InputModuleItems` are the same, we can avoid /// running name resolution. -#[derive(Debug, Default)] -struct InputModuleItems { +#[derive(Debug, Default, PartialEq, Eq)] +pub(crate) struct InputModuleItems { items: Vec, glob_imports: Vec, imports: Vec, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] struct Path { kind: PathKind, segments: Vec<(LocalSyntaxPtr, SmolStr)>, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] enum PathKind { Abs, Self_, @@ -46,16 +46,58 @@ enum PathKind { Crate, } +pub(crate) fn input_module_items( + db: &impl DescriptorDatabase, + source_root: SourceRootId, + module_id: ModuleId, +) -> Cancelable> { + let module_tree = db._module_tree(source_root)?; + let source = module_id.source(&module_tree); + let res = match source.resolve(db) { + ModuleSourceNode::SourceFile(it) => { + let items = it.borrowed().items(); + InputModuleItems::new(items) + } + ModuleSourceNode::Module(it) => { + let items = it + .borrowed() + .item_list() + .into_iter() + .flat_map(|it| it.items()); + InputModuleItems::new(items) + } + }; + Ok(Arc::new(res)) +} + pub(crate) fn item_map( db: &impl DescriptorDatabase, source_root: SourceRootId, ) -> Cancelable> { - unimplemented!() + let module_tree = db._module_tree(source_root)?; + let input = module_tree + .modules() + .map(|id| { + let items = db._input_module_items(source_root, id)?; + Ok((id, items)) + }) + .collect::>>()?; + + let mut resolver = Resolver { + db: db, + input: &input, + source_root, + module_tree, + result: ItemMap::default(), + }; + resolver.resolve()?; + let res = resolver.result; + Ok(Arc::new(res)) } /// Item map is the result of the name resolution. Item map contains, for each /// module, the set of visible items. -#[derive(Debug, PartialEq, Eq)] +#[derive(Default, Debug, PartialEq, Eq)] pub(crate) struct ItemMap { per_module: FxHashMap, } @@ -86,7 +128,7 @@ struct PerNs { values: Option, } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] struct ModuleItem { ptr: LocalSyntaxPtr, name: SmolStr, @@ -94,7 +136,7 @@ struct ModuleItem { vis: Vis, } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] enum Vis { Priv, Other, @@ -116,11 +158,13 @@ impl InputModuleItems { ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?), - ast::ModuleItem::ImplItem(it) => { + ast::ModuleItem::ImplItem(_) => { // impls don't define items } ast::ModuleItem::UseItem(it) => self.add_use_item(it), - ast::ModuleItem::ExternCrateItem(it) => (), + ast::ModuleItem::ExternCrateItem(_) => { + // TODO + } ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?), @@ -227,7 +271,7 @@ impl ModuleItem { struct Resolver<'a, DB> { db: &'a DB, - input: &'a FxHashMap, + input: &'a FxHashMap>, source_root: SourceRootId, module_tree: Arc, result: ItemMap, @@ -237,14 +281,16 @@ impl<'a, DB> Resolver<'a, DB> where DB: DescriptorDatabase, { - fn resolve(&mut self) { + fn resolve(&mut self) -> Cancelable<()> { for (&module_id, items) in self.input.iter() { self.populate_module(module_id, items) } for &module_id in self.input.keys() { + crate::db::check_canceled(self.db)?; self.resolve_imports(module_id); } + Ok(()) } fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) { @@ -346,3 +392,46 @@ where f(module_items) } } + +#[cfg(test)] +mod tests { + use crate::{ + mock_analysis::analysis_and_position, + descriptors::{DescriptorDatabase, module::ModuleDescriptor}, + input::FilesDatabase, +}; + use super::*; + + fn item_map(fixture: &str) -> (Arc, ModuleId) { + let (analysis, pos) = analysis_and_position(fixture); + let db = analysis.imp.db; + let source_root = db.file_source_root(pos.file_id); + let descr = ModuleDescriptor::guess_from_position(&*db, pos) + .unwrap() + .unwrap(); + let module_id = descr.module_id; + (db._item_map(source_root).unwrap(), module_id) + } + + #[test] + fn test_item_map() { + let (item_map, module_id) = item_map( + " + //- /lib.rs + mod foo; + + use crate::foo::bar::Baz; + <|> + + //- /foo/mod.rs + pub mod bar; + + //- /foo/bar.rs + pub struct Baz; + ", + ); + let name = SmolStr::from("Baz"); + let resolution = &item_map.per_module[&module_id].items[&name]; + assert!(resolution.def_id.is_some()); + } +} -- cgit v1.2.3 From ff75ad13a45dc603d445b1491d65e17c4db9addb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 11:18:43 +0300 Subject: Measure time --- crates/ra_analysis/src/descriptors/module/nameres.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 2fae93c9d..a354fa54c 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -1,5 +1,8 @@ //! Name resolution algorithm -use std::sync::Arc; +use std::{ + sync::Arc, + time::Instant, +}; use rustc_hash::FxHashMap; @@ -74,6 +77,7 @@ pub(crate) fn item_map( db: &impl DescriptorDatabase, source_root: SourceRootId, ) -> Cancelable> { + let start = Instant::now(); let module_tree = db._module_tree(source_root)?; let input = module_tree .modules() @@ -92,6 +96,8 @@ pub(crate) fn item_map( }; resolver.resolve()?; let res = resolver.result; + let elapsed = start.elapsed(); + log::info!("item_map: {:?}", elapsed); Ok(Arc::new(res)) } -- cgit v1.2.3 From b70b6bce19981df5d0cda6a0193fb9b07da6ea51 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 11:35:25 +0300 Subject: Move to top --- .../ra_analysis/src/descriptors/module/nameres.rs | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index a354fa54c..34127e78f 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -22,6 +22,19 @@ use crate::{ input::SourceRootId, }; +/// Item map is the result of the name resolution. Item map contains, for each +/// module, the set of visible items. +#[derive(Default, Debug, PartialEq, Eq)] +pub(crate) struct ItemMap { + per_module: FxHashMap, +} + +#[derive(Debug, Default, PartialEq, Eq)] +struct ModuleItems { + items: FxHashMap, + import_resolutions: FxHashMap, +} + /// A set of items and imports declared inside a module, without relation to /// other modules. /// @@ -101,19 +114,6 @@ pub(crate) fn item_map( Ok(Arc::new(res)) } -/// Item map is the result of the name resolution. Item map contains, for each -/// module, the set of visible items. -#[derive(Default, Debug, PartialEq, Eq)] -pub(crate) struct ItemMap { - per_module: FxHashMap, -} - -#[derive(Debug, Default, PartialEq, Eq)] -struct ModuleItems { - 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, PartialEq, Eq)] -- cgit v1.2.3 From 049f8df93cca05af395ce873738dc85d5a25f3fc Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 12:57:05 +0300 Subject: switch completion to new scope --- .../ra_analysis/src/descriptors/module/nameres.rs | 60 +++++++++++++--------- 1 file changed, 35 insertions(+), 25 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module/nameres.rs') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 34127e78f..c5bf467ca 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; use ra_syntax::{ SmolStr, SyntaxKind::{self, *}, - ast::{self, NameOwner, AstNode, ModuleItemOwner} + ast::{self, AstNode, ModuleItemOwner} }; use crate::{ @@ -26,13 +26,13 @@ use crate::{ /// module, the set of visible items. #[derive(Default, Debug, PartialEq, Eq)] pub(crate) struct ItemMap { - per_module: FxHashMap, + pub(crate) per_module: FxHashMap, } -#[derive(Debug, Default, PartialEq, Eq)] -struct ModuleItems { - items: FxHashMap, - import_resolutions: FxHashMap, +#[derive(Debug, Default, PartialEq, Eq, Clone)] +pub(crate) struct ModuleScope { + pub(crate) items: FxHashMap, + pub(crate) import_resolutions: FxHashMap, } /// A set of items and imports declared inside a module, without relation to @@ -117,22 +117,25 @@ pub(crate) fn item_map( /// Resolution is basically `DefId` atm, but it should account for stuff like /// multiple namespaces, ambiguity and errors. #[derive(Debug, Clone, PartialEq, Eq)] -struct Resolution { +pub(crate) struct Resolution { /// None for unresolved - def_id: Option, + pub(crate) def_id: Option, + /// ident by whitch this is imported into local scope. + /// TODO: make this offset-independent. + pub(crate) import_name: Option, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -enum Namespace { - Types, - Values, -} +// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +// enum Namespace { +// Types, +// Values, +// } -#[derive(Debug)] -struct PerNs { - types: Option, - values: Option, -} +// #[derive(Debug)] +// struct PerNs { +// types: Option, +// values: Option, +// } #[derive(Debug, PartialEq, Eq)] struct ModuleItem { @@ -144,7 +147,7 @@ struct ModuleItem { #[derive(Debug, PartialEq, Eq)] enum Vis { - Priv, + // Priv, Other, } @@ -302,13 +305,17 @@ where 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(); + let mut module_items = ModuleScope::default(); for import in input.imports.iter() { - if let Some((_, name)) = import.segments.last() { - module_items - .items - .insert(name.clone(), Resolution { def_id: None }); + if let Some((ptr, name)) = import.segments.last() { + module_items.items.insert( + name.clone(), + Resolution { + def_id: None, + import_name: Some(*ptr), + }, + ); } } @@ -322,6 +329,7 @@ where let def_id = self.db.id_maps().def_id(def_loc); let resolution = Resolution { def_id: Some(def_id), + import_name: None, }; module_items.items.insert(item.name.clone(), resolution); } @@ -334,6 +342,7 @@ where let def_id = self.db.id_maps().def_id(def_loc); let resolution = Resolution { def_id: Some(def_id), + import_name: None, }; module_items.items.insert(name, resolution); } @@ -386,6 +395,7 @@ where self.update(module_id, |items| { let res = Resolution { def_id: Some(def_id), + import_name: Some(*ptr), }; items.items.insert(name.clone(), res); }) @@ -393,7 +403,7 @@ where } } - fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleItems)) { + fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleScope)) { let module_items = self.result.per_module.get_mut(&module_id).unwrap(); f(module_items) } -- cgit v1.2.3