diff options
Diffstat (limited to 'crates/ra_analysis/src/completion/reference_completion.rs')
-rw-r--r-- | crates/ra_analysis/src/completion/reference_completion.rs | 78 |
1 files changed, 30 insertions, 48 deletions
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs index b08174968..13d4de9d5 100644 --- a/crates/ra_analysis/src/completion/reference_completion.rs +++ b/crates/ra_analysis/src/completion/reference_completion.rs | |||
@@ -3,24 +3,26 @@ use ra_editor::find_node_at_offset; | |||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | algo::visit::{visitor, Visitor}, | 4 | algo::visit::{visitor, Visitor}, |
5 | SourceFileNode, AstNode, | 5 | SourceFileNode, AstNode, |
6 | ast::{self, AstChildren, ModuleItemOwner, LoopBodyOwner}, | 6 | ast::{self, LoopBodyOwner}, |
7 | SyntaxKind::*, | 7 | SyntaxKind::*, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::RootDatabase, | 11 | db::RootDatabase, |
12 | input::FilesDatabase, | 12 | input::{SourceRootId}, |
13 | completion::CompletionItem, | 13 | completion::CompletionItem, |
14 | descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource}, | 14 | descriptors::module::{ModuleId, ModuleScope, ModuleTree}, |
15 | descriptors::function::FnScopes, | 15 | descriptors::function::FnScopes, |
16 | descriptors::DescriptorDatabase, | 16 | descriptors::DescriptorDatabase, |
17 | FileId, Cancelable | 17 | Cancelable |
18 | }; | 18 | }; |
19 | 19 | ||
20 | pub(super) fn completions( | 20 | pub(super) fn completions( |
21 | acc: &mut Vec<CompletionItem>, | 21 | acc: &mut Vec<CompletionItem>, |
22 | db: &RootDatabase, | 22 | db: &RootDatabase, |
23 | file_id: FileId, | 23 | source_root_id: SourceRootId, |
24 | module_tree: &ModuleTree, | ||
25 | module_id: ModuleId, | ||
24 | file: &SourceFileNode, | 26 | file: &SourceFileNode, |
25 | name_ref: ast::NameRef, | 27 | name_ref: ast::NameRef, |
26 | ) -> Cancelable<()> { | 28 | ) -> Cancelable<()> { |
@@ -28,14 +30,18 @@ pub(super) fn completions( | |||
28 | Some(it) => it, | 30 | Some(it) => it, |
29 | None => return Ok(()), | 31 | None => return Ok(()), |
30 | }; | 32 | }; |
33 | |||
31 | match kind { | 34 | match kind { |
32 | NameRefKind::LocalRef => { | 35 | NameRefKind::LocalRef => { |
33 | if let Some(fn_def) = complete_local_name(acc, &file, name_ref) { | 36 | let module_scope = db.module_scope(source_root_id, module_id)?; |
37 | if let Some(fn_def) = complete_local_name(acc, &module_scope, name_ref) { | ||
34 | complete_expr_keywords(&file, fn_def, name_ref, acc); | 38 | complete_expr_keywords(&file, fn_def, name_ref, acc); |
35 | complete_expr_snippets(acc); | 39 | complete_expr_snippets(acc); |
36 | } | 40 | } |
37 | } | 41 | } |
38 | NameRefKind::CratePath(path) => complete_path(acc, db, file_id, path)?, | 42 | NameRefKind::CratePath(path) => { |
43 | complete_path(acc, db, source_root_id, module_tree, module_id, path)? | ||
44 | } | ||
39 | NameRefKind::BareIdentInMod => { | 45 | NameRefKind::BareIdentInMod => { |
40 | let name_range = name_ref.syntax().range(); | 46 | let name_range = name_ref.syntax().range(); |
41 | let top_node = name_ref | 47 | let top_node = name_ref |
@@ -107,45 +113,26 @@ fn crate_path(mut path: ast::Path) -> Option<Vec<ast::NameRef>> { | |||
107 | 113 | ||
108 | fn complete_local_name<'a>( | 114 | fn complete_local_name<'a>( |
109 | acc: &mut Vec<CompletionItem>, | 115 | acc: &mut Vec<CompletionItem>, |
110 | file: &SourceFileNode, | 116 | module_scope: &ModuleScope, |
111 | name_ref: ast::NameRef<'a>, | 117 | name_ref: ast::NameRef<'a>, |
112 | ) -> Option<ast::FnDef<'a>> { | 118 | ) -> Option<ast::FnDef<'a>> { |
113 | let mut enclosing_fn = None; | 119 | let enclosing_fn = name_ref |
114 | for node in name_ref.syntax().ancestors() { | 120 | .syntax() |
115 | if let Some(items) = visitor() | 121 | .ancestors() |
116 | .visit::<ast::SourceFile, _>(|it| Some(it.items())) | 122 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) |
117 | .visit::<ast::Module, _>(|it| Some(it.item_list()?.items())) | 123 | .find_map(ast::FnDef::cast); |
118 | .accept(node) | 124 | if let Some(fn_def) = enclosing_fn { |
119 | { | 125 | let scopes = FnScopes::new(fn_def); |
120 | if let Some(items) = items { | 126 | complete_fn(name_ref, &scopes, acc); |
121 | complete_module_items(file, items, Some(name_ref), acc); | ||
122 | } | ||
123 | break; | ||
124 | } else if enclosing_fn.is_none() { | ||
125 | if let Some(fn_def) = ast::FnDef::cast(node) { | ||
126 | enclosing_fn = Some(fn_def); | ||
127 | let scopes = FnScopes::new(fn_def); | ||
128 | complete_fn(name_ref, &scopes, acc); | ||
129 | } | ||
130 | } | ||
131 | } | 127 | } |
132 | enclosing_fn | ||
133 | } | ||
134 | 128 | ||
135 | fn complete_module_items( | ||
136 | file: &SourceFileNode, | ||
137 | items: AstChildren<ast::ModuleItem>, | ||
138 | this_item: Option<ast::NameRef>, | ||
139 | acc: &mut Vec<CompletionItem>, | ||
140 | ) { | ||
141 | let scope = ModuleScope::new(items); // FIXME | ||
142 | acc.extend( | 129 | acc.extend( |
143 | scope | 130 | module_scope |
144 | .entries() | 131 | .entries() |
145 | .iter() | 132 | .iter() |
146 | .filter(|entry| { | 133 | .filter(|entry| { |
147 | let syntax = entry.ptr().resolve(file); | 134 | // Don't expose this item |
148 | Some(syntax.borrowed()) != this_item.map(|it| it.syntax()) | 135 | !entry.ptr().range().is_subrange(&name_ref.syntax().range()) |
149 | }) | 136 | }) |
150 | .map(|entry| CompletionItem { | 137 | .map(|entry| CompletionItem { |
151 | label: entry.name().to_string(), | 138 | label: entry.name().to_string(), |
@@ -153,6 +140,7 @@ fn complete_module_items( | |||
153 | snippet: None, | 140 | snippet: None, |
154 | }), | 141 | }), |
155 | ); | 142 | ); |
143 | enclosing_fn | ||
156 | } | 144 | } |
157 | 145 | ||
158 | fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { | 146 | fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { |
@@ -180,16 +168,12 @@ fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<Completi | |||
180 | fn complete_path( | 168 | fn complete_path( |
181 | acc: &mut Vec<CompletionItem>, | 169 | acc: &mut Vec<CompletionItem>, |
182 | db: &RootDatabase, | 170 | db: &RootDatabase, |
183 | file_id: FileId, | 171 | source_root_id: SourceRootId, |
172 | module_tree: &ModuleTree, | ||
173 | module_id: ModuleId, | ||
184 | crate_path: Vec<ast::NameRef>, | 174 | crate_path: Vec<ast::NameRef>, |
185 | ) -> Cancelable<()> { | 175 | ) -> Cancelable<()> { |
186 | let source_root_id = db.file_source_root(file_id); | 176 | let target_module_id = match find_target_module(module_tree, module_id, crate_path) { |
187 | let module_tree = db.module_tree(source_root_id)?; | ||
188 | let module_id = match module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) { | ||
189 | None => return Ok(()), | ||
190 | Some(it) => it, | ||
191 | }; | ||
192 | let target_module_id = match find_target_module(&module_tree, module_id, crate_path) { | ||
193 | None => return Ok(()), | 177 | None => return Ok(()), |
194 | Some(it) => it, | 178 | Some(it) => it, |
195 | }; | 179 | }; |
@@ -327,5 +311,3 @@ fn complete_expr_snippets(acc: &mut Vec<CompletionItem>) { | |||
327 | snippet: Some("eprintln!(\"$0 = {:#?}\", $0);".to_string()), | 311 | snippet: Some("eprintln!(\"$0 = {:#?}\", $0);".to_string()), |
328 | }); | 312 | }); |
329 | } | 313 | } |
330 | |||
331 | |||