mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Use OO API in crate_for
This commit is contained in:
parent
d475e3b29f
commit
0ab3c65d98
2 changed files with 50 additions and 12 deletions
|
@ -6,6 +6,7 @@ use std::sync::Arc;
|
||||||
use ra_editor::find_node_at_offset;
|
use ra_editor::find_node_at_offset;
|
||||||
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
|
algo::generate,
|
||||||
ast::{self, AstNode, NameOwner},
|
ast::{self, AstNode, NameOwner},
|
||||||
SmolStr, SyntaxNode, SyntaxNodeRef,
|
SmolStr, SyntaxNode, SyntaxNodeRef,
|
||||||
};
|
};
|
||||||
|
@ -27,6 +28,16 @@ pub(crate) struct ModuleDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleDescriptor {
|
impl ModuleDescriptor {
|
||||||
|
/// Lookup `ModuleDescriptor` by `FileId`. Note that this is inherently
|
||||||
|
/// lossy transformation: in general, a single source might correspond to
|
||||||
|
/// several modules.
|
||||||
|
pub fn guess_from_file_id(
|
||||||
|
db: &impl DescriptorDatabase,
|
||||||
|
file_id: FileId,
|
||||||
|
) -> Cancelable<Option<ModuleDescriptor>> {
|
||||||
|
ModuleDescriptor::guess_from_source(db, file_id, ModuleSource::SourceFile(file_id))
|
||||||
|
}
|
||||||
|
|
||||||
/// Lookup `ModuleDescriptor` by position in the source code. Note that this
|
/// Lookup `ModuleDescriptor` by position in the source code. Note that this
|
||||||
/// is inherently lossy transformation: in general, a single source might
|
/// is inherently lossy transformation: in general, a single source might
|
||||||
/// correspond to several modules.
|
/// correspond to several modules.
|
||||||
|
@ -34,14 +45,23 @@ impl ModuleDescriptor {
|
||||||
db: &impl DescriptorDatabase,
|
db: &impl DescriptorDatabase,
|
||||||
position: FilePosition,
|
position: FilePosition,
|
||||||
) -> Cancelable<Option<ModuleDescriptor>> {
|
) -> Cancelable<Option<ModuleDescriptor>> {
|
||||||
let source_root = db.file_source_root(position.file_id);
|
|
||||||
let module_tree = db.module_tree(source_root)?;
|
|
||||||
let file = db.file_syntax(position.file_id);
|
let file = db.file_syntax(position.file_id);
|
||||||
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(position.file_id, m),
|
Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m),
|
||||||
_ => ModuleSource::SourceFile(position.file_id),
|
_ => ModuleSource::SourceFile(position.file_id),
|
||||||
};
|
};
|
||||||
|
ModuleDescriptor::guess_from_source(db, position.file_id, module_source)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guess_from_source(
|
||||||
|
db: &impl DescriptorDatabase,
|
||||||
|
file_id: FileId,
|
||||||
|
module_source: ModuleSource,
|
||||||
|
) -> Cancelable<Option<ModuleDescriptor>> {
|
||||||
|
let source_root = db.file_source_root(file_id);
|
||||||
|
let module_tree = db.module_tree(source_root)?;
|
||||||
|
|
||||||
let res = match module_tree.any_module_for_source(module_source) {
|
let res = match module_tree.any_module_for_source(module_source) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(module_id) => Some(ModuleDescriptor {
|
Some(module_id) => Some(ModuleDescriptor {
|
||||||
|
@ -64,6 +84,11 @@ impl ModuleDescriptor {
|
||||||
Some((file_id, src))
|
Some((file_id, src))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn source(&self) -> ModuleSource {
|
||||||
|
self.module_id.source(&self.tree)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parent module. Returns `None` if this is a root module.
|
||||||
pub fn parent(&self) -> Option<ModuleDescriptor> {
|
pub fn parent(&self) -> Option<ModuleDescriptor> {
|
||||||
let parent_id = self.module_id.parent(&self.tree)?;
|
let parent_id = self.module_id.parent(&self.tree)?;
|
||||||
Some(ModuleDescriptor {
|
Some(ModuleDescriptor {
|
||||||
|
@ -71,6 +96,14 @@ impl ModuleDescriptor {
|
||||||
module_id: parent_id,
|
module_id: parent_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The root of the tree this module is part of
|
||||||
|
pub fn crate_root(&self) -> ModuleDescriptor {
|
||||||
|
generate(Some(self.clone()), |it| it.parent())
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// `name` is `None` for the crate's root module
|
/// `name` is `None` for the crate's root module
|
||||||
pub fn name(&self) -> Option<SmolStr> {
|
pub fn name(&self) -> Option<SmolStr> {
|
||||||
let link = self.module_id.parent_link(&self.tree)?;
|
let link = self.module_id.parent_link(&self.tree)?;
|
||||||
|
|
|
@ -220,6 +220,8 @@ impl AnalysisImpl {
|
||||||
let source_root = self.db.file_source_root(file_id);
|
let source_root = self.db.file_source_root(file_id);
|
||||||
self.db.module_tree(source_root)
|
self.db.module_tree(source_root)
|
||||||
}
|
}
|
||||||
|
/// This return `Vec`: a module may be inclucded from several places.
|
||||||
|
/// We don't handle this case yet though, so the Vec has length at most one.
|
||||||
pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
|
pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
|
||||||
let descr = match ModuleDescriptor::guess_from_position(&*self.db, position)? {
|
let descr = match ModuleDescriptor::guess_from_position(&*self.db, position)? {
|
||||||
None => return Ok(Vec::new()),
|
None => return Ok(Vec::new()),
|
||||||
|
@ -238,18 +240,21 @@ impl AnalysisImpl {
|
||||||
};
|
};
|
||||||
Ok(vec![(file_id, sym)])
|
Ok(vec![(file_id, sym)])
|
||||||
}
|
}
|
||||||
|
/// Returns `Vec` for the same reason as `parent_module`
|
||||||
pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
|
pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
|
||||||
let module_tree = self.module_tree(file_id)?;
|
let descr = match ModuleDescriptor::guess_from_file_id(&*self.db, file_id)? {
|
||||||
let crate_graph = self.db.crate_graph();
|
None => return Ok(Vec::new()),
|
||||||
let res = module_tree
|
Some(it) => it,
|
||||||
.modules_for_source(ModuleSource::SourceFile(file_id))
|
};
|
||||||
.into_iter()
|
let root = descr.crate_root();
|
||||||
.map(|it| it.root(&module_tree))
|
let file_id = root
|
||||||
.filter_map(|it| it.source(&module_tree).as_file())
|
.source()
|
||||||
.filter_map(|it| crate_graph.crate_id_for_crate_root(it))
|
.as_file()
|
||||||
.collect();
|
.expect("root module always has a file as a source");
|
||||||
|
|
||||||
Ok(res)
|
let crate_graph = self.db.crate_graph();
|
||||||
|
let crate_id = crate_graph.crate_id_for_crate_root(file_id);
|
||||||
|
Ok(crate_id.into_iter().collect())
|
||||||
}
|
}
|
||||||
pub fn crate_root(&self, crate_id: CrateId) -> FileId {
|
pub fn crate_root(&self, crate_id: CrateId) -> FileId {
|
||||||
self.db.crate_graph().crate_roots[&crate_id]
|
self.db.crate_graph().crate_roots[&crate_id]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue