diff options
author | Florian Diebold <[email protected]> | 2019-02-01 22:06:57 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-02-01 22:24:26 +0000 |
commit | c5852f422ff45adaa21815c1a15e03b067a56a82 (patch) | |
tree | c53ff3531cbbad182e821eb92fa9ad201d2bff0c /crates | |
parent | d571d26955148befd6986008a5112fff3a901c43 (diff) |
Some cleanup and additional tests
Diffstat (limited to 'crates')
6 files changed, 138 insertions, 30 deletions
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 7929e8b7c..6c87d0df7 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -46,7 +46,6 @@ pub(crate) enum Scope { | |||
46 | 46 | ||
47 | #[derive(Debug, Clone, PartialEq, Eq)] | 47 | #[derive(Debug, Clone, PartialEq, Eq)] |
48 | pub enum Resolution { | 48 | pub enum Resolution { |
49 | // FIXME make these tuple variants | ||
50 | /// An item | 49 | /// An item |
51 | Def(ModuleDef), | 50 | Def(ModuleDef), |
52 | /// A local binding (only value namespace) | 51 | /// A local binding (only value namespace) |
@@ -85,7 +84,7 @@ impl Resolver { | |||
85 | 84 | ||
86 | pub fn all_names(&self) -> FxHashMap<Name, PerNs<Resolution>> { | 85 | pub fn all_names(&self) -> FxHashMap<Name, PerNs<Resolution>> { |
87 | let mut names = FxHashMap::default(); | 86 | let mut names = FxHashMap::default(); |
88 | for scope in &self.scopes { | 87 | for scope in self.scopes.iter().rev() { |
89 | scope.collect_names(&mut |name, res| { | 88 | scope.collect_names(&mut |name, res| { |
90 | let current: &mut PerNs<Resolution> = names.entry(name).or_default(); | 89 | let current: &mut PerNs<Resolution> = names.entry(name).or_default(); |
91 | if current.types.is_none() { | 90 | if current.types.is_none() { |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index ce929cf3e..59f782277 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -204,12 +204,13 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te | |||
204 | } | 204 | } |
205 | 205 | ||
206 | pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver { | 206 | pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver { |
207 | let file = db.parse(position.file_id); | 207 | let file_id = position.file_id; |
208 | let file = db.parse(file_id); | ||
208 | find_leaf_at_offset(file.syntax(), position.offset) | 209 | find_leaf_at_offset(file.syntax(), position.offset) |
209 | .find_map(|node| { | 210 | .find_map(|node| { |
210 | node.ancestors().find_map(|node| { | 211 | node.ancestors().find_map(|node| { |
211 | if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { | 212 | if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { |
212 | if let Some(func) = function_from_child_node(db, position.file_id, node) { | 213 | if let Some(func) = function_from_child_node(db, file_id, node) { |
213 | let scopes = func.scopes(db); | 214 | let scopes = func.scopes(db); |
214 | let scope = scopes.scope_for_offset(position.offset); | 215 | let scope = scopes.scope_for_offset(position.offset); |
215 | Some(expr::resolver_for_scope(func.body(db), db, scope)) | 216 | Some(expr::resolver_for_scope(func.body(db), db, scope)) |
@@ -218,9 +219,15 @@ pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> R | |||
218 | None | 219 | None |
219 | } | 220 | } |
220 | } else if let Some(module) = ast::Module::cast(node) { | 221 | } else if let Some(module) = ast::Module::cast(node) { |
221 | Some(module_from_declaration(db, position.file_id, module)?.resolver(db)) | 222 | Some(module_from_declaration(db, file_id, module)?.resolver(db)) |
222 | } else if let Some(_) = ast::SourceFile::cast(node) { | 223 | } else if let Some(_) = ast::SourceFile::cast(node) { |
223 | Some(module_from_source(db, position.file_id.into(), None)?.resolver(db)) | 224 | Some(module_from_source(db, file_id.into(), None)?.resolver(db)) |
225 | } else if let Some(s) = ast::StructDef::cast(node) { | ||
226 | let module = module_from_child_node(db, file_id, s.syntax())?; | ||
227 | Some(struct_from_module(db, module, s).resolver(db)) | ||
228 | } else if let Some(e) = ast::EnumDef::cast(node) { | ||
229 | let module = module_from_child_node(db, file_id, e.syntax())?; | ||
230 | Some(enum_from_module(db, module, e).resolver(db)) | ||
224 | } else { | 231 | } else { |
225 | // TODO add missing cases | 232 | // TODO add missing cases |
226 | None | 233 | None |
@@ -246,6 +253,12 @@ pub fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNo | |||
246 | Some(module_from_declaration(db, file_id, module)?.resolver(db)) | 253 | Some(module_from_declaration(db, file_id, module)?.resolver(db)) |
247 | } else if let Some(_) = ast::SourceFile::cast(node) { | 254 | } else if let Some(_) = ast::SourceFile::cast(node) { |
248 | Some(module_from_source(db, file_id.into(), None)?.resolver(db)) | 255 | Some(module_from_source(db, file_id.into(), None)?.resolver(db)) |
256 | } else if let Some(s) = ast::StructDef::cast(node) { | ||
257 | let module = module_from_child_node(db, file_id, s.syntax())?; | ||
258 | Some(struct_from_module(db, module, s).resolver(db)) | ||
259 | } else if let Some(e) = ast::EnumDef::cast(node) { | ||
260 | let module = module_from_child_node(db, file_id, e.syntax())?; | ||
261 | Some(enum_from_module(db, module, e).resolver(db)) | ||
249 | } else { | 262 | } else { |
250 | // TODO add missing cases | 263 | // TODO add missing cases |
251 | None | 264 | None |
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 8e0f6a79e..0b9948d4b 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -66,6 +66,17 @@ mod tests { | |||
66 | } | 66 | } |
67 | 67 | ||
68 | #[test] | 68 | #[test] |
69 | #[ignore] // should not complete foo, which currently doesn't work | ||
70 | fn dont_complete_current_use() { | ||
71 | check_reference_completion( | ||
72 | "dont_complete_current_use", | ||
73 | r" | ||
74 | use self::foo<|>; | ||
75 | ", | ||
76 | ); | ||
77 | } | ||
78 | |||
79 | #[test] | ||
69 | fn completes_mod_with_docs() { | 80 | fn completes_mod_with_docs() { |
70 | check_reference_completion( | 81 | check_reference_completion( |
71 | "mod_with_docs", | 82 | "mod_with_docs", |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 3488d6480..44514ab2b 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -6,29 +6,15 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { | |||
6 | } | 6 | } |
7 | let names = ctx.resolver.all_names(); | 7 | let names = ctx.resolver.all_names(); |
8 | 8 | ||
9 | // let module_scope = module.scope(ctx.db); | 9 | names.into_iter().for_each(|(name, res)| { |
10 | names | 10 | CompletionItem::new( |
11 | .into_iter() | 11 | CompletionKind::Reference, |
12 | // FIXME check tests | 12 | ctx.source_range(), |
13 | // .filter(|(_name, res)| { | 13 | name.to_string(), |
14 | // // For cases like `use self::foo<|>` don't suggest foo itself. | 14 | ) |
15 | // match res.import { | 15 | .from_resolution(ctx, &res) |
16 | // None => true, | 16 | .add_to(acc) |
17 | // Some(import) => { | 17 | }); |
18 | // let source = module.import_source(ctx.db, import); | ||
19 | // !source.syntax().range().is_subrange(&ctx.leaf.range()) | ||
20 | // } | ||
21 | // } | ||
22 | // }) | ||
23 | .for_each(|(name, res)| { | ||
24 | CompletionItem::new( | ||
25 | CompletionKind::Reference, | ||
26 | ctx.source_range(), | ||
27 | name.to_string(), | ||
28 | ) | ||
29 | .from_resolution(ctx, &res) | ||
30 | .add_to(acc) | ||
31 | }); | ||
32 | } | 18 | } |
33 | 19 | ||
34 | #[cfg(test)] | 20 | #[cfg(test)] |
@@ -87,6 +73,30 @@ mod tests { | |||
87 | } | 73 | } |
88 | 74 | ||
89 | #[test] | 75 | #[test] |
76 | fn completes_generic_params() { | ||
77 | check_reference_completion( | ||
78 | "generic_params", | ||
79 | r" | ||
80 | fn quux<T>() { | ||
81 | <|> | ||
82 | } | ||
83 | ", | ||
84 | ); | ||
85 | } | ||
86 | |||
87 | #[test] | ||
88 | fn completes_generic_params_in_struct() { | ||
89 | check_reference_completion( | ||
90 | "generic_params_in_struct", | ||
91 | r" | ||
92 | struct X<T> { | ||
93 | x: <|> | ||
94 | } | ||
95 | ", | ||
96 | ); | ||
97 | } | ||
98 | |||
99 | #[test] | ||
90 | fn completes_module_items() { | 100 | fn completes_module_items() { |
91 | check_reference_completion( | 101 | check_reference_completion( |
92 | "module_items", | 102 | "module_items", |
@@ -145,5 +155,4 @@ mod tests { | |||
145 | fn completes_self_in_methods() { | 155 | fn completes_self_in_methods() { |
146 | check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }") | 156 | check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }") |
147 | } | 157 | } |
148 | |||
149 | } | 158 | } |
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap new file mode 100644 index 000000000..71cb55a5b --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap | |||
@@ -0,0 +1,40 @@ | |||
1 | --- | ||
2 | created: "2019-02-01T22:20:40.580128393+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: kind_completions | ||
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "T", | ||
11 | kind: Some( | ||
12 | TypeParam | ||
13 | ), | ||
14 | detail: None, | ||
15 | documentation: None, | ||
16 | lookup: None, | ||
17 | insert_text: None, | ||
18 | insert_text_format: PlainText, | ||
19 | source_range: [44; 44), | ||
20 | text_edit: None | ||
21 | }, | ||
22 | CompletionItem { | ||
23 | completion_kind: Reference, | ||
24 | label: "quux", | ||
25 | kind: Some( | ||
26 | Function | ||
27 | ), | ||
28 | detail: Some( | ||
29 | "fn quux<T>()" | ||
30 | ), | ||
31 | documentation: None, | ||
32 | lookup: None, | ||
33 | insert_text: Some( | ||
34 | "quux()$0" | ||
35 | ), | ||
36 | insert_text_format: Snippet, | ||
37 | source_range: [44; 44), | ||
38 | text_edit: None | ||
39 | } | ||
40 | ] | ||
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap new file mode 100644 index 000000000..a35c0cd13 --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap | |||
@@ -0,0 +1,36 @@ | |||
1 | --- | ||
2 | created: "2019-02-01T22:23:21.508620224+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: kind_completions | ||
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "T", | ||
11 | kind: Some( | ||
12 | TypeParam | ||
13 | ), | ||
14 | detail: None, | ||
15 | documentation: None, | ||
16 | lookup: None, | ||
17 | insert_text: None, | ||
18 | insert_text_format: PlainText, | ||
19 | source_range: [46; 46), | ||
20 | text_edit: None | ||
21 | }, | ||
22 | CompletionItem { | ||
23 | completion_kind: Reference, | ||
24 | label: "X", | ||
25 | kind: Some( | ||
26 | Struct | ||
27 | ), | ||
28 | detail: None, | ||
29 | documentation: None, | ||
30 | lookup: None, | ||
31 | insert_text: None, | ||
32 | insert_text_format: PlainText, | ||
33 | source_range: [46; 46), | ||
34 | text_edit: None | ||
35 | } | ||
36 | ] | ||