aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/descriptors/module
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/descriptors/module')
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs79
1 files changed, 78 insertions, 1 deletions
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs
index 055a56b54..d62826ee3 100644
--- a/crates/ra_analysis/src/descriptors/module/mod.rs
+++ b/crates/ra_analysis/src/descriptors/module/mod.rs
@@ -1,16 +1,90 @@
1pub(super) mod imp; 1pub(super) mod imp;
2pub(crate) mod scope; 2pub(crate) mod scope;
3 3
4use std::sync::Arc;
5
6use ra_editor::find_node_at_offset;
7
4use ra_syntax::{ 8use ra_syntax::{
5 ast::{self, AstNode, NameOwner}, 9 ast::{self, AstNode, NameOwner},
6 SmolStr, SyntaxNode, SyntaxNodeRef, 10 SmolStr, SyntaxNode, SyntaxNodeRef,
7}; 11};
8use relative_path::RelativePathBuf; 12use relative_path::RelativePathBuf;
9 13
10use crate::{db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId}; 14use crate::{
15 db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId, FilePosition, Cancelable,
16 descriptors::DescriptorDatabase,
17};
11 18
12pub(crate) use self::scope::ModuleScope; 19pub(crate) use self::scope::ModuleScope;
13 20
21/// `ModuleDescriptor` is API entry point to get all the information
22/// about a particular module.
23#[derive(Debug, Clone)]
24pub(crate) struct ModuleDescriptor {
25 tree: Arc<ModuleTree>,
26 module_id: ModuleId,
27}
28
29impl ModuleDescriptor {
30 /// Lookup `ModuleDescriptor` by position in the source code. Note that this
31 /// is inherently lossy transformation: in general, a single source might
32 /// correspond to several modules.
33 pub fn guess_from_position(
34 db: &impl DescriptorDatabase,
35 position: FilePosition,
36 ) -> Cancelable<Option<ModuleDescriptor>> {
37 let source_root = db.file_source_root(position.file_id);
38 let module_tree = db.module_tree(source_root)?;
39 let file = db.file_syntax(position.file_id);
40 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset)
41 {
42 Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m),
43 _ => ModuleSource::SourceFile(position.file_id),
44 };
45 let res = match module_tree.any_module_for_source(module_source) {
46 None => None,
47 Some(module_id) => Some(ModuleDescriptor {
48 tree: module_tree,
49 module_id,
50 }),
51 };
52 Ok(res)
53 }
54
55 /// Returns `mod foo;` or `mod foo {}` node whihc declared this module.
56 /// Returns `None` for the root module
57 pub fn parent_link_source(
58 &self,
59 db: &impl DescriptorDatabase,
60 ) -> Option<(FileId, ast::ModuleNode)> {
61 let link = self.module_id.parent_link(&self.tree)?;
62 let file_id = link.owner(&self.tree).source(&self.tree).file_id();
63 let src = link.bind_source(&self.tree, db);
64 Some((file_id, src))
65 }
66
67 pub fn parent(&self) -> Option<ModuleDescriptor> {
68 let parent_id = self.module_id.parent(&self.tree)?;
69 Some(ModuleDescriptor {
70 tree: Arc::clone(&self.tree),
71 module_id: parent_id,
72 })
73 }
74 /// `name` is `None` for the crate's root module
75 pub fn name(&self) -> Option<SmolStr> {
76 let link = self.module_id.parent_link(&self.tree)?;
77 Some(link.name(&self.tree))
78 }
79 pub fn child(&self, name: &str) -> Option<ModuleDescriptor> {
80 let child_id = self.module_id.child(&self.tree, name)?;
81 Some(ModuleDescriptor {
82 tree: Arc::clone(&self.tree),
83 module_id: child_id,
84 })
85 }
86}
87
14/// Phisically, rust source is organized as a set of files, but logically it is 88/// Phisically, rust source is organized as a set of files, but logically it is
15/// organized as a tree of modules. Usually, a single file corresponds to a 89/// organized as a tree of modules. Usually, a single file corresponds to a
16/// single module, but it is not nessary the case. 90/// single module, but it is not nessary the case.
@@ -136,6 +210,9 @@ impl LinkId {
136 pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId { 210 pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId {
137 tree.link(self).owner 211 tree.link(self).owner
138 } 212 }
213 pub(crate) fn name(self, tree: &ModuleTree) -> SmolStr {
214 tree.link(self).name.clone()
215 }
139 pub(crate) fn bind_source<'a>( 216 pub(crate) fn bind_source<'a>(
140 self, 217 self,
141 tree: &ModuleTree, 218 tree: &ModuleTree,