254: Defids r=matklad a=matklad

Fleshing out DefIds some more

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2018-12-04 20:54:54 +00:00
commit 84f2509730
12 changed files with 187 additions and 161 deletions

View file

@ -163,7 +163,7 @@ fn complete_path(
}; };
let target_module = match def_id.resolve(db)? { let target_module = match def_id.resolve(db)? {
Def::Module(it) => it, Def::Module(it) => it,
Def::Item => return Ok(()), _ => return Ok(()),
}; };
let module_scope = target_module.scope(db)?; let module_scope = target_module.scope(db)?;
let completions = module_scope.entries().map(|(name, _res)| CompletionItem { let completions = module_scope.entries().map(|(name, _res)| CompletionItem {

View file

@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use salsa::{self, Database}; use salsa::{self, Database};
use ra_db::{LocationIntener, BaseDatabase}; use ra_db::{LocationIntener, BaseDatabase};
use hir::{self, DefId, DefLoc, FnId, SourceItemId}; use hir::{self, DefId, DefLoc};
use crate::{ use crate::{
symbol_index, symbol_index,
@ -15,7 +15,6 @@ pub(crate) struct RootDatabase {
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct IdMaps { struct IdMaps {
fns: LocationIntener<SourceItemId, FnId>,
defs: LocationIntener<DefLoc, DefId>, defs: LocationIntener<DefLoc, DefId>,
} }
@ -58,12 +57,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
} }
} }
impl AsRef<LocationIntener<hir::SourceItemId, FnId>> for RootDatabase {
fn as_ref(&self) -> &LocationIntener<hir::SourceItemId, FnId> {
&self.id_maps.fns
}
}
salsa::database_storage! { salsa::database_storage! {
pub(crate) struct RootDatabaseStorage for RootDatabase { pub(crate) struct RootDatabaseStorage for RootDatabase {
impl ra_db::FilesDatabase { impl ra_db::FilesDatabase {

View file

@ -190,10 +190,7 @@ impl AnalysisImpl {
Some(it) => it, Some(it) => it,
}; };
let root = descr.crate_root(); let root = descr.crate_root();
let file_id = root let file_id = root.source().file_id();
.source()
.as_file()
.expect("root module always has a file as a source");
let crate_graph = self.db.crate_graph(); let crate_graph = self.db.crate_graph();
let crate_id = crate_graph.crate_id_for_crate_root(file_id); let crate_id = crate_graph.crate_id_for_crate_root(file_id);
@ -213,7 +210,7 @@ impl AnalysisImpl {
let syntax = file.syntax(); let syntax = file.syntax();
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
if let Some(fn_descr) = if let Some(fn_descr) =
hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref) hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref)?
{ {
let scope = fn_descr.scope(&*self.db); let scope = fn_descr.scope(&*self.db);
// First try to resolve the symbol locally // First try to resolve the symbol locally
@ -260,11 +257,11 @@ impl AnalysisImpl {
Ok(vec![]) Ok(vec![])
} }
pub fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
let file = self.db.source_file(position.file_id); let file = self.db.source_file(position.file_id);
// Find the binding associated with the offset // Find the binding associated with the offset
let (binding, descr) = match find_binding(&self.db, &file, position) { let (binding, descr) = match find_binding(&self.db, &file, position)? {
None => return Vec::new(), None => return Ok(Vec::new()),
Some(it) => it, Some(it) => it,
}; };
@ -277,25 +274,36 @@ impl AnalysisImpl {
.map(|ref_desc| (position.file_id, ref_desc.range)), .map(|ref_desc| (position.file_id, ref_desc.range)),
); );
return ret; return Ok(ret);
fn find_binding<'a>( fn find_binding<'a>(
db: &db::RootDatabase, db: &db::RootDatabase,
source_file: &'a SourceFileNode, source_file: &'a SourceFileNode,
position: FilePosition, position: FilePosition,
) -> Option<(ast::BindPat<'a>, hir::Function)> { ) -> Cancelable<Option<(ast::BindPat<'a>, hir::Function)>> {
let syntax = source_file.syntax(); let syntax = source_file.syntax();
if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) { if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) {
let descr = hir::Function::guess_for_bind_pat(db, position.file_id, binding)?; let descr = ctry!(hir::Function::guess_for_bind_pat(
return Some((binding, descr)); db,
position.file_id,
binding
)?);
return Ok(Some((binding, descr)));
}; };
let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?; let name_ref = ctry!(find_node_at_offset::<ast::NameRef>(syntax, position.offset));
let descr = hir::Function::guess_for_name_ref(db, position.file_id, name_ref)?; let descr = ctry!(hir::Function::guess_for_name_ref(
db,
position.file_id,
name_ref
)?);
let scope = descr.scope(db); let scope = descr.scope(db);
let resolved = scope.resolve_local_name(name_ref)?; let resolved = ctry!(scope.resolve_local_name(name_ref));
let resolved = resolved.ptr().resolve(source_file); let resolved = resolved.ptr().resolve(source_file);
let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?; let binding = ctry!(find_node_at_offset::<ast::BindPat>(
Some((binding, descr)) syntax,
resolved.range().end()
));
Ok(Some((binding, descr)))
} }
} }
@ -411,7 +419,9 @@ impl AnalysisImpl {
if fs.kind == FN_DEF { if fs.kind == FN_DEF {
let fn_file = self.db.source_file(fn_file_id); let fn_file = self.db.source_file(fn_file_id);
if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) { if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) {
let descr = hir::Function::guess_from_source(&*self.db, fn_file_id, fn_def); let descr = ctry!(hir::Function::guess_from_source(
&*self.db, fn_file_id, fn_def
)?);
if let Some(descriptor) = descr.signature_info(&*self.db) { if let Some(descriptor) = descr.signature_info(&*self.db) {
// If we have a calling expression let's find which argument we are on // If we have a calling expression let's find which argument we are on
let mut current_parameter = None; let mut current_parameter = None;

View file

@ -248,7 +248,7 @@ impl Analysis {
self.imp.approximately_resolve_symbol(position) self.imp.approximately_resolve_symbol(position)
} }
pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
Ok(self.imp.find_all_refs(position)) self.imp.find_all_refs(position)
} }
pub fn doc_comment_for( pub fn doc_comment_for(
&self, &self,

View file

@ -7,10 +7,11 @@ use ra_syntax::{
use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable}; use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable};
use crate::{ use crate::{
DefLoc, DefId, FnId, DefLoc, DefId,
SourceFileItems, SourceItemId, SourceFileItems, SourceItemId,
query_definitions, query_definitions,
FnScopes, FnScopes,
function::FnId,
module::{ModuleId, ModuleTree, ModuleSource, module::{ModuleId, ModuleTree, ModuleSource,
nameres::{ItemMap, InputModuleItems}}, nameres::{ItemMap, InputModuleItems}},
}; };
@ -19,7 +20,6 @@ salsa::query_group! {
pub trait HirDatabase: SyntaxDatabase pub trait HirDatabase: SyntaxDatabase
+ AsRef<LocationIntener<DefLoc, DefId>> + AsRef<LocationIntener<DefLoc, DefId>>
+ AsRef<LocationIntener<SourceItemId, FnId>>
{ {
fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> { fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> {
type FnScopesQuery; type FnScopesQuery;

View file

@ -12,39 +12,49 @@ use ra_syntax::{
use ra_db::FileId; use ra_db::FileId;
use crate::{ use crate::{
FnId, HirDatabase, SourceItemId, Cancelable,
DefLoc, DefKind, DefId, HirDatabase, SourceItemId,
Module,
}; };
pub use self::scope::FnScopes; pub use self::scope::FnScopes;
impl FnId { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub fn get(db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId { pub struct FnId(pub(crate) DefId);
let file_items = db.file_items(file_id);
let item_id = file_items.id_of(fn_def.syntax());
let item_id = SourceItemId { file_id, item_id };
FnId::from_loc(db, &item_id)
}
}
pub struct Function { pub struct Function {
fn_id: FnId, fn_id: FnId,
} }
impl Function { impl Function {
pub(crate) fn new(def_id: DefId) -> Function {
let fn_id = FnId(def_id);
Function { fn_id }
}
pub fn guess_from_source( pub fn guess_from_source(
db: &impl HirDatabase, db: &impl HirDatabase,
file_id: FileId, file_id: FileId,
fn_def: ast::FnDef, fn_def: ast::FnDef,
) -> Function { ) -> Cancelable<Option<Function>> {
let fn_id = FnId::get(db, file_id, fn_def); let module = ctry!(Module::guess_from_child_node(db, file_id, fn_def.syntax())?);
Function { fn_id } let file_items = db.file_items(file_id);
let item_id = file_items.id_of(fn_def.syntax());
let source_item_id = SourceItemId { file_id, item_id };
let def_loc = DefLoc {
kind: DefKind::Function,
source_root_id: module.source_root_id,
module_id: module.module_id,
source_item_id,
};
Ok(Some(Function::new(def_loc.id(db))))
} }
pub fn guess_for_name_ref( pub fn guess_for_name_ref(
db: &impl HirDatabase, db: &impl HirDatabase,
file_id: FileId, file_id: FileId,
name_ref: ast::NameRef, name_ref: ast::NameRef,
) -> Option<Function> { ) -> Cancelable<Option<Function>> {
Function::guess_for_node(db, file_id, name_ref.syntax()) Function::guess_for_node(db, file_id, name_ref.syntax())
} }
@ -52,7 +62,7 @@ impl Function {
db: &impl HirDatabase, db: &impl HirDatabase,
file_id: FileId, file_id: FileId,
bind_pat: ast::BindPat, bind_pat: ast::BindPat,
) -> Option<Function> { ) -> Cancelable<Option<Function>> {
Function::guess_for_node(db, file_id, bind_pat.syntax()) Function::guess_for_node(db, file_id, bind_pat.syntax())
} }
@ -60,10 +70,9 @@ impl Function {
db: &impl HirDatabase, db: &impl HirDatabase,
file_id: FileId, file_id: FileId,
node: SyntaxNodeRef, node: SyntaxNodeRef,
) -> Option<Function> { ) -> Cancelable<Option<Function>> {
let fn_def = node.ancestors().find_map(ast::FnDef::cast)?; let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast));
let res = Function::guess_from_source(db, file_id, fn_def); Function::guess_from_source(db, file_id, fn_def)
Some(res)
} }
pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> { pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> {

View file

@ -41,63 +41,58 @@ pub use self::{
pub use self::function::FnSignatureInfo; pub use self::function::FnSignatureInfo;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
pub struct FnId(u32); /// in a specific module.
ra_db::impl_numeric_id!(FnId);
impl FnId {
pub fn from_loc(
db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
loc: &SourceItemId,
) -> FnId {
db.as_ref().loc2id(loc)
}
pub fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
db.as_ref().id2loc(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DefId(u32); pub struct DefId(u32);
ra_db::impl_numeric_id!(DefId); ra_db::impl_numeric_id!(DefId);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum DefKind {
Module,
Function,
Item,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum DefLoc { pub struct DefLoc {
Module { pub(crate) kind: DefKind,
id: ModuleId, source_root_id: SourceRootId,
source_root: SourceRootId, module_id: ModuleId,
},
Item {
source_item_id: SourceItemId, source_item_id: SourceItemId,
},
} }
impl DefId { impl DefId {
pub fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc { pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
db.as_ref().id2loc(self) db.as_ref().id2loc(self)
} }
} }
impl DefLoc { impl DefLoc {
pub fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId { pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
db.as_ref().loc2id(&self) db.as_ref().loc2id(&self)
} }
} }
pub enum Def { pub enum Def {
Module(Module), Module(Module),
Function(Function),
Item, Item,
} }
impl DefId { impl DefId {
pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> { pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
let loc = self.loc(db); let loc = self.loc(db);
let res = match loc { let res = match loc.kind {
DefLoc::Module { id, source_root } => { DefKind::Module => {
let descr = Module::new(db, source_root, id)?; let module = Module::new(db, loc.source_root_id, loc.module_id)?;
Def::Module(descr) Def::Module(module)
} }
DefLoc::Item { .. } => Def::Item, DefKind::Function => {
let function = Function::new(self);
Def::Function(function)
}
DefKind::Item => Def::Item,
}; };
Ok(res) Ok(res)
} }
@ -131,6 +126,10 @@ impl SourceFileItems {
.unwrap(); .unwrap();
id id
} }
pub fn id_of_source_file(&self) -> SourceFileItemId {
let (id, _syntax) = self.arena.iter().next().unwrap();
id
}
} }
impl Index<SourceFileItemId> for SourceFileItems { impl Index<SourceFileItemId> for SourceFileItems {

View file

@ -6,7 +6,7 @@ use ra_db::{LocationIntener, BaseDatabase, FilePosition, mock::FileMap, FileId,
use relative_path::RelativePathBuf; use relative_path::RelativePathBuf;
use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
use crate::{db, DefId, DefLoc, FnId, SourceItemId}; use crate::{db, DefId, DefLoc};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct MockDatabase { pub(crate) struct MockDatabase {
@ -65,7 +65,6 @@ impl MockDatabase {
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct IdMaps { struct IdMaps {
fns: LocationIntener<SourceItemId, FnId>,
defs: LocationIntener<DefLoc, DefId>, defs: LocationIntener<DefLoc, DefId>,
} }
@ -117,12 +116,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for MockDatabase {
} }
} }
impl AsRef<LocationIntener<SourceItemId, FnId>> for MockDatabase {
fn as_ref(&self) -> &LocationIntener<SourceItemId, FnId> {
&self.id_maps.fns
}
}
impl MockDatabase { impl MockDatabase {
pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> { pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
*self.events.lock() = Some(Vec::new()); *self.events.lock() = Some(Vec::new());

View file

@ -66,7 +66,7 @@ fn create_module_tree<'a>(
let source_root = db.source_root(source_root); let source_root = db.source_root(source_root);
for &file_id in source_root.files.iter() { for &file_id in source_root.files.iter() {
let source = ModuleSource::SourceFile(file_id); let source = ModuleSource::new_file(db, file_id);
if visited.contains(&source) { if visited.contains(&source) {
continue; // TODO: use explicit crate_roots here continue; // TODO: use explicit crate_roots here
} }
@ -126,7 +126,7 @@ fn build_subtree(
visited, visited,
roots, roots,
Some(link), Some(link),
ModuleSource::SourceFile(file_id), ModuleSource::new_file(db, file_id),
), ),
}) })
.collect::<Cancelable<Vec<_>>>()?; .collect::<Cancelable<Vec<_>>>()?;
@ -157,13 +157,8 @@ fn resolve_submodule(
name: &SmolStr, name: &SmolStr,
file_resolver: &FileResolverImp, file_resolver: &FileResolverImp,
) -> (Vec<FileId>, Option<Problem>) { ) -> (Vec<FileId>, Option<Problem>) {
let file_id = match source { // TODO: handle submodules of inline modules properly
ModuleSource::SourceFile(it) => it, let file_id = source.file_id();
ModuleSource::Module(..) => {
// TODO
return (Vec::new(), None);
}
};
let mod_name = file_resolver.file_stem(file_id); let mod_name = file_resolver.file_stem(file_id);
let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main";

View file

@ -8,13 +8,13 @@ use ra_editor::find_node_at_offset;
use ra_syntax::{ use ra_syntax::{
algo::generate, algo::generate,
ast::{self, AstNode, NameOwner}, ast::{self, AstNode, NameOwner},
SmolStr, SyntaxNode, SmolStr, SyntaxNode, SyntaxNodeRef,
}; };
use ra_db::{SourceRootId, FileId, FilePosition, Cancelable}; use ra_db::{SourceRootId, FileId, FilePosition, Cancelable};
use relative_path::RelativePathBuf; use relative_path::RelativePathBuf;
use crate::{ use crate::{
DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, DefKind, DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId,
arena::{Arena, Id}, arena::{Arena, Id},
}; };
@ -25,8 +25,8 @@ pub use self::nameres::ModuleScope;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Module { pub struct Module {
tree: Arc<ModuleTree>, tree: Arc<ModuleTree>,
source_root_id: SourceRootId, pub(crate) source_root_id: SourceRootId,
module_id: ModuleId, pub(crate) module_id: ModuleId,
} }
impl Module { impl Module {
@ -37,7 +37,8 @@ impl Module {
db: &impl HirDatabase, db: &impl HirDatabase,
file_id: FileId, file_id: FileId,
) -> Cancelable<Option<Module>> { ) -> Cancelable<Option<Module>> {
Module::guess_from_source(db, file_id, ModuleSource::SourceFile(file_id)) let module_source = ModuleSource::new_file(db, file_id);
Module::guess_from_source(db, module_source)
} }
/// Lookup `Module` by position in the source code. Note that this /// Lookup `Module` by position in the source code. Note that this
@ -51,17 +52,33 @@ impl Module {
let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset)
{ {
Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m), Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m),
_ => ModuleSource::SourceFile(position.file_id), _ => ModuleSource::new_file(db, position.file_id),
}; };
Module::guess_from_source(db, position.file_id, module_source) Module::guess_from_source(db, module_source)
}
pub fn guess_from_child_node(
db: &impl HirDatabase,
file_id: FileId,
node: SyntaxNodeRef,
) -> Cancelable<Option<Module>> {
let module_source = if let Some(m) = node
.ancestors()
.filter_map(ast::Module::cast)
.find(|it| !it.has_semi())
{
ModuleSource::new_inline(db, file_id, m)
} else {
ModuleSource::new_file(db, file_id)
};
Module::guess_from_source(db, module_source)
} }
fn guess_from_source( fn guess_from_source(
db: &impl HirDatabase, db: &impl HirDatabase,
file_id: FileId,
module_source: ModuleSource, module_source: ModuleSource,
) -> Cancelable<Option<Module>> { ) -> Cancelable<Option<Module>> {
let source_root_id = db.file_source_root(file_id); let source_root_id = db.file_source_root(module_source.file_id());
let module_tree = db.module_tree(source_root_id)?; let module_tree = db.module_tree(source_root_id)?;
let res = match module_tree.any_module_for_source(module_source) { let res = match module_tree.any_module_for_source(module_source) {
@ -127,9 +144,11 @@ impl Module {
} }
pub fn def_id(&self, db: &impl HirDatabase) -> DefId { pub fn def_id(&self, db: &impl HirDatabase) -> DefId {
let def_loc = DefLoc::Module { let def_loc = DefLoc {
id: self.module_id, kind: DefKind::Module,
source_root: self.source_root_id, source_root_id: self.source_root_id,
module_id: self.module_id,
source_item_id: self.module_id.source(&self.tree).0,
}; };
def_loc.id(db) def_loc.id(db)
} }
@ -161,7 +180,12 @@ impl Module {
let segments = path.segments; let segments = path.segments;
for name in segments.iter() { for name in segments.iter() {
let module = match curr.loc(db) { let module = match curr.loc(db) {
DefLoc::Module { id, source_root } => Module::new(db, source_root, id)?, DefLoc {
kind: DefKind::Module,
source_root_id,
module_id,
..
} => Module::new(db, source_root_id, module_id)?,
_ => return Ok(None), _ => return Ok(None),
}; };
let scope = module.scope(db)?; let scope = module.scope(db)?;
@ -209,10 +233,7 @@ impl ModuleTree {
/// `ModuleSource` is the syntax tree element that produced this module: /// `ModuleSource` is the syntax tree element that produced this module:
/// either a file, or an inlinde module. /// either a file, or an inlinde module.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ModuleSource { pub struct ModuleSource(SourceItemId);
SourceFile(FileId),
Module(SourceItemId),
}
/// An owned syntax node for a module. Unlike `ModuleSource`, /// An owned syntax node for a module. Unlike `ModuleSource`,
/// this holds onto the AST for the whole file. /// this holds onto the AST for the whole file.
@ -310,46 +331,42 @@ pub struct ModuleData {
} }
impl ModuleSource { impl ModuleSource {
// precondition: item_id **must** point to module
fn new(file_id: FileId, item_id: SourceFileItemId) -> ModuleSource {
let source_item_id = SourceItemId { file_id, item_id };
ModuleSource(source_item_id)
}
pub(crate) fn new_file(db: &impl HirDatabase, file_id: FileId) -> ModuleSource {
let file_items = db.file_items(file_id);
let item_id = file_items.id_of_source_file();
ModuleSource::new(file_id, item_id)
}
pub(crate) fn new_inline( pub(crate) fn new_inline(
db: &impl HirDatabase, db: &impl HirDatabase,
file_id: FileId, file_id: FileId,
module: ast::Module, m: ast::Module,
) -> ModuleSource { ) -> ModuleSource {
assert!(!module.has_semi()); assert!(!m.has_semi());
let items = db.file_items(file_id); let file_items = db.file_items(file_id);
let item_id = items.id_of(module.syntax()); let item_id = file_items.id_of(m.syntax());
let id = SourceItemId { file_id, item_id }; ModuleSource::new(file_id, item_id)
ModuleSource::Module(id)
}
pub fn as_file(self) -> Option<FileId> {
match self {
ModuleSource::SourceFile(f) => Some(f),
ModuleSource::Module(..) => None,
}
} }
pub fn file_id(self) -> FileId { pub fn file_id(self) -> FileId {
match self { self.0.file_id
ModuleSource::SourceFile(f) => f,
ModuleSource::Module(source_item_id) => source_item_id.file_id,
}
} }
pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode { pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode {
match self { let syntax_node = db.file_item(self.0);
ModuleSource::SourceFile(file_id) => { let syntax_node = syntax_node.borrowed();
let syntax = db.source_file(file_id); if let Some(file) = ast::SourceFile::cast(syntax_node) {
ModuleSourceNode::SourceFile(syntax.ast().owned()) return ModuleSourceNode::SourceFile(file.owned());
} }
ModuleSource::Module(item_id) => { let module = ast::Module::cast(syntax_node).unwrap();
let syntax = db.file_item(item_id);
let syntax = syntax.borrowed();
let module = ast::Module::cast(syntax).unwrap();
ModuleSourceNode::Module(module.owned()) ModuleSourceNode::Module(module.owned())
} }
}
}
} }
#[derive(Hash, Debug, PartialEq, Eq)] #[derive(Hash, Debug, PartialEq, Eq)]

View file

@ -28,7 +28,7 @@ use ra_db::SourceRootId;
use crate::{ use crate::{
Cancelable, FileId, Cancelable, FileId,
DefId, DefLoc, DefId, DefLoc, DefKind,
SourceItemId, SourceFileItemId, SourceFileItems, SourceItemId, SourceFileItemId, SourceFileItems,
Path, PathKind, Path, PathKind,
HirDatabase, HirDatabase,
@ -247,7 +247,10 @@ where
// handle submodules separatelly // handle submodules separatelly
continue; continue;
} }
let def_loc = DefLoc::Item { let def_loc = DefLoc {
kind: DefKind::Item,
source_root_id: self.source_root,
module_id,
source_item_id: SourceItemId { source_item_id: SourceItemId {
file_id, file_id,
item_id: item.id, item_id: item.id,
@ -261,10 +264,12 @@ where
module_items.items.insert(item.name.clone(), resolution); module_items.items.insert(item.name.clone(), resolution);
} }
for (name, mod_id) in module_id.children(&self.module_tree) { for (name, module_id) in module_id.children(&self.module_tree) {
let def_loc = DefLoc::Module { let def_loc = DefLoc {
id: mod_id, kind: DefKind::Module,
source_root: self.source_root, source_root_id: self.source_root,
module_id,
source_item_id: module_id.source(&self.module_tree).0,
}; };
let def_id = def_loc.id(self.db); let def_id = def_loc.id(self.db);
let resolution = Resolution { let resolution = Resolution {
@ -316,7 +321,11 @@ where
if !is_last { if !is_last {
curr = match def_id.loc(self.db) { curr = match def_id.loc(self.db) {
DefLoc::Module { id, .. } => id, DefLoc {
kind: DefKind::Module,
module_id,
..
} => module_id,
_ => return, _ => return,
} }
} else { } else {

View file

@ -11,10 +11,9 @@ use ra_syntax::{
use ra_db::{SourceRootId, FileId, Cancelable,}; use ra_db::{SourceRootId, FileId, Cancelable,};
use crate::{ use crate::{
FnId, SourceFileItems, SourceItemId, DefKind,
SourceFileItems, SourceItemId,
db::HirDatabase, db::HirDatabase,
function::FnScopes, function::{FnScopes, FnId},
module::{ module::{
ModuleSource, ModuleSourceNode, ModuleId, ModuleSource, ModuleSourceNode, ModuleId,
imp::Submodule, imp::Submodule,
@ -24,8 +23,9 @@ use crate::{
/// Resolve `FnId` to the corresponding `SyntaxNode` /// Resolve `FnId` to the corresponding `SyntaxNode`
pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode { pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode {
let item_id = fn_id.loc(db); let def_loc = fn_id.0.loc(db);
let syntax = db.file_item(item_id); assert!(def_loc.kind == DefKind::Function);
let syntax = db.file_item(def_loc.source_item_id);
FnDef::cast(syntax.borrowed()).unwrap().owned() FnDef::cast(syntax.borrowed()).unwrap().owned()
} }
@ -36,9 +36,10 @@ pub(super) fn fn_scopes(db: &impl HirDatabase, fn_id: FnId) -> Arc<FnScopes> {
} }
pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> { pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> {
let source_file = db.source_file(file_id);
let source_file = source_file.borrowed();
let mut res = SourceFileItems::default(); let mut res = SourceFileItems::default();
let source_file = db.source_file(file_id);
res.alloc(source_file.syntax().owned());
let source_file = source_file.borrowed();
source_file source_file
.syntax() .syntax()
.descendants() .descendants()