diff options
Diffstat (limited to 'crates/ra_analysis/src/completion/mod.rs')
-rw-r--r-- | crates/ra_analysis/src/completion/mod.rs | 54 |
1 files changed, 24 insertions, 30 deletions
diff --git a/crates/ra_analysis/src/completion/mod.rs b/crates/ra_analysis/src/completion/mod.rs index 2e082705e..e5ba92acd 100644 --- a/crates/ra_analysis/src/completion/mod.rs +++ b/crates/ra_analysis/src/completion/mod.rs | |||
@@ -2,18 +2,16 @@ 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, |
9 | SyntaxNodeRef, | 8 | SyntaxNodeRef, |
10 | }; | 9 | }; |
10 | use ra_db::SyntaxDatabase; | ||
11 | use rustc_hash::{FxHashMap}; | 11 | use rustc_hash::{FxHashMap}; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | db::{self, SyntaxDatabase}, | 14 | db, |
15 | descriptors::{DescriptorDatabase, module::ModuleSource}, | ||
16 | input::{FilesDatabase}, | ||
17 | Cancelable, FilePosition | 15 | Cancelable, FilePosition |
18 | }; | 16 | }; |
19 | 17 | ||
@@ -31,39 +29,21 @@ pub(crate) fn completions( | |||
31 | db: &db::RootDatabase, | 29 | db: &db::RootDatabase, |
32 | position: FilePosition, | 30 | position: FilePosition, |
33 | ) -> Cancelable<Option<Vec<CompletionItem>>> { | 31 | ) -> Cancelable<Option<Vec<CompletionItem>>> { |
34 | let original_file = db.file_syntax(position.file_id); | 32 | let original_file = db.source_file(position.file_id); |
35 | // Insert a fake ident to get a valid parse tree | 33 | // Insert a fake ident to get a valid parse tree |
36 | let file = { | 34 | let file = { |
37 | let edit = AtomEdit::insert(position.offset, "intellijRulezz".to_string()); | 35 | let edit = AtomEdit::insert(position.offset, "intellijRulezz".to_string()); |
38 | original_file.reparse(&edit) | 36 | original_file.reparse(&edit) |
39 | }; | 37 | }; |
40 | 38 | ||
41 | let leaf = match find_leaf_at_offset(original_file.syntax(), position.offset).left_biased() { | 39 | let module = ctry!(hir::Module::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), | ||
50 | Some(it) => it, | ||
51 | }; | ||
52 | 40 | ||
53 | let mut res = Vec::new(); | 41 | let mut res = Vec::new(); |
54 | let mut has_completions = false; | 42 | let mut has_completions = false; |
55 | // First, let's try to complete a reference to some declaration. | 43 | // 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) { | 44 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { |
57 | has_completions = true; | 45 | has_completions = true; |
58 | reference_completion::completions( | 46 | 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) {} }` | 47 | // special case, `trait T { fn foo(i_am_a_name_ref) {} }` |
68 | if is_node::<ast::Param>(name_ref.syntax()) { | 48 | if is_node::<ast::Param>(name_ref.syntax()) { |
69 | param_completions(name_ref.syntax(), &mut res); | 49 | param_completions(name_ref.syntax(), &mut res); |
@@ -219,9 +199,9 @@ mod tests { | |||
219 | <|> | 199 | <|> |
220 | } | 200 | } |
221 | ", | 201 | ", |
222 | r#"[CompletionItem { label: "Foo", lookup: None, snippet: None }, | 202 | r#"[CompletionItem { label: "quux", lookup: None, snippet: None }, |
223 | CompletionItem { label: "Baz", lookup: None, snippet: None }, | 203 | CompletionItem { label: "Foo", lookup: None, snippet: None }, |
224 | CompletionItem { label: "quux", lookup: None, snippet: None }]"#, | 204 | CompletionItem { label: "Baz", lookup: None, snippet: None }]"#, |
225 | ); | 205 | ); |
226 | } | 206 | } |
227 | 207 | ||
@@ -236,6 +216,20 @@ mod tests { | |||
236 | } | 216 | } |
237 | 217 | ||
238 | #[test] | 218 | #[test] |
219 | fn test_completion_self_path() { | ||
220 | check_scope_completion( | ||
221 | r" | ||
222 | use self::m::<|>; | ||
223 | |||
224 | mod m { | ||
225 | struct Bar; | ||
226 | } | ||
227 | ", | ||
228 | r#"[CompletionItem { label: "Bar", lookup: None, snippet: None }]"#, | ||
229 | ); | ||
230 | } | ||
231 | |||
232 | #[test] | ||
239 | fn test_completion_mod_scope_nested() { | 233 | fn test_completion_mod_scope_nested() { |
240 | check_scope_completion( | 234 | check_scope_completion( |
241 | r" | 235 | r" |
@@ -245,8 +239,8 @@ mod tests { | |||
245 | fn quux() { <|> } | 239 | fn quux() { <|> } |
246 | } | 240 | } |
247 | ", | 241 | ", |
248 | r#"[CompletionItem { label: "Bar", lookup: None, snippet: None }, | 242 | r#"[CompletionItem { label: "quux", lookup: None, snippet: None }, |
249 | CompletionItem { label: "quux", lookup: None, snippet: None }]"#, | 243 | CompletionItem { label: "Bar", lookup: None, snippet: None }]"#, |
250 | ); | 244 | ); |
251 | } | 245 | } |
252 | 246 | ||