aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/completion/reference_completion.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/completion/reference_completion.rs')
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs78
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;
3use ra_syntax::{ 3use 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
10use crate::{ 10use 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
20pub(super) fn completions( 20pub(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
108fn complete_local_name<'a>( 114fn 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
135fn 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
158fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { 146fn 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
180fn complete_path( 168fn 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