aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/descriptors
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-11-20 14:33:54 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-11-20 14:33:54 +0000
commit713c3ea30b38199e05e1f70094d85177f16915f8 (patch)
treef4f3c59a59e4a607b77321cb685bf616824dc8f7 /crates/ra_analysis/src/descriptors
parent902778ccaefc7b51548cab459715aaf8653bbbc6 (diff)
parenta2fdb41ace4de7737a3ba0e4ef5e68d0a41e924d (diff)
Merge #234
234: Global module r=matklad a=matklad This series of commits re-introdces `ModuleDescriptor` as one stop shop for all information about a module. Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_analysis/src/descriptors')
-rw-r--r--crates/ra_analysis/src/descriptors/function/imp.rs2
-rw-r--r--crates/ra_analysis/src/descriptors/mod.rs21
-rw-r--r--crates/ra_analysis/src/descriptors/module/imp.rs4
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs190
4 files changed, 151 insertions, 66 deletions
diff --git a/crates/ra_analysis/src/descriptors/function/imp.rs b/crates/ra_analysis/src/descriptors/function/imp.rs
index a7257acf9..e09deba0f 100644
--- a/crates/ra_analysis/src/descriptors/function/imp.rs
+++ b/crates/ra_analysis/src/descriptors/function/imp.rs
@@ -15,7 +15,7 @@ pub(crate) fn fn_syntax(db: &impl DescriptorDatabase, fn_id: FnId) -> FnDefNode
15} 15}
16 16
17pub(crate) fn fn_scopes(db: &impl DescriptorDatabase, fn_id: FnId) -> Arc<FnScopes> { 17pub(crate) fn fn_scopes(db: &impl DescriptorDatabase, fn_id: FnId) -> Arc<FnScopes> {
18 let syntax = db.fn_syntax(fn_id); 18 let syntax = db._fn_syntax(fn_id);
19 let res = FnScopes::new(syntax.borrowed()); 19 let res = FnScopes::new(syntax.borrowed());
20 Arc::new(res) 20 Arc::new(res)
21} 21}
diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs
index d602c4e04..a8489f89c 100644
--- a/crates/ra_analysis/src/descriptors/mod.rs
+++ b/crates/ra_analysis/src/descriptors/mod.rs
@@ -20,27 +20,28 @@ use crate::{
20 20
21salsa::query_group! { 21salsa::query_group! {
22 pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase { 22 pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase {
23 fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { 23 fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> {
24 type FnScopesQuery;
25 use fn function::imp::fn_scopes;
26 }
27
28 fn _module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> {
24 type ModuleTreeQuery; 29 type ModuleTreeQuery;
25 use fn module::imp::module_tree; 30 use fn module::imp::module_tree;
26 } 31 }
27 fn submodules(source: ModuleSource) -> Cancelable<Arc<Vec<module::imp::Submodule>>> { 32 fn _module_scope(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<ModuleScope>> {
28 type SubmodulesQuery;
29 use fn module::imp::submodules;
30 }
31 fn module_scope(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<ModuleScope>> {
32 type ModuleScopeQuery; 33 type ModuleScopeQuery;
33 use fn module::imp::module_scope; 34 use fn module::imp::module_scope;
34 } 35 }
35 fn fn_syntax(fn_id: FnId) -> FnDefNode { 36 fn _fn_syntax(fn_id: FnId) -> FnDefNode {
36 type FnSyntaxQuery; 37 type FnSyntaxQuery;
37 // Don't retain syntax trees in memory 38 // Don't retain syntax trees in memory
38 storage volatile; 39 storage volatile;
39 use fn function::imp::fn_syntax; 40 use fn function::imp::fn_syntax;
40 } 41 }
41 fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> { 42 fn _submodules(source: ModuleSource) -> Cancelable<Arc<Vec<module::imp::Submodule>>> {
42 type FnScopesQuery; 43 type SubmodulesQuery;
43 use fn function::imp::fn_scopes; 44 use fn module::imp::submodules;
44 } 45 }
45 } 46 }
46} 47}
diff --git a/crates/ra_analysis/src/descriptors/module/imp.rs b/crates/ra_analysis/src/descriptors/module/imp.rs
index ade96ddc0..defe87216 100644
--- a/crates/ra_analysis/src/descriptors/module/imp.rs
+++ b/crates/ra_analysis/src/descriptors/module/imp.rs
@@ -86,7 +86,7 @@ pub(crate) fn module_scope(
86 source_root_id: SourceRootId, 86 source_root_id: SourceRootId,
87 module_id: ModuleId, 87 module_id: ModuleId,
88) -> Cancelable<Arc<ModuleScope>> { 88) -> Cancelable<Arc<ModuleScope>> {
89 let tree = db.module_tree(source_root_id)?; 89 let tree = db._module_tree(source_root_id)?;
90 let source = module_id.source(&tree).resolve(db); 90 let source = module_id.source(&tree).resolve(db);
91 let res = match source { 91 let res = match source {
92 ModuleSourceNode::SourceFile(it) => ModuleScope::new(it.borrowed().items()), 92 ModuleSourceNode::SourceFile(it) => ModuleScope::new(it.borrowed().items()),
@@ -155,7 +155,7 @@ fn build_subtree(
155 parent, 155 parent,
156 children: Vec::new(), 156 children: Vec::new(),
157 }); 157 });
158 for sub in db.submodules(source)?.iter() { 158 for sub in db._submodules(source)?.iter() {
159 let link = tree.push_link(LinkData { 159 let link = tree.push_link(LinkData {
160 name: sub.name().clone(), 160 name: sub.name().clone(),
161 owner: id, 161 owner: id,
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs
index 055a56b54..047454cff 100644
--- a/crates/ra_analysis/src/descriptors/module/mod.rs
+++ b/crates/ra_analysis/src/descriptors/module/mod.rs
@@ -1,16 +1,137 @@
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::{
9 algo::generate,
5 ast::{self, AstNode, NameOwner}, 10 ast::{self, AstNode, NameOwner},
6 SmolStr, SyntaxNode, SyntaxNodeRef, 11 SmolStr, SyntaxNode,
7}; 12};
8use relative_path::RelativePathBuf; 13use relative_path::RelativePathBuf;
9 14
10use crate::{db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId}; 15use crate::{
16 db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId, FilePosition, Cancelable,
17 descriptors::DescriptorDatabase,
18 input::SourceRootId
19};
11 20
12pub(crate) use self::scope::ModuleScope; 21pub(crate) use self::scope::ModuleScope;
13 22
23/// `ModuleDescriptor` is API entry point to get all the information
24/// about a particular module.
25#[derive(Debug, Clone)]
26pub(crate) struct ModuleDescriptor {
27 tree: Arc<ModuleTree>,
28 source_root_id: SourceRootId,
29 module_id: ModuleId,
30}
31
32impl ModuleDescriptor {
33 /// Lookup `ModuleDescriptor` by `FileId`. Note that this is inherently
34 /// lossy transformation: in general, a single source might correspond to
35 /// several modules.
36 pub fn guess_from_file_id(
37 db: &impl DescriptorDatabase,
38 file_id: FileId,
39 ) -> Cancelable<Option<ModuleDescriptor>> {
40 ModuleDescriptor::guess_from_source(db, file_id, ModuleSource::SourceFile(file_id))
41 }
42
43 /// Lookup `ModuleDescriptor` by position in the source code. Note that this
44 /// is inherently lossy transformation: in general, a single source might
45 /// correspond to several modules.
46 pub fn guess_from_position(
47 db: &impl DescriptorDatabase,
48 position: FilePosition,
49 ) -> Cancelable<Option<ModuleDescriptor>> {
50 let file = db.file_syntax(position.file_id);
51 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset)
52 {
53 Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m),
54 _ => ModuleSource::SourceFile(position.file_id),
55 };
56 ModuleDescriptor::guess_from_source(db, position.file_id, module_source)
57 }
58
59 fn guess_from_source(
60 db: &impl DescriptorDatabase,
61 file_id: FileId,
62 module_source: ModuleSource,
63 ) -> Cancelable<Option<ModuleDescriptor>> {
64 let source_root_id = db.file_source_root(file_id);
65 let module_tree = db._module_tree(source_root_id)?;
66
67 let res = match module_tree.any_module_for_source(module_source) {
68 None => None,
69 Some(module_id) => Some(ModuleDescriptor {
70 tree: module_tree,
71 source_root_id,
72 module_id,
73 }),
74 };
75 Ok(res)
76 }
77
78 /// Returns `mod foo;` or `mod foo {}` node whihc declared this module.
79 /// Returns `None` for the root module
80 pub fn parent_link_source(
81 &self,
82 db: &impl DescriptorDatabase,
83 ) -> Option<(FileId, ast::ModuleNode)> {
84 let link = self.module_id.parent_link(&self.tree)?;
85 let file_id = link.owner(&self.tree).source(&self.tree).file_id();
86 let src = link.bind_source(&self.tree, db);
87 Some((file_id, src))
88 }
89
90 pub fn source(&self) -> ModuleSource {
91 self.module_id.source(&self.tree)
92 }
93
94 /// Parent module. Returns `None` if this is a root module.
95 pub fn parent(&self) -> Option<ModuleDescriptor> {
96 let parent_id = self.module_id.parent(&self.tree)?;
97 Some(ModuleDescriptor {
98 module_id: parent_id,
99 ..self.clone()
100 })
101 }
102
103 /// The root of the tree this module is part of
104 pub fn crate_root(&self) -> ModuleDescriptor {
105 generate(Some(self.clone()), |it| it.parent())
106 .last()
107 .unwrap()
108 }
109
110 /// `name` is `None` for the crate's root module
111 pub fn name(&self) -> Option<SmolStr> {
112 let link = self.module_id.parent_link(&self.tree)?;
113 Some(link.name(&self.tree))
114 }
115
116 /// Finds a child module with the specified name.
117 pub fn child(&self, name: &str) -> Option<ModuleDescriptor> {
118 let child_id = self.module_id.child(&self.tree, name)?;
119 Some(ModuleDescriptor {
120 module_id: child_id,
121 ..self.clone()
122 })
123 }
124
125 /// Returns a `ModuleScope`: a set of items, visible in this module.
126 pub fn scope(&self, db: &impl DescriptorDatabase) -> Cancelable<Arc<ModuleScope>> {
127 db._module_scope(self.source_root_id, self.module_id)
128 }
129
130 pub fn problems(&self, db: &impl DescriptorDatabase) -> Vec<(SyntaxNode, Problem)> {
131 self.module_id.problems(&self.tree, db)
132 }
133}
134
14/// Phisically, rust source is organized as a set of files, but logically it is 135/// 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 136/// organized as a tree of modules. Usually, a single file corresponds to a
16/// single module, but it is not nessary the case. 137/// single module, but it is not nessary the case.
@@ -25,7 +146,7 @@ pub(crate) struct ModuleTree {
25} 146}
26 147
27impl ModuleTree { 148impl ModuleTree {
28 pub(crate) fn modules_for_source(&self, source: ModuleSource) -> Vec<ModuleId> { 149 fn modules_for_source(&self, source: ModuleSource) -> Vec<ModuleId> {
29 self.mods 150 self.mods
30 .iter() 151 .iter()
31 .enumerate() 152 .enumerate()
@@ -34,7 +155,7 @@ impl ModuleTree {
34 .collect() 155 .collect()
35 } 156 }
36 157
37 pub(crate) fn any_module_for_source(&self, source: ModuleSource) -> Option<ModuleId> { 158 fn any_module_for_source(&self, source: ModuleSource) -> Option<ModuleId> {
38 self.modules_for_source(source).pop() 159 self.modules_for_source(source).pop()
39 } 160 }
40} 161}
@@ -58,17 +179,8 @@ enum ModuleSourceNode {
58#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] 179#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
59pub(crate) struct ModuleId(u32); 180pub(crate) struct ModuleId(u32);
60 181
61impl crate::loc2id::NumericId for ModuleId {
62 fn from_u32(id: u32) -> Self {
63 ModuleId(id)
64 }
65 fn to_u32(self) -> u32 {
66 self.0
67 }
68}
69
70#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] 182#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
71pub(crate) struct LinkId(u32); 183struct LinkId(u32);
72 184
73#[derive(Clone, Debug, Hash, PartialEq, Eq)] 185#[derive(Clone, Debug, Hash, PartialEq, Eq)]
74pub enum Problem { 186pub enum Problem {
@@ -82,30 +194,17 @@ pub enum Problem {
82} 194}
83 195
84impl ModuleId { 196impl ModuleId {
85 pub(crate) fn source(self, tree: &ModuleTree) -> ModuleSource { 197 fn source(self, tree: &ModuleTree) -> ModuleSource {
86 tree.module(self).source 198 tree.module(self).source
87 } 199 }
88 pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { 200 fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
89 tree.module(self).parent 201 tree.module(self).parent
90 } 202 }
91 pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> { 203 fn parent(self, tree: &ModuleTree) -> Option<ModuleId> {
92 let link = self.parent_link(tree)?; 204 let link = self.parent_link(tree)?;
93 Some(tree.link(link).owner) 205 Some(tree.link(link).owner)
94 } 206 }
95 pub(crate) fn root(self, tree: &ModuleTree) -> ModuleId { 207 fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
96 let mut curr = self;
97 let mut i = 0;
98 while let Some(next) = curr.parent(tree) {
99 curr = next;
100 i += 1;
101 // simplistic cycle detection
102 if i > 100 {
103 return self;
104 }
105 }
106 curr
107 }
108 pub(crate) fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
109 let link = tree 208 let link = tree
110 .module(self) 209 .module(self)
111 .children 210 .children
@@ -114,11 +213,7 @@ impl ModuleId {
114 .find(|it| it.name == name)?; 213 .find(|it| it.name == name)?;
115 Some(*link.points_to.first()?) 214 Some(*link.points_to.first()?)
116 } 215 }
117 pub(crate) fn problems( 216 fn problems(self, tree: &ModuleTree, db: &impl SyntaxDatabase) -> Vec<(SyntaxNode, Problem)> {
118 self,
119 tree: &ModuleTree,
120 db: &impl SyntaxDatabase,
121 ) -> Vec<(SyntaxNode, Problem)> {
122 tree.module(self) 217 tree.module(self)
123 .children 218 .children
124 .iter() 219 .iter()
@@ -133,14 +228,13 @@ impl ModuleId {
133} 228}
134 229
135impl LinkId { 230impl LinkId {
136 pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId { 231 fn owner(self, tree: &ModuleTree) -> ModuleId {
137 tree.link(self).owner 232 tree.link(self).owner
138 } 233 }
139 pub(crate) fn bind_source<'a>( 234 fn name(self, tree: &ModuleTree) -> SmolStr {
140 self, 235 tree.link(self).name.clone()
141 tree: &ModuleTree, 236 }
142 db: &impl SyntaxDatabase, 237 fn bind_source<'a>(self, tree: &ModuleTree, db: &impl SyntaxDatabase) -> ast::ModuleNode {
143 ) -> ast::ModuleNode {
144 let owner = self.owner(tree); 238 let owner = self.owner(tree);
145 match owner.source(tree).resolve(db) { 239 match owner.source(tree).resolve(db) {
146 ModuleSourceNode::SourceFile(root) => { 240 ModuleSourceNode::SourceFile(root) => {
@@ -163,17 +257,7 @@ struct ModuleData {
163} 257}
164 258
165impl ModuleSource { 259impl ModuleSource {
166 pub(crate) fn for_node(file_id: FileId, node: SyntaxNodeRef) -> ModuleSource { 260 fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource {
167 for node in node.ancestors() {
168 if let Some(m) = ast::Module::cast(node) {
169 if !m.has_semi() {
170 return ModuleSource::new_inline(file_id, m);
171 }
172 }
173 }
174 ModuleSource::SourceFile(file_id)
175 }
176 pub(crate) fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource {
177 assert!(!module.has_semi()); 261 assert!(!module.has_semi());
178 let ptr = SyntaxPtr::new(file_id, module.syntax()); 262 let ptr = SyntaxPtr::new(file_id, module.syntax());
179 ModuleSource::Module(ptr) 263 ModuleSource::Module(ptr)