diff options
author | Ville Penttinen <[email protected]> | 2019-03-07 08:32:39 +0000 |
---|---|---|
committer | Ville Penttinen <[email protected]> | 2019-03-07 15:34:44 +0000 |
commit | 4a0bb3d7c53c2a914649087bf206d52ed5768576 (patch) | |
tree | f51670df82dfc0df68e6fda77d40878297af2ad6 /crates/ra_ide_api | |
parent | a41d8e140ca65cb87bf6e69a35c3e86410aba374 (diff) |
Add support for goto definition and hover on Self
This fixes #943
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 96 | ||||
-rw-r--r-- | crates/ra_ide_api/src/hover.rs | 58 | ||||
-rw-r--r-- | crates/ra_ide_api/src/navigation_target.rs | 13 |
3 files changed, 165 insertions, 2 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index dd5f9f31c..d4e10b69c 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -121,8 +121,12 @@ pub(crate) fn reference_definition( | |||
121 | Some(Resolution::GenericParam(..)) => { | 121 | Some(Resolution::GenericParam(..)) => { |
122 | // TODO: go to the generic param def | 122 | // TODO: go to the generic param def |
123 | } | 123 | } |
124 | Some(Resolution::SelfType(_impl_block)) => { | 124 | Some(Resolution::SelfType(impl_block)) => { |
125 | // TODO: go to the implemented type | 125 | let ty = impl_block.target_ty(db); |
126 | |||
127 | if let hir::Ty::Adt { def_id, .. } = ty { | ||
128 | return Exact(NavigationTarget::from_adt_def(db, def_id)); | ||
129 | } | ||
126 | } | 130 | } |
127 | None => { | 131 | None => { |
128 | // If we failed to resolve then check associated items | 132 | // If we failed to resolve then check associated items |
@@ -337,6 +341,94 @@ mod tests { | |||
337 | "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)", | 341 | "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)", |
338 | ); | 342 | ); |
339 | } | 343 | } |
344 | #[test] | ||
345 | fn goto_definition_on_self() { | ||
346 | check_goto( | ||
347 | " | ||
348 | //- /lib.rs | ||
349 | struct Foo; | ||
350 | impl Foo { | ||
351 | pub fn new() -> Self { | ||
352 | Self<|> {} | ||
353 | } | ||
354 | } | ||
355 | ", | ||
356 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | ||
357 | ); | ||
358 | |||
359 | check_goto( | ||
360 | " | ||
361 | //- /lib.rs | ||
362 | struct Foo; | ||
363 | impl Foo { | ||
364 | pub fn new() -> Self<|> { | ||
365 | Self {} | ||
366 | } | ||
367 | } | ||
368 | ", | ||
369 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | ||
370 | ); | ||
371 | |||
372 | check_goto( | ||
373 | " | ||
374 | //- /lib.rs | ||
375 | enum Foo { A } | ||
376 | impl Foo { | ||
377 | pub fn new() -> Self<|> { | ||
378 | Foo::A | ||
379 | } | ||
380 | } | ||
381 | ", | ||
382 | "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)", | ||
383 | ); | ||
384 | |||
385 | check_goto( | ||
386 | " | ||
387 | //- /lib.rs | ||
388 | enum Foo { A } | ||
389 | impl Foo { | ||
390 | pub fn thing(a: &Self<|>) { | ||
391 | } | ||
392 | } | ||
393 | ", | ||
394 | "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)", | ||
395 | ); | ||
396 | } | ||
397 | |||
398 | #[test] | ||
399 | fn goto_definition_on_self_in_trait_impl() { | ||
400 | check_goto( | ||
401 | " | ||
402 | //- /lib.rs | ||
403 | struct Foo; | ||
404 | trait Make { | ||
405 | fn new() -> Self; | ||
406 | } | ||
407 | impl Make for Foo { | ||
408 | fn new() -> Self { | ||
409 | Self<|> {} | ||
410 | } | ||
411 | } | ||
412 | ", | ||
413 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | ||
414 | ); | ||
415 | |||
416 | check_goto( | ||
417 | " | ||
418 | //- /lib.rs | ||
419 | struct Foo; | ||
420 | trait Make { | ||
421 | fn new() -> Self; | ||
422 | } | ||
423 | impl Make for Foo { | ||
424 | fn new() -> Self<|> { | ||
425 | Self{} | ||
426 | } | ||
427 | } | ||
428 | ", | ||
429 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | ||
430 | ); | ||
431 | } | ||
340 | 432 | ||
341 | #[test] | 433 | #[test] |
342 | fn goto_definition_works_when_used_on_definition_name_itself() { | 434 | fn goto_definition_works_when_used_on_definition_name_itself() { |
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 638c24e31..f14001e84 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -557,4 +557,62 @@ mod tests { | |||
557 | assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32")); | 557 | assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32")); |
558 | assert_eq!(hover.info.is_exact(), true); | 558 | assert_eq!(hover.info.is_exact(), true); |
559 | } | 559 | } |
560 | |||
561 | #[test] | ||
562 | fn test_hover_self() { | ||
563 | let (analysis, position) = single_file_with_position( | ||
564 | " | ||
565 | struct Thing { x: u32 }; | ||
566 | impl Thing { | ||
567 | fn new() -> Self { | ||
568 | Self<|> { x: 0 } | ||
569 | } | ||
570 | } | ||
571 | ", | ||
572 | ); | ||
573 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
574 | assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing")); | ||
575 | assert_eq!(hover.info.is_exact(), true); | ||
576 | |||
577 | let (analysis, position) = single_file_with_position( | ||
578 | " | ||
579 | struct Thing { x: u32 }; | ||
580 | impl Thing { | ||
581 | fn new() -> Self<|> { | ||
582 | Self { x: 0 } | ||
583 | } | ||
584 | } | ||
585 | ", | ||
586 | ); | ||
587 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
588 | assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing")); | ||
589 | assert_eq!(hover.info.is_exact(), true); | ||
590 | |||
591 | let (analysis, position) = single_file_with_position( | ||
592 | " | ||
593 | enum Thing { A }; | ||
594 | impl Thing { | ||
595 | pub fn new() -> Self<|> { | ||
596 | Thing::A | ||
597 | } | ||
598 | } | ||
599 | ", | ||
600 | ); | ||
601 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
602 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); | ||
603 | assert_eq!(hover.info.is_exact(), true); | ||
604 | |||
605 | let (analysis, position) = single_file_with_position( | ||
606 | " | ||
607 | enum Thing { A }; | ||
608 | impl Thing { | ||
609 | pub fn thing(a: Self<|>) { | ||
610 | } | ||
611 | } | ||
612 | ", | ||
613 | ); | ||
614 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
615 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); | ||
616 | assert_eq!(hover.info.is_exact(), true); | ||
617 | } | ||
560 | } | 618 | } |
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index d806cb368..f6d7f3192 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs | |||
@@ -126,6 +126,19 @@ impl NavigationTarget { | |||
126 | } | 126 | } |
127 | } | 127 | } |
128 | 128 | ||
129 | pub(crate) fn from_adt_def(db: &RootDatabase, adt_def: hir::AdtDef) -> NavigationTarget { | ||
130 | match adt_def { | ||
131 | hir::AdtDef::Struct(s) => { | ||
132 | let (file_id, node) = s.source(db); | ||
133 | NavigationTarget::from_named(file_id.original_file(db), &*node) | ||
134 | } | ||
135 | hir::AdtDef::Enum(s) => { | ||
136 | let (file_id, node) = s.source(db); | ||
137 | NavigationTarget::from_named(file_id.original_file(db), &*node) | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
129 | pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget { | 142 | pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget { |
130 | match module_def { | 143 | match module_def { |
131 | hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module), | 144 | hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module), |