split module source into decl/defin

This commit is contained in:
Aleksey Kladov 2019-01-06 15:58:45 +03:00
parent 9cb02fd931
commit a7f4f7bfcc
6 changed files with 106 additions and 32 deletions

View file

@ -397,7 +397,7 @@ impl Analysis {
} }
/// Returns the root file of the given crate. /// Returns the root file of the given crate.
pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> { pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> {
Ok(self.db.crate_root(crate_id)) Ok(self.db.crate_graph().crate_root(crate_id))
} }
/// Returns the set of possible targets to run for the current file. /// Returns the set of possible targets to run for the current file.
pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> { pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {

View file

@ -73,11 +73,11 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti
let module = let module =
hir::source_binder::module_from_child_node(db, file_id, module.syntax()).ok()??; hir::source_binder::module_from_child_node(db, file_id, module.syntax()).ok()??;
let path = module let path = module
.path_to_root() .path_to_root(db)
.ok()?
.into_iter() .into_iter()
.rev() .rev()
.into_iter() .filter_map(|it| it.name(db).map(Clone::clone))
.filter_map(|it| it.name().map(Clone::clone))
.join("::"); .join("::");
Some(Runnable { Some(Runnable {
range, range,

View file

@ -1,6 +1,7 @@
use ra_db::{CrateId, Cancelable}; use ra_db::{CrateId, Cancelable, FileId};
use ra_syntax::{ast, SyntaxNode};
use crate::{Name, db::HirDatabase, DefId, Path, PerNs, module::{ModuleSource, ModuleScope}}; use crate::{Name, db::HirDatabase, DefId, Path, PerNs, module::{Problem, ModuleScope}};
/// hir::Crate describes a single crate. It's the main inteface with which /// hir::Crate describes a single crate. It's the main inteface with which
/// crate's dependencies interact. Mostly, it should be just a proxy for the /// crate's dependencies interact. Mostly, it should be just a proxy for the
@ -33,10 +34,27 @@ pub struct Module {
pub(crate) def_id: DefId, pub(crate) def_id: DefId,
} }
/// An owned syntax node for a module. Unlike `ModuleSource`,
/// this holds onto the AST for the whole file.
pub enum ModuleSource {
SourceFile(ast::SourceFileNode),
Module(ast::ModuleNode),
}
impl Module { impl Module {
// FIXME: what is a module source exactly? It should contain two nodes pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> {
pub fn source(&self, db: &impl HirDatabase) -> Cancelable<ModuleSource> { self.name_impl(db)
Ok(self.source_impl(db)) }
pub fn defenition_source(&self, db: &impl HirDatabase) -> Cancelable<(FileId, ModuleSource)> {
self.defenition_source_impl(db)
}
pub fn declaration_source(
&self,
db: &impl HirDatabase,
) -> Cancelable<Option<(FileId, ast::ModuleNode)>> {
self.declaration_source_impl(db)
} }
/// Returns the crate this module is part of. /// Returns the crate this module is part of.
@ -56,6 +74,15 @@ impl Module {
pub fn parent(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { pub fn parent(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> {
self.parent_impl(db) self.parent_impl(db)
} }
pub fn path_to_root(&self, db: &impl HirDatabase) -> Cancelable<Vec<Module>> {
let mut res = vec![self.clone()];
let mut curr = self.clone();
while let Some(next) = curr.parent(db)? {
res.push(next.clone());
curr = next
}
Ok(res)
}
/// Returns a `ModuleScope`: a set of items, visible in this module. /// Returns a `ModuleScope`: a set of items, visible in this module.
pub fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { pub fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> {
self.scope_impl(db) self.scope_impl(db)
@ -63,4 +90,7 @@ impl Module {
pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> Cancelable<PerNs<DefId>> { pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> Cancelable<PerNs<DefId>> {
self.resolve_path_impl(db, path) self.resolve_path_impl(db, path)
} }
pub fn problems(&self, db: &impl HirDatabase) -> Cancelable<Vec<(SyntaxNode, Problem)>> {
self.problems_impl(db)
}
} }

View file

@ -1,12 +1,13 @@
use ra_db::{CrateId, Cancelable, SourceRootId}; use ra_db::{CrateId, Cancelable, SourceRootId, FileId};
use ra_syntax::{ast, SyntaxNode, AstNode};
use crate::{ use crate::{
HirFileId, Crate, CrateDependency, AsName, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, ModuleId, HirFileId, Crate, CrateDependency, AsName, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, ModuleId,
module::{ModuleSource, ModuleScope}, module::{ModuleScope, Problem},
db::HirDatabase, db::HirDatabase,
}; };
use crate::code_model_api::Module; use crate::code_model_api::{Module, ModuleSource};
impl Crate { impl Crate {
pub(crate) fn new(crate_id: CrateId) -> Crate { pub(crate) fn new(crate_id: CrateId) -> Crate {
@ -68,9 +69,44 @@ impl Module {
Ok(module) Ok(module)
} }
pub(crate) fn source_impl(&self, db: &impl HirDatabase) -> ModuleSource { pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> {
let loc = self.def_id.loc(db); let loc = self.def_id.loc(db);
ModuleSource(loc.source_item_id) let module_tree = db.module_tree(loc.source_root_id)?;
let link = ctry!(loc.module_id.parent_link(&module_tree));
Ok(Some(link.name(&module_tree).clone()))
}
pub fn defenition_source_impl(
&self,
db: &impl HirDatabase,
) -> Cancelable<(FileId, ModuleSource)> {
let loc = self.def_id.loc(db);
let file_id = loc.source_item_id.file_id.as_original_file();
let syntax_node = db.file_item(loc.source_item_id);
let syntax_node = syntax_node.borrowed();
let module_source = if let Some(source_file) = ast::SourceFile::cast(syntax_node) {
ModuleSource::SourceFile(source_file.owned())
} else {
let module = ast::Module::cast(syntax_node).unwrap();
ModuleSource::Module(module.owned())
};
Ok((file_id, module_source))
}
pub fn declaration_source_impl(
&self,
db: &impl HirDatabase,
) -> Cancelable<Option<(FileId, ast::ModuleNode)>> {
let loc = self.def_id.loc(db);
let module_tree = db.module_tree(loc.source_root_id)?;
let link = ctry!(loc.module_id.parent_link(&module_tree));
let file_id = link
.owner(&module_tree)
.source(&module_tree)
.file_id()
.as_original_file();
let src = link.bind_source(&module_tree, db);
Ok(Some((file_id, src)))
} }
pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> { pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> {
@ -150,4 +186,9 @@ impl Module {
} }
Ok(curr_per_ns) Ok(curr_per_ns)
} }
pub fn problems_impl(&self, db: &impl HirDatabase) -> Cancelable<Vec<(SyntaxNode, Problem)>> {
let loc = self.def_id.loc(db);
let module_tree = db.module_tree(loc.source_root_id)?;
Ok(loc.module_id.problems(&module_tree, db))
}
} }

View file

@ -10,10 +10,10 @@ use crate::{
Function, Function,
db::HirDatabase, db::HirDatabase,
type_ref::TypeRef, type_ref::TypeRef,
module::{ModuleSourceNode, ModuleId}, module::ModuleId,
}; };
use crate::code_model_api::Module; use crate::code_model_api::{Module, ModuleSource};
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplBlock { pub struct ImplBlock {
@ -150,13 +150,13 @@ impl ModuleImplBlocks {
} }
fn collect(&mut self, db: &impl HirDatabase, module: Module) -> Cancelable<()> { fn collect(&mut self, db: &impl HirDatabase, module: Module) -> Cancelable<()> {
let module_source_node = module.source(db)?.resolve(db); let (file_id, module_source) = module.defenition_source(db)?;
let node = match &module_source_node { let node = match &module_source {
ModuleSourceNode::SourceFile(node) => node.borrowed().syntax(), ModuleSource::SourceFile(node) => node.borrowed().syntax(),
ModuleSourceNode::Module(node) => node.borrowed().syntax(), ModuleSource::Module(node) => node.borrowed().syntax(),
}; };
let source_file_items = db.file_items(module.source(db)?.file_id()); let source_file_items = db.file_items(file_id.into());
for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
let impl_block = ImplData::from_ast(db, &source_file_items, &module, impl_block_ast); let impl_block = ImplData::from_ast(db, &source_file_items, &module, impl_block_ast);

View file

@ -1,8 +1,6 @@
pub(super) mod imp; pub(super) mod imp;
pub(super) mod nameres; pub(super) mod nameres;
use log;
use ra_syntax::{ use ra_syntax::{
algo::generate, algo::generate,
ast::{self, AstNode, NameOwner}, ast::{self, AstNode, NameOwner},
@ -11,10 +9,7 @@ use ra_syntax::{
use ra_arena::{Arena, RawId, impl_arena_id}; use ra_arena::{Arena, RawId, impl_arena_id};
use relative_path::RelativePathBuf; use relative_path::RelativePathBuf;
use crate::{ use crate::{Name, HirDatabase, SourceItemId, SourceFileItemId, HirFileId};
Name, HirDatabase, SourceItemId, SourceFileItemId,
HirFileId,
};
pub use self::nameres::{ModuleScope, Resolution, Namespace, PerNs}; pub use self::nameres::{ModuleScope, Resolution, Namespace, PerNs};
@ -78,7 +73,7 @@ impl ModuleId {
pub(crate) fn source(self, tree: &ModuleTree) -> ModuleSource { pub(crate) fn source(self, tree: &ModuleTree) -> ModuleSource {
tree.mods[self].source tree.mods[self].source
} }
fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
tree.mods[self].parent tree.mods[self].parent
} }
pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> { pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> {
@ -105,7 +100,11 @@ impl ModuleId {
Some((link.name.clone(), module)) Some((link.name.clone(), module))
}) })
} }
fn problems(self, tree: &ModuleTree, db: &impl HirDatabase) -> Vec<(SyntaxNode, Problem)> { pub(crate) fn problems(
self,
tree: &ModuleTree,
db: &impl HirDatabase,
) -> Vec<(SyntaxNode, Problem)> {
tree.mods[self] tree.mods[self]
.children .children
.iter() .iter()
@ -120,13 +119,17 @@ impl ModuleId {
} }
impl LinkId { impl LinkId {
fn owner(self, tree: &ModuleTree) -> ModuleId { pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId {
tree.links[self].owner tree.links[self].owner
} }
fn name(self, tree: &ModuleTree) -> &Name { pub(crate) fn name(self, tree: &ModuleTree) -> &Name {
&tree.links[self].name &tree.links[self].name
} }
fn bind_source<'a>(self, tree: &ModuleTree, db: &impl HirDatabase) -> ast::ModuleNode { pub(crate) fn bind_source<'a>(
self,
tree: &ModuleTree,
db: &impl HirDatabase,
) -> ast::ModuleNode {
let owner = self.owner(tree); let owner = self.owner(tree);
match owner.source(tree).resolve(db) { match owner.source(tree).resolve(db) {
ModuleSourceNode::SourceFile(root) => { ModuleSourceNode::SourceFile(root) => {