aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src
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
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')
-rw-r--r--crates/ra_analysis/src/completion/mod.rs25
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs31
-rw-r--r--crates/ra_analysis/src/db.rs4
-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
-rw-r--r--crates/ra_analysis/src/imp.rs136
-rw-r--r--crates/ra_analysis/src/loc2id.rs23
9 files changed, 233 insertions, 203 deletions
diff --git a/crates/ra_analysis/src/completion/mod.rs b/crates/ra_analysis/src/completion/mod.rs
index 2e082705e..5e3ee79dd 100644
--- a/crates/ra_analysis/src/completion/mod.rs
+++ b/crates/ra_analysis/src/completion/mod.rs
@@ -2,7 +2,6 @@ mod reference_completion;
2 2
3use ra_editor::find_node_at_offset; 3use ra_editor::find_node_at_offset;
4use ra_syntax::{ 4use ra_syntax::{
5 algo::find_leaf_at_offset,
6 algo::visit::{visitor_ctx, VisitorCtx}, 5 algo::visit::{visitor_ctx, VisitorCtx},
7 ast, 6 ast,
8 AstNode, AtomEdit, 7 AstNode, AtomEdit,
@@ -12,8 +11,9 @@ use rustc_hash::{FxHashMap};
12 11
13use crate::{ 12use crate::{
14 db::{self, SyntaxDatabase}, 13 db::{self, SyntaxDatabase},
15 descriptors::{DescriptorDatabase, module::ModuleSource}, 14 descriptors::{
16 input::{FilesDatabase}, 15 module::{ModuleDescriptor}
16 },
17 Cancelable, FilePosition 17 Cancelable, FilePosition
18}; 18};
19 19
@@ -38,14 +38,7 @@ pub(crate) fn completions(
38 original_file.reparse(&edit) 38 original_file.reparse(&edit)
39 }; 39 };
40 40
41 let leaf = match find_leaf_at_offset(original_file.syntax(), position.offset).left_biased() { 41 let module = match ModuleDescriptor::guess_from_position(db, position)? {
42 None => return Ok(None),
43 Some(it) => it,
44 };
45 let source_root_id = db.file_source_root(position.file_id);
46 let module_tree = db.module_tree(source_root_id)?;
47 let module_source = ModuleSource::for_node(position.file_id, leaf);
48 let module_id = match module_tree.any_module_for_source(module_source) {
49 None => return Ok(None), 42 None => return Ok(None),
50 Some(it) => it, 43 Some(it) => it,
51 }; 44 };
@@ -55,15 +48,7 @@ pub(crate) fn completions(
55 // First, let's try to complete a reference to some declaration. 48 // First, let's try to complete a reference to some declaration.
56 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { 49 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
57 has_completions = true; 50 has_completions = true;
58 reference_completion::completions( 51 reference_completion::completions(&mut res, db, &module, &file, name_ref)?;
59 &mut res,
60 db,
61 source_root_id,
62 &module_tree,
63 module_id,
64 &file,
65 name_ref,
66 )?;
67 // special case, `trait T { fn foo(i_am_a_name_ref) {} }` 52 // special case, `trait T { fn foo(i_am_a_name_ref) {} }`
68 if is_node::<ast::Param>(name_ref.syntax()) { 53 if is_node::<ast::Param>(name_ref.syntax()) {
69 param_completions(name_ref.syntax(), &mut res); 54 param_completions(name_ref.syntax(), &mut res);
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
index 6c5fd0be6..c94d9af75 100644
--- a/crates/ra_analysis/src/completion/reference_completion.rs
+++ b/crates/ra_analysis/src/completion/reference_completion.rs
@@ -9,20 +9,16 @@ use ra_syntax::{
9 9
10use crate::{ 10use crate::{
11 db::RootDatabase, 11 db::RootDatabase,
12 input::{SourceRootId},
13 completion::CompletionItem, 12 completion::CompletionItem,
14 descriptors::module::{ModuleId, ModuleTree}, 13 descriptors::module::{ModuleDescriptor},
15 descriptors::function::FnScopes, 14 descriptors::function::FnScopes,
16 descriptors::DescriptorDatabase,
17 Cancelable 15 Cancelable
18}; 16};
19 17
20pub(super) fn completions( 18pub(super) fn completions(
21 acc: &mut Vec<CompletionItem>, 19 acc: &mut Vec<CompletionItem>,
22 db: &RootDatabase, 20 db: &RootDatabase,
23 source_root_id: SourceRootId, 21 module: &ModuleDescriptor,
24 module_tree: &ModuleTree,
25 module_id: ModuleId,
26 file: &SourceFileNode, 22 file: &SourceFileNode,
27 name_ref: ast::NameRef, 23 name_ref: ast::NameRef,
28) -> Cancelable<()> { 24) -> Cancelable<()> {
@@ -40,7 +36,7 @@ pub(super) fn completions(
40 complete_expr_snippets(acc); 36 complete_expr_snippets(acc);
41 } 37 }
42 38
43 let module_scope = db.module_scope(source_root_id, module_id)?; 39 let module_scope = module.scope(db)?;
44 acc.extend( 40 acc.extend(
45 module_scope 41 module_scope
46 .entries() 42 .entries()
@@ -56,9 +52,7 @@ pub(super) fn completions(
56 }), 52 }),
57 ); 53 );
58 } 54 }
59 NameRefKind::CratePath(path) => { 55 NameRefKind::CratePath(path) => complete_path(acc, db, module, path)?,
60 complete_path(acc, db, source_root_id, module_tree, module_id, path)?
61 }
62 NameRefKind::BareIdentInMod => { 56 NameRefKind::BareIdentInMod => {
63 let name_range = name_ref.syntax().range(); 57 let name_range = name_ref.syntax().range();
64 let top_node = name_ref 58 let top_node = name_ref
@@ -171,16 +165,14 @@ fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<Completi
171fn complete_path( 165fn complete_path(
172 acc: &mut Vec<CompletionItem>, 166 acc: &mut Vec<CompletionItem>,
173 db: &RootDatabase, 167 db: &RootDatabase,
174 source_root_id: SourceRootId, 168 module: &ModuleDescriptor,
175 module_tree: &ModuleTree,
176 module_id: ModuleId,
177 crate_path: Vec<ast::NameRef>, 169 crate_path: Vec<ast::NameRef>,
178) -> Cancelable<()> { 170) -> Cancelable<()> {
179 let target_module_id = match find_target_module(module_tree, module_id, crate_path) { 171 let target_module = match find_target_module(module, crate_path) {
180 None => return Ok(()), 172 None => return Ok(()),
181 Some(it) => it, 173 Some(it) => it,
182 }; 174 };
183 let module_scope = db.module_scope(source_root_id, target_module_id)?; 175 let module_scope = target_module.scope(db)?;
184 let completions = module_scope.entries().iter().map(|entry| CompletionItem { 176 let completions = module_scope.entries().iter().map(|entry| CompletionItem {
185 label: entry.name().to_string(), 177 label: entry.name().to_string(),
186 lookup: None, 178 lookup: None,
@@ -191,14 +183,13 @@ fn complete_path(
191} 183}
192 184
193fn find_target_module( 185fn find_target_module(
194 module_tree: &ModuleTree, 186 module: &ModuleDescriptor,
195 module_id: ModuleId,
196 mut crate_path: Vec<ast::NameRef>, 187 mut crate_path: Vec<ast::NameRef>,
197) -> Option<ModuleId> { 188) -> Option<ModuleDescriptor> {
198 crate_path.pop(); 189 crate_path.pop();
199 let mut target_module = module_id.root(&module_tree); 190 let mut target_module = module.crate_root();
200 for name in crate_path { 191 for name in crate_path {
201 target_module = target_module.child(module_tree, name.text().as_str())?; 192 target_module = target_module.child(name.text().as_str())?;
202 } 193 }
203 Some(target_module) 194 Some(target_module)
204} 195}
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index d78b6afb9..8133b7875 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -85,10 +85,10 @@ salsa::database_storage! {
85 } 85 }
86 impl DescriptorDatabase { 86 impl DescriptorDatabase {
87 fn module_tree() for ModuleTreeQuery; 87 fn module_tree() for ModuleTreeQuery;
88 fn module_descriptor() for SubmodulesQuery;
89 fn module_scope() for ModuleScopeQuery; 88 fn module_scope() for ModuleScopeQuery;
90 fn fn_syntax() for FnSyntaxQuery;
91 fn fn_scopes() for FnScopesQuery; 89 fn fn_scopes() for FnScopesQuery;
90 fn _fn_syntax() for FnSyntaxQuery;
91 fn _submodules() for SubmodulesQuery;
92 } 92 }
93 } 93 }
94} 94}
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)
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index 812fed32d..e1493bdaa 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -21,7 +21,7 @@ use crate::{
21 db::{self, FileSyntaxQuery, SyntaxDatabase}, 21 db::{self, FileSyntaxQuery, SyntaxDatabase},
22 descriptors::{ 22 descriptors::{
23 function::{FnDescriptor, FnId}, 23 function::{FnDescriptor, FnId},
24 module::{ModuleSource, ModuleTree, Problem}, 24 module::{ModuleDescriptor, Problem},
25 DeclarationDescriptor, DescriptorDatabase, 25 DeclarationDescriptor, DescriptorDatabase,
26 }, 26 },
27 input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE}, 27 input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE},
@@ -216,52 +216,41 @@ impl AnalysisImpl {
216 .sweep(salsa::SweepStrategy::default().discard_values()); 216 .sweep(salsa::SweepStrategy::default().discard_values());
217 Ok(query.search(&buf)) 217 Ok(query.search(&buf))
218 } 218 }
219 fn module_tree(&self, file_id: FileId) -> Cancelable<Arc<ModuleTree>> { 219 /// This return `Vec`: a module may be included from several places. We
220 let source_root = self.db.file_source_root(file_id); 220 /// don't handle this case yet though, so the Vec has length at most one.
221 self.db.module_tree(source_root)
222 }
223 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { 221 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
224 let module_tree = self.module_tree(position.file_id)?; 222 let descr = match ModuleDescriptor::guess_from_position(&*self.db, position)? {
225 let file = self.db.file_syntax(position.file_id); 223 None => return Ok(Vec::new()),
226 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) 224 Some(it) => it,
227 {
228 Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m),
229 _ => ModuleSource::SourceFile(position.file_id),
230 }; 225 };
231 226 let (file_id, decl) = match descr.parent_link_source(&*self.db) {
232 let res = module_tree 227 None => return Ok(Vec::new()),
233 .modules_for_source(module_source) 228 Some(it) => it,
234 .into_iter() 229 };
235 .filter_map(|module_id| { 230 let decl = decl.borrowed();
236 let link = module_id.parent_link(&module_tree)?; 231 let decl_name = decl.name().unwrap();
237 let file_id = link.owner(&module_tree).source(&module_tree).file_id(); 232 let sym = FileSymbol {
238 let decl = link.bind_source(&module_tree, &*self.db); 233 name: decl_name.text(),
239 let decl = decl.borrowed(); 234 node_range: decl_name.syntax().range(),
240 235 kind: MODULE,
241 let decl_name = decl.name().unwrap(); 236 };
242 237 Ok(vec![(file_id, sym)])
243 let sym = FileSymbol {
244 name: decl_name.text(),
245 node_range: decl_name.syntax().range(),
246 kind: MODULE,
247 };
248 Some((file_id, sym))
249 })
250 .collect();
251 Ok(res)
252 } 238 }
239 /// Returns `Vec` for the same reason as `parent_module`
253 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 240 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
254 let module_tree = self.module_tree(file_id)?; 241 let descr = match ModuleDescriptor::guess_from_file_id(&*self.db, file_id)? {
255 let crate_graph = self.db.crate_graph(); 242 None => return Ok(Vec::new()),
256 let res = module_tree 243 Some(it) => it,
257 .modules_for_source(ModuleSource::SourceFile(file_id)) 244 };
258 .into_iter() 245 let root = descr.crate_root();
259 .map(|it| it.root(&module_tree)) 246 let file_id = root
260 .filter_map(|it| it.source(&module_tree).as_file()) 247 .source()
261 .filter_map(|it| crate_graph.crate_id_for_crate_root(it)) 248 .as_file()
262 .collect(); 249 .expect("root module always has a file as a source");
263 250
264 Ok(res) 251 let crate_graph = self.db.crate_graph();
252 let crate_id = crate_graph.crate_id_for_crate_root(file_id);
253 Ok(crate_id.into_iter().collect())
265 } 254 }
266 pub fn crate_root(&self, crate_id: CrateId) -> FileId { 255 pub fn crate_root(&self, crate_id: CrateId) -> FileId {
267 self.db.crate_graph().crate_roots[&crate_id] 256 self.db.crate_graph().crate_roots[&crate_id]
@@ -273,7 +262,6 @@ impl AnalysisImpl {
273 &self, 262 &self,
274 position: FilePosition, 263 position: FilePosition,
275 ) -> Cancelable<Vec<(FileId, FileSymbol)>> { 264 ) -> Cancelable<Vec<(FileId, FileSymbol)>> {
276 let module_tree = self.module_tree(position.file_id)?;
277 let file = self.db.file_syntax(position.file_id); 265 let file = self.db.file_syntax(position.file_id);
278 let syntax = file.syntax(); 266 let syntax = file.syntax();
279 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { 267 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
@@ -299,25 +287,23 @@ impl AnalysisImpl {
299 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { 287 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
300 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { 288 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
301 if module.has_semi() { 289 if module.has_semi() {
302 let file_ids = self.resolve_module(&*module_tree, position.file_id, module); 290 let parent_module =
303 291 ModuleDescriptor::guess_from_file_id(&*self.db, position.file_id)?;
304 let res = file_ids 292 let child_name = module.name();
305 .into_iter() 293 match (parent_module, child_name) {
306 .map(|id| { 294 (Some(parent_module), Some(child_name)) => {
307 let name = module 295 if let Some(child) = parent_module.child(&child_name.text()) {
308 .name() 296 let file_id = child.source().file_id();
309 .map(|n| n.text()) 297 let symbol = FileSymbol {
310 .unwrap_or_else(|| SmolStr::new("")); 298 name: child_name.text(),
311 let symbol = FileSymbol { 299 node_range: TextRange::offset_len(0.into(), 0.into()),
312 name, 300 kind: MODULE,
313 node_range: TextRange::offset_len(0.into(), 0.into()), 301 };
314 kind: MODULE, 302 return Ok(vec![(file_id, symbol)]);
315 }; 303 }
316 (id, symbol) 304 }
317 }) 305 _ => (),
318 .collect(); 306 }
319
320 return Ok(res);
321 } 307 }
322 } 308 }
323 } 309 }
@@ -364,7 +350,6 @@ impl AnalysisImpl {
364 } 350 }
365 351
366 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { 352 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
367 let module_tree = self.module_tree(file_id)?;
368 let syntax = self.db.file_syntax(file_id); 353 let syntax = self.db.file_syntax(file_id);
369 354
370 let mut res = ra_editor::diagnostics(&syntax) 355 let mut res = ra_editor::diagnostics(&syntax)
@@ -375,8 +360,8 @@ impl AnalysisImpl {
375 fix: None, 360 fix: None,
376 }) 361 })
377 .collect::<Vec<_>>(); 362 .collect::<Vec<_>>();
378 if let Some(m) = module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) { 363 if let Some(m) = ModuleDescriptor::guess_from_file_id(&*self.db, file_id)? {
379 for (name_node, problem) in m.problems(&module_tree, &*self.db) { 364 for (name_node, problem) in m.problems(&*self.db) {
380 let diag = match problem { 365 let diag = match problem {
381 Problem::UnresolvedModule { candidate } => { 366 Problem::UnresolvedModule { candidate } => {
382 let create_file = FileSystemEdit::CreateFile { 367 let create_file = FileSystemEdit::CreateFile {
@@ -526,27 +511,6 @@ impl AnalysisImpl {
526 query.limit(4); 511 query.limit(4);
527 self.world_symbols(query) 512 self.world_symbols(query)
528 } 513 }
529
530 fn resolve_module(
531 &self,
532 module_tree: &ModuleTree,
533 file_id: FileId,
534 module: ast::Module,
535 ) -> Vec<FileId> {
536 let name = match module.name() {
537 Some(name) => name.text(),
538 None => return Vec::new(),
539 };
540 let module_id = match module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) {
541 Some(id) => id,
542 None => return Vec::new(),
543 };
544 module_id
545 .child(module_tree, name.as_str())
546 .and_then(|it| it.source(&module_tree).as_file())
547 .into_iter()
548 .collect()
549 }
550} 514}
551 515
552impl SourceChange { 516impl SourceChange {
diff --git a/crates/ra_analysis/src/loc2id.rs b/crates/ra_analysis/src/loc2id.rs
index 8eaa24997..8c297156a 100644
--- a/crates/ra_analysis/src/loc2id.rs
+++ b/crates/ra_analysis/src/loc2id.rs
@@ -72,17 +72,22 @@ pub(crate) trait NumericId: Clone + Eq + Hash {
72 fn to_u32(self) -> u32; 72 fn to_u32(self) -> u32;
73} 73}
74 74
75macro_rules! impl_numeric_id {
76 ($id:ident) => {
77 impl NumericId for $id {
78 fn from_u32(id: u32) -> Self {
79 $id(id)
80 }
81 fn to_u32(self) -> u32 {
82 self.0
83 }
84 }
85 };
86}
87
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
76pub(crate) struct FnId(u32); 89pub(crate) struct FnId(u32);
77 90impl_numeric_id!(FnId);
78impl NumericId for FnId {
79 fn from_u32(id: u32) -> FnId {
80 FnId(id)
81 }
82 fn to_u32(self) -> u32 {
83 self.0
84 }
85}
86 91
87pub(crate) trait IdDatabase: salsa::Database { 92pub(crate) trait IdDatabase: salsa::Database {
88 fn id_maps(&self) -> &IdMaps; 93 fn id_maps(&self) -> &IdMaps;