From 82c088137abe2ed834433634f0f7641a601a21fd Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 16:02:34 +0300 Subject: Remove import_resolutions It's cheaper to re-query this info anyway --- crates/ra_analysis/src/descriptors/module/nameres.rs | 5 ----- 1 file changed, 5 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index c5bf467ca..d69cc6e4d 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -32,7 +32,6 @@ pub(crate) struct ItemMap { #[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 @@ -382,10 +381,6 @@ where }, }; - 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, -- cgit v1.2.3 From 8954d4dc67fc3cf519a9855b974846cfcb8c53b2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 16:15:15 +0300 Subject: Introduce Import struct --- .../ra_analysis/src/descriptors/module/nameres.rs | 69 ++++++++++++++-------- 1 file changed, 44 insertions(+), 25 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index d69cc6e4d..fb315a870 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -43,14 +43,26 @@ pub(crate) struct ModuleScope { #[derive(Debug, Default, PartialEq, Eq)] pub(crate) struct InputModuleItems { items: Vec, - glob_imports: Vec, - imports: Vec, + imports: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +struct Import { + path: Path, + kind: ImportKind, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum ImportKind { + Glob, + // TODO: make offset independent + Named(LocalSyntaxPtr), } #[derive(Debug, Clone, PartialEq, Eq)] struct Path { kind: PathKind, - segments: Vec<(LocalSyntaxPtr, SmolStr)>, + segments: Vec, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -199,14 +211,15 @@ impl InputModuleItems { 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 + if let Some(ast_path) = tree.path() { + if let Some(path) = convert_path(prefix, ast_path) { + let kind = if tree.has_star() { + ImportKind::Glob } else { - &mut self.imports - } - .push(path); + let ptr = LocalSyntaxPtr::new(ast_path.segment().unwrap().syntax()); + ImportKind::Named(ptr) + }; + self.imports.push(Import { kind, path }) } } } @@ -226,8 +239,7 @@ fn convert_path(prefix: Option, path: ast::Path) -> Option { kind: PathKind::Abs, segments: Vec::with_capacity(1), }); - let ptr = LocalSyntaxPtr::new(name.syntax()); - res.segments.push((ptr, name.text())); + res.segments.push(name.text()); res } ast::PathSegmentKind::CrateKw => { @@ -307,14 +319,16 @@ where let mut module_items = ModuleScope::default(); for import in input.imports.iter() { - if let Some((ptr, name)) = import.segments.last() { - module_items.items.insert( - name.clone(), - Resolution { - def_id: None, - import_name: Some(*ptr), - }, - ); + if let Some(name) = import.path.segments.iter().last() { + if let ImportKind::Named(ptr) = import.kind { + module_items.items.insert( + name.clone(), + Resolution { + def_id: None, + import_name: Some(ptr), + }, + ); + } } } @@ -355,8 +369,13 @@ where } } - fn resolve_import(&mut self, module_id: ModuleId, import: &Path) { - let mut curr = match import.kind { + fn resolve_import(&mut self, module_id: ModuleId, import: &Import) { + let ptr = match import.kind { + ImportKind::Glob => return, + ImportKind::Named(ptr) => ptr, + }; + + let mut curr = match import.path.kind { // TODO: handle extern crates PathKind::Abs => return, PathKind::Self_ => module_id, @@ -370,8 +389,8 @@ where 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; + for (i, name) in import.path.segments.iter().enumerate() { + let is_last = i == import.path.segments.len() - 1; let def_id = match self.result.per_module[&curr].items.get(name) { None => return, @@ -390,7 +409,7 @@ where self.update(module_id, |items| { let res = Resolution { def_id: Some(def_id), - import_name: Some(*ptr), + import_name: Some(ptr), }; items.items.insert(name.clone(), res); }) -- cgit v1.2.3 From d47075af5275bcf4f22b9c8ab00027f7828d640d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 16:16:54 +0300 Subject: move path to descriptors --- crates/ra_analysis/src/descriptors/module/nameres.rs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index fb315a870..16f1bbd1e 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -15,6 +15,7 @@ use crate::{ Cancelable, loc2id::{DefId, DefLoc}, descriptors::{ + Path, PathKind, DescriptorDatabase, module::{ModuleId, ModuleTree, ModuleSourceNode}, }, @@ -59,20 +60,6 @@ enum ImportKind { Named(LocalSyntaxPtr), } -#[derive(Debug, Clone, PartialEq, Eq)] -struct Path { - kind: PathKind, - segments: Vec, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum PathKind { - Abs, - Self_, - Super, - Crate, -} - pub(crate) fn input_module_items( db: &impl DescriptorDatabase, source_root: SourceRootId, -- cgit v1.2.3 From 18000ba864cd076141778fd692b3853716adb683 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 17:07:44 +0300 Subject: docs --- crates/ra_analysis/src/descriptors/module/nameres.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'crates/ra_analysis/src/descriptors/module') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 16f1bbd1e..526e42af3 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -1,4 +1,19 @@ -//! Name resolution algorithm +//! Name resolution algorithm. The end result of the algorithm is `ItemMap`: a +//! map with maps each module to it's scope: the set of items, visible in the +//! module. That is, we only resolve imports here, name resolution of item +//! bodies will be done in a separate step. +//! +//! Like Rustc, we use an interative per-crate algorithm: we start with scopes +//! containing only directly defined items, and then iteratively resolve +//! imports. +//! +//! To make this work nicely in the IDE scenarios, we place `InputModuleItems` +//! in between raw syntax and name resolution. `InputModuleItems` are computed +//! using only the module's syntax, and it is all directly defined items plus +//! imports. The plain is to make `InputModuleItems` independent of local +//! modifications (that is, typing inside a function shold not change IMIs), +//! such that the results of name resolution can be preserved unless the module +//! structure itself is modified. use std::{ sync::Arc, time::Instant, -- cgit v1.2.3 From 5a87a24f8288d905428db755c7ea806640b6ac1d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 17:18:26 +0300 Subject: move Path --- .../ra_analysis/src/descriptors/module/nameres.rs | 82 ++-------------------- 1 file changed, 6 insertions(+), 76 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 526e42af3..bf671470c 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -195,86 +195,16 @@ impl InputModuleItems { } 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 - }, + Path::expand_use_item(item, |path, ptr| { + let kind = match ptr { + None => ImportKind::Glob, + Some(ptr) => ImportKind::Named(ptr), }; - for tree in use_tree_list.use_trees() { - self.add_use_tree(prefix.clone(), tree); - } - } else { - if let Some(ast_path) = tree.path() { - if let Some(path) = convert_path(prefix, ast_path) { - let kind = if tree.has_star() { - ImportKind::Glob - } else { - let ptr = LocalSyntaxPtr::new(ast_path.segment().unwrap().syntax()); - ImportKind::Named(ptr) - }; - self.imports.push(Import { kind, path }) - } - } - } + self.imports.push(Import { kind, path }) + }) } } -fn convert_path(prefix: Option, path: ast::Path) -> Option { - 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 { fn new<'a>(item: impl ast::NameOwner<'a>) -> Option { let name = item.name()?.text(); -- cgit v1.2.3 From 11f19b784923ac701bc6fc39a6aea712f0091bf7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 17:51:02 +0300 Subject: name res uses paths --- crates/ra_analysis/src/descriptors/module/nameres.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module') diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index bf671470c..4c555421d 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs @@ -23,7 +23,7 @@ use rustc_hash::FxHashMap; use ra_syntax::{ SmolStr, SyntaxKind::{self, *}, - ast::{self, AstNode, ModuleItemOwner} + ast::{self, ModuleItemOwner} }; use crate::{ @@ -309,7 +309,7 @@ where let mut curr = match import.path.kind { // TODO: handle extern crates - PathKind::Abs => return, + PathKind::Plain => return, PathKind::Self_ => module_id, PathKind::Super => { match module_id.parent(&self.module_tree) { -- cgit v1.2.3 From 7ffc7d33082475ffd3b8768be001af5b8988a54b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 18:20:44 +0300 Subject: Move path completion to descriptors --- crates/ra_analysis/src/descriptors/module/mod.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'crates/ra_analysis/src/descriptors/module') diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index cfdffcdbc..a7e41e3db 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs @@ -14,11 +14,11 @@ use relative_path::RelativePathBuf; use crate::{ db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId, FilePosition, Cancelable, - descriptors::DescriptorDatabase, + descriptors::{Path, PathKind, DescriptorDatabase}, input::SourceRootId }; -pub(crate) use self::{nameres::ModuleScope}; +pub(crate) use self::nameres::ModuleScope; /// `ModuleDescriptor` is API entry point to get all the information /// about a particular module. @@ -131,6 +131,19 @@ impl ModuleDescriptor { Ok(res) } + pub(crate) fn 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()?, + }; + let segments = path.segments; + for name in segments { + curr = curr.child(&name)?; + } + Some(curr) + } + pub fn problems(&self, db: &impl DescriptorDatabase) -> Vec<(SyntaxNode, Problem)> { self.module_id.problems(&self.tree, db) } -- cgit v1.2.3 From edeec6a41487e6458a9d96b328c9b784525d8f06 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Nov 2018 18:34:20 +0300 Subject: Complete paths after :: --- crates/ra_analysis/src/descriptors/module/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'crates/ra_analysis/src/descriptors/module') diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index a7e41e3db..acc6c1c5a 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs @@ -110,6 +110,7 @@ impl ModuleDescriptor { } /// `name` is `None` for the crate's root module + #[allow(unused)] pub fn name(&self) -> Option { let link = self.module_id.parent_link(&self.tree)?; Some(link.name(&self.tree)) -- cgit v1.2.3