246: Resolve path r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2018-11-27 16:56:38 +00:00
commit 9f08341aa4
7 changed files with 99 additions and 33 deletions

View file

@ -38,10 +38,7 @@ pub(crate) fn completions(
original_file.reparse(&edit) original_file.reparse(&edit)
}; };
let module = match ModuleDescriptor::guess_from_position(db, position)? { let module = ctry!(ModuleDescriptor::guess_from_position(db, position)?);
None => return Ok(None),
Some(it) => it,
};
let mut res = Vec::new(); let mut res = Vec::new();
let mut has_completions = false; let mut has_completions = false;

View file

@ -13,6 +13,7 @@ use crate::{
descriptors::{ descriptors::{
module::{ModuleDescriptor}, module::{ModuleDescriptor},
function::FnScopes, function::FnScopes,
Def,
Path, Path,
}, },
Cancelable Cancelable
@ -42,8 +43,7 @@ pub(super) fn completions(
let module_scope = module.scope(db)?; let module_scope = module.scope(db)?;
acc.extend( acc.extend(
module_scope module_scope
.items .entries()
.iter()
.filter(|(_name, res)| { .filter(|(_name, res)| {
// Don't expose this item // Don't expose this item
match res.import { match res.import {
@ -157,15 +157,16 @@ fn complete_path(
return Ok(()); return Ok(());
} }
path.segments.pop(); path.segments.pop();
let target_module = match module.resolve_path(path) { let def_id = match module.resolve_path(db, path)? {
None => return Ok(()), None => return Ok(()),
Some(it) => it, Some(it) => it,
}; };
let target_module = match def_id.resolve(db)? {
Def::Module(it) => it,
Def::Item => return Ok(()),
};
let module_scope = target_module.scope(db)?; let module_scope = target_module.scope(db)?;
let completions = module_scope let completions = module_scope.entries().map(|(name, _res)| CompletionItem {
.items
.iter()
.map(|(name, _res)| CompletionItem {
label: name.to_string(), label: name.to_string(),
lookup: None, lookup: None,
snippet: None, snippet: None,

View file

@ -13,9 +13,12 @@ use crate::{
FileId, FileId,
db::SyntaxDatabase, db::SyntaxDatabase,
descriptors::function::{resolve_local_name, FnId, FnScopes}, descriptors::function::{resolve_local_name, FnId, FnScopes},
descriptors::module::{ModuleId, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems, FileItems}}, descriptors::module::{
ModuleId, ModuleTree, ModuleSource, ModuleDescriptor,
nameres::{ItemMap, InputModuleItems, FileItems}
},
input::SourceRootId, input::SourceRootId,
loc2id::IdDatabase, loc2id::{IdDatabase, DefId, DefLoc},
syntax_ptr::LocalSyntaxPtr, syntax_ptr::LocalSyntaxPtr,
Cancelable, Cancelable,
}; };
@ -67,6 +70,25 @@ salsa::query_group! {
} }
} }
pub(crate) enum Def {
Module(ModuleDescriptor),
Item,
}
impl DefId {
pub(crate) fn resolve(self, db: &impl DescriptorDatabase) -> Cancelable<Def> {
let loc = db.id_maps().def_loc(self);
let res = match loc {
DefLoc::Module { id, source_root } => {
let descr = ModuleDescriptor::new(db, source_root, id)?;
Def::Module(descr)
}
DefLoc::Item { .. } => Def::Item,
};
Ok(res)
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct ReferenceDescriptor { pub struct ReferenceDescriptor {
pub range: TextRange, pub range: TextRange,

View file

@ -17,6 +17,7 @@ use crate::{
descriptors::{Path, PathKind, DescriptorDatabase}, descriptors::{Path, PathKind, DescriptorDatabase},
input::SourceRootId, input::SourceRootId,
arena::{Arena, Id}, arena::{Arena, Id},
loc2id::{DefLoc, DefId},
}; };
pub(crate) use self::nameres::ModuleScope; pub(crate) use self::nameres::ModuleScope;
@ -76,6 +77,20 @@ impl ModuleDescriptor {
Ok(res) Ok(res)
} }
pub(super) fn new(
db: &impl DescriptorDatabase,
source_root_id: SourceRootId,
module_id: ModuleId,
) -> Cancelable<ModuleDescriptor> {
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 `mod foo;` or `mod foo {}` node whihc declared this module.
/// Returns `None` for the root module /// Returns `None` for the root module
pub fn parent_link_source( pub fn parent_link_source(
@ -117,6 +132,14 @@ impl ModuleDescriptor {
Some(link.name(&self.tree)) Some(link.name(&self.tree))
} }
pub fn def_id(&self, db: &impl DescriptorDatabase) -> DefId {
let def_loc = DefLoc::Module {
id: self.module_id,
source_root: self.source_root_id,
};
db.id_maps().def_id(def_loc)
}
/// Finds a child module with the specified name. /// Finds a child module with the specified name.
pub fn child(&self, name: &str) -> Option<ModuleDescriptor> { pub fn child(&self, name: &str) -> Option<ModuleDescriptor> {
let child_id = self.module_id.child(&self.tree, name)?; let child_id = self.module_id.child(&self.tree, name)?;
@ -133,17 +156,28 @@ impl ModuleDescriptor {
Ok(res) Ok(res)
} }
pub(crate) fn resolve_path(&self, path: Path) -> Option<ModuleDescriptor> { pub(crate) fn resolve_path(
&self,
db: &impl DescriptorDatabase,
path: Path,
) -> Cancelable<Option<DefId>> {
let mut curr = match path.kind { let mut curr = match path.kind {
PathKind::Crate => self.crate_root(), PathKind::Crate => self.crate_root(),
PathKind::Self_ | PathKind::Plain => self.clone(), 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)?;
} }
Some(curr) .def_id(db);
let segments = path.segments;
for name in segments.iter() {
let module = match db.id_maps().def_loc(curr) {
DefLoc::Module { id, source_root } => ModuleDescriptor::new(db, source_root, id)?,
_ => return Ok(None),
};
let scope = module.scope(db)?;
curr = ctry!(ctry!(scope.get(&name)).def_id);
}
Ok(Some(curr))
} }
pub fn problems(&self, db: &impl DescriptorDatabase) -> Vec<(SyntaxNode, Problem)> { pub fn problems(&self, db: &impl DescriptorDatabase) -> Vec<(SyntaxNode, Problem)> {

View file

@ -103,7 +103,16 @@ pub(crate) struct ItemMap {
#[derive(Debug, Default, PartialEq, Eq, Clone)] #[derive(Debug, Default, PartialEq, Eq, Clone)]
pub(crate) struct ModuleScope { pub(crate) struct ModuleScope {
pub(crate) items: FxHashMap<SmolStr, Resolution>, items: FxHashMap<SmolStr, Resolution>,
}
impl ModuleScope {
pub(crate) fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + '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 /// A set of items and imports declared inside a module, without relation to

View file

@ -450,14 +450,8 @@ impl AnalysisImpl {
let syntax = file.syntax(); let syntax = file.syntax();
// Find the calling expression and it's NameRef // Find the calling expression and it's NameRef
let calling_node = match FnCallNode::with_node(syntax, position.offset) { let calling_node = ctry!(FnCallNode::with_node(syntax, position.offset));
Some(node) => node, let name_ref = ctry!(calling_node.name_ref());
None => return Ok(None),
};
let name_ref = match calling_node.name_ref() {
Some(name) => name,
None => return Ok(None),
};
// Resolve the function's NameRef (NOTE: this isn't entirely accurate). // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
let file_symbols = self.index_resolve(name_ref)?; let file_symbols = self.index_resolve(name_ref)?;

View file

@ -9,6 +9,15 @@ extern crate relative_path;
extern crate rustc_hash; extern crate rustc_hash;
extern crate salsa; extern crate salsa;
macro_rules! ctry {
($expr:expr) => {
match $expr {
None => return Ok(None),
Some(it) => it,
}
};
}
mod arena; mod arena;
mod db; mod db;
mod loc2id; mod loc2id;