diff options
-rw-r--r-- | crates/ra_analysis/src/completion/mod.rs | 25 | ||||
-rw-r--r-- | crates/ra_analysis/src/completion/reference_completion.rs | 31 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/mod.rs | 43 |
3 files changed, 31 insertions, 68 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 | ||
3 | use ra_editor::find_node_at_offset; | 3 | use ra_editor::find_node_at_offset; |
4 | use ra_syntax::{ | 4 | use 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 | ||
13 | use crate::{ | 12 | use 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 | ||
10 | use crate::{ | 10 | use 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 | ||
20 | pub(super) fn completions( | 18 | pub(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 | |||
171 | fn complete_path( | 165 | fn 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 | ||
193 | fn find_target_module( | 185 | fn 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/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index d0560244a..a894025ed 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs | |||
@@ -15,6 +15,7 @@ use relative_path::RelativePathBuf; | |||
15 | use crate::{ | 15 | use crate::{ |
16 | db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId, FilePosition, Cancelable, | 16 | db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId, FilePosition, Cancelable, |
17 | descriptors::DescriptorDatabase, | 17 | descriptors::DescriptorDatabase, |
18 | input::SourceRootId | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | pub(crate) use self::scope::ModuleScope; | 21 | pub(crate) use self::scope::ModuleScope; |
@@ -24,6 +25,7 @@ pub(crate) use self::scope::ModuleScope; | |||
24 | #[derive(Debug, Clone)] | 25 | #[derive(Debug, Clone)] |
25 | pub(crate) struct ModuleDescriptor { | 26 | pub(crate) struct ModuleDescriptor { |
26 | tree: Arc<ModuleTree>, | 27 | tree: Arc<ModuleTree>, |
28 | source_root_id: SourceRootId, | ||
27 | module_id: ModuleId, | 29 | module_id: ModuleId, |
28 | } | 30 | } |
29 | 31 | ||
@@ -59,13 +61,14 @@ impl ModuleDescriptor { | |||
59 | file_id: FileId, | 61 | file_id: FileId, |
60 | module_source: ModuleSource, | 62 | module_source: ModuleSource, |
61 | ) -> Cancelable<Option<ModuleDescriptor>> { | 63 | ) -> Cancelable<Option<ModuleDescriptor>> { |
62 | let source_root = db.file_source_root(file_id); | 64 | let source_root_id = db.file_source_root(file_id); |
63 | let module_tree = db.module_tree(source_root)?; | 65 | let module_tree = db.module_tree(source_root_id)?; |
64 | 66 | ||
65 | let res = match module_tree.any_module_for_source(module_source) { | 67 | let res = match module_tree.any_module_for_source(module_source) { |
66 | None => None, | 68 | None => None, |
67 | Some(module_id) => Some(ModuleDescriptor { | 69 | Some(module_id) => Some(ModuleDescriptor { |
68 | tree: module_tree, | 70 | tree: module_tree, |
71 | source_root_id, | ||
69 | module_id, | 72 | module_id, |
70 | }), | 73 | }), |
71 | }; | 74 | }; |
@@ -92,8 +95,8 @@ impl ModuleDescriptor { | |||
92 | pub fn parent(&self) -> Option<ModuleDescriptor> { | 95 | pub fn parent(&self) -> Option<ModuleDescriptor> { |
93 | let parent_id = self.module_id.parent(&self.tree)?; | 96 | let parent_id = self.module_id.parent(&self.tree)?; |
94 | Some(ModuleDescriptor { | 97 | Some(ModuleDescriptor { |
95 | tree: Arc::clone(&self.tree), | ||
96 | module_id: parent_id, | 98 | module_id: parent_id, |
99 | ..self.clone() | ||
97 | }) | 100 | }) |
98 | } | 101 | } |
99 | 102 | ||
@@ -109,13 +112,20 @@ impl ModuleDescriptor { | |||
109 | let link = self.module_id.parent_link(&self.tree)?; | 112 | let link = self.module_id.parent_link(&self.tree)?; |
110 | Some(link.name(&self.tree)) | 113 | Some(link.name(&self.tree)) |
111 | } | 114 | } |
115 | |||
116 | /// Finds a child module with the specified name. | ||
112 | pub fn child(&self, name: &str) -> Option<ModuleDescriptor> { | 117 | pub fn child(&self, name: &str) -> Option<ModuleDescriptor> { |
113 | let child_id = self.module_id.child(&self.tree, name)?; | 118 | let child_id = self.module_id.child(&self.tree, name)?; |
114 | Some(ModuleDescriptor { | 119 | Some(ModuleDescriptor { |
115 | tree: Arc::clone(&self.tree), | ||
116 | module_id: child_id, | 120 | module_id: child_id, |
121 | ..self.clone() | ||
117 | }) | 122 | }) |
118 | } | 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 | } | ||
119 | } | 129 | } |
120 | 130 | ||
121 | /// Phisically, rust source is organized as a set of files, but logically it is | 131 | /// Phisically, rust source is organized as a set of files, but logically it is |
@@ -190,20 +200,7 @@ impl ModuleId { | |||
190 | let link = self.parent_link(tree)?; | 200 | let link = self.parent_link(tree)?; |
191 | Some(tree.link(link).owner) | 201 | Some(tree.link(link).owner) |
192 | } | 202 | } |
193 | pub(crate) fn root(self, tree: &ModuleTree) -> ModuleId { | 203 | fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { |
194 | let mut curr = self; | ||
195 | let mut i = 0; | ||
196 | while let Some(next) = curr.parent(tree) { | ||
197 | curr = next; | ||
198 | i += 1; | ||
199 | // simplistic cycle detection | ||
200 | if i > 100 { | ||
201 | return self; | ||
202 | } | ||
203 | } | ||
204 | curr | ||
205 | } | ||
206 | pub(crate) fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { | ||
207 | let link = tree | 204 | let link = tree |
208 | .module(self) | 205 | .module(self) |
209 | .children | 206 | .children |
@@ -260,16 +257,6 @@ struct ModuleData { | |||
260 | } | 257 | } |
261 | 258 | ||
262 | impl ModuleSource { | 259 | impl ModuleSource { |
263 | pub(crate) fn for_node(file_id: FileId, node: SyntaxNodeRef) -> ModuleSource { | ||
264 | for node in node.ancestors() { | ||
265 | if let Some(m) = ast::Module::cast(node) { | ||
266 | if !m.has_semi() { | ||
267 | return ModuleSource::new_inline(file_id, m); | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | ModuleSource::SourceFile(file_id) | ||
272 | } | ||
273 | pub(crate) fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource { | 260 | pub(crate) fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource { |
274 | assert!(!module.has_semi()); | 261 | assert!(!module.has_semi()); |
275 | let ptr = SyntaxPtr::new(file_id, module.syntax()); | 262 | let ptr = SyntaxPtr::new(file_id, module.syntax()); |