diff options
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r-- | crates/ra_ide_api/src/hover.rs | 82 |
1 files changed, 79 insertions, 3 deletions
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index ef3b5df29..47913d753 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use ra_db::SourceDatabase; | 1 | use ra_db::SourceDatabase; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | AstNode, SyntaxNode, TreeArc, ast::{self, NameOwner, VisibilityOwner}, | 3 | AstNode, SyntaxNode, TreeArc, ast::{self, NameOwner, VisibilityOwner, TypeAscriptionOwner}, |
4 | algo::{find_covering_node, find_node_at_offset, find_leaf_at_offset, visit::{visitor, Visitor}}, | 4 | algo::{find_covering_node, find_node_at_offset, find_leaf_at_offset, visit::{visitor, Visitor}}, |
5 | }; | 5 | }; |
6 | 6 | ||
@@ -179,6 +179,7 @@ impl NavigationTarget { | |||
179 | .visit(doc_comments::<ast::TypeAliasDef>) | 179 | .visit(doc_comments::<ast::TypeAliasDef>) |
180 | .visit(doc_comments::<ast::ConstDef>) | 180 | .visit(doc_comments::<ast::ConstDef>) |
181 | .visit(doc_comments::<ast::StaticDef>) | 181 | .visit(doc_comments::<ast::StaticDef>) |
182 | .visit(doc_comments::<ast::NamedFieldDef>) | ||
182 | .accept(&node)? | 183 | .accept(&node)? |
183 | } | 184 | } |
184 | 185 | ||
@@ -189,6 +190,20 @@ impl NavigationTarget { | |||
189 | // TODO: After type inference is done, add type information to improve the output | 190 | // TODO: After type inference is done, add type information to improve the output |
190 | let node = self.node(db)?; | 191 | let node = self.node(db)?; |
191 | 192 | ||
193 | fn visit_ascribed_node<T>(node: &T, prefix: &str) -> Option<String> | ||
194 | where | ||
195 | T: NameOwner + VisibilityOwner + TypeAscriptionOwner, | ||
196 | { | ||
197 | let mut string = visit_node(node, prefix)?; | ||
198 | |||
199 | if let Some(type_ref) = node.ascribed_type() { | ||
200 | string.push_str(": "); | ||
201 | type_ref.syntax().text().push_to(&mut string); | ||
202 | } | ||
203 | |||
204 | Some(string) | ||
205 | } | ||
206 | |||
192 | fn visit_node<T>(node: &T, label: &str) -> Option<String> | 207 | fn visit_node<T>(node: &T, label: &str) -> Option<String> |
193 | where | 208 | where |
194 | T: NameOwner + VisibilityOwner, | 209 | T: NameOwner + VisibilityOwner, |
@@ -207,8 +222,9 @@ impl NavigationTarget { | |||
207 | .visit(|node: &ast::TraitDef| visit_node(node, "trait ")) | 222 | .visit(|node: &ast::TraitDef| visit_node(node, "trait ")) |
208 | .visit(|node: &ast::Module| visit_node(node, "mod ")) | 223 | .visit(|node: &ast::Module| visit_node(node, "mod ")) |
209 | .visit(|node: &ast::TypeAliasDef| visit_node(node, "type ")) | 224 | .visit(|node: &ast::TypeAliasDef| visit_node(node, "type ")) |
210 | .visit(|node: &ast::ConstDef| visit_node(node, "const ")) | 225 | .visit(|node: &ast::ConstDef| visit_ascribed_node(node, "const ")) |
211 | .visit(|node: &ast::StaticDef| visit_node(node, "static ")) | 226 | .visit(|node: &ast::StaticDef| visit_ascribed_node(node, "static ")) |
227 | .visit(|node: &ast::NamedFieldDef| visit_ascribed_node(node, "")) | ||
212 | .accept(&node)? | 228 | .accept(&node)? |
213 | } | 229 | } |
214 | } | 230 | } |
@@ -321,6 +337,66 @@ mod tests { | |||
321 | } | 337 | } |
322 | 338 | ||
323 | #[test] | 339 | #[test] |
340 | fn hover_shows_struct_field_info() { | ||
341 | // Hovering over the field when instantiating | ||
342 | check_hover_result( | ||
343 | r#" | ||
344 | //- /main.rs | ||
345 | struct Foo { | ||
346 | field_a: u32, | ||
347 | } | ||
348 | |||
349 | fn main() { | ||
350 | let foo = Foo { | ||
351 | field_a<|>: 0, | ||
352 | }; | ||
353 | } | ||
354 | "#, | ||
355 | &["field_a: u32"], | ||
356 | ); | ||
357 | |||
358 | // Hovering over the field in the definition | ||
359 | check_hover_result( | ||
360 | r#" | ||
361 | //- /main.rs | ||
362 | struct Foo { | ||
363 | field_a<|>: u32, | ||
364 | } | ||
365 | |||
366 | fn main() { | ||
367 | let foo = Foo { | ||
368 | field_a: 0, | ||
369 | }; | ||
370 | } | ||
371 | "#, | ||
372 | &["field_a: u32"], | ||
373 | ); | ||
374 | } | ||
375 | |||
376 | #[test] | ||
377 | fn hover_const_static() { | ||
378 | check_hover_result( | ||
379 | r#" | ||
380 | //- /main.rs | ||
381 | fn main() { | ||
382 | const foo<|>: u32 = 0; | ||
383 | } | ||
384 | "#, | ||
385 | &["const foo: u32"], | ||
386 | ); | ||
387 | |||
388 | check_hover_result( | ||
389 | r#" | ||
390 | //- /main.rs | ||
391 | fn main() { | ||
392 | static foo<|>: u32 = 0; | ||
393 | } | ||
394 | "#, | ||
395 | &["static foo: u32"], | ||
396 | ); | ||
397 | } | ||
398 | |||
399 | #[test] | ||
324 | fn hover_some() { | 400 | fn hover_some() { |
325 | let (analysis, position) = single_file_with_position( | 401 | let (analysis, position) = single_file_with_position( |
326 | " | 402 | " |