aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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/descriptors/module/mod.rs43
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
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/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;
15use crate::{ 15use 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
20pub(crate) use self::scope::ModuleScope; 21pub(crate) use self::scope::ModuleScope;
@@ -24,6 +25,7 @@ pub(crate) use self::scope::ModuleScope;
24#[derive(Debug, Clone)] 25#[derive(Debug, Clone)]
25pub(crate) struct ModuleDescriptor { 26pub(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
262impl ModuleSource { 259impl 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());