From 4a0bb3d7c53c2a914649087bf206d52ed5768576 Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Thu, 7 Mar 2019 10:32:39 +0200 Subject: Add support for goto definition and hover on Self This fixes #943 --- crates/ra_ide_api/src/goto_definition.rs | 96 +++++++++++++++++++++++++++++- crates/ra_ide_api/src/hover.rs | 58 ++++++++++++++++++ crates/ra_ide_api/src/navigation_target.rs | 13 ++++ 3 files changed, 165 insertions(+), 2 deletions(-) (limited to 'crates/ra_ide_api') 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( Some(Resolution::GenericParam(..)) => { // TODO: go to the generic param def } - Some(Resolution::SelfType(_impl_block)) => { - // TODO: go to the implemented type + Some(Resolution::SelfType(impl_block)) => { + let ty = impl_block.target_ty(db); + + if let hir::Ty::Adt { def_id, .. } = ty { + return Exact(NavigationTarget::from_adt_def(db, def_id)); + } } None => { // If we failed to resolve then check associated items @@ -337,6 +341,94 @@ mod tests { "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)", ); } + #[test] + fn goto_definition_on_self() { + check_goto( + " + //- /lib.rs + struct Foo; + impl Foo { + pub fn new() -> Self { + Self<|> {} + } + } + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + + check_goto( + " + //- /lib.rs + struct Foo; + impl Foo { + pub fn new() -> Self<|> { + Self {} + } + } + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + + check_goto( + " + //- /lib.rs + enum Foo { A } + impl Foo { + pub fn new() -> Self<|> { + Foo::A + } + } + ", + "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)", + ); + + check_goto( + " + //- /lib.rs + enum Foo { A } + impl Foo { + pub fn thing(a: &Self<|>) { + } + } + ", + "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)", + ); + } + + #[test] + fn goto_definition_on_self_in_trait_impl() { + check_goto( + " + //- /lib.rs + struct Foo; + trait Make { + fn new() -> Self; + } + impl Make for Foo { + fn new() -> Self { + Self<|> {} + } + } + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + + check_goto( + " + //- /lib.rs + struct Foo; + trait Make { + fn new() -> Self; + } + impl Make for Foo { + fn new() -> Self<|> { + Self{} + } + } + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + } #[test] 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 { assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32")); assert_eq!(hover.info.is_exact(), true); } + + #[test] + fn test_hover_self() { + let (analysis, position) = single_file_with_position( + " + struct Thing { x: u32 }; + impl Thing { + fn new() -> Self { + Self<|> { x: 0 } + } + } + ", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing")); + assert_eq!(hover.info.is_exact(), true); + + let (analysis, position) = single_file_with_position( + " + struct Thing { x: u32 }; + impl Thing { + fn new() -> Self<|> { + Self { x: 0 } + } + } + ", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing")); + assert_eq!(hover.info.is_exact(), true); + + let (analysis, position) = single_file_with_position( + " + enum Thing { A }; + impl Thing { + pub fn new() -> Self<|> { + Thing::A + } + } + ", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); + assert_eq!(hover.info.is_exact(), true); + + let (analysis, position) = single_file_with_position( + " + enum Thing { A }; + impl Thing { + pub fn thing(a: Self<|>) { + } + } + ", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); + assert_eq!(hover.info.is_exact(), true); + } } 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 { } } + pub(crate) fn from_adt_def(db: &RootDatabase, adt_def: hir::AdtDef) -> NavigationTarget { + match adt_def { + hir::AdtDef::Struct(s) => { + let (file_id, node) = s.source(db); + NavigationTarget::from_named(file_id.original_file(db), &*node) + } + hir::AdtDef::Enum(s) => { + let (file_id, node) = s.source(db); + NavigationTarget::from_named(file_id.original_file(db), &*node) + } + } + } + pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget { match module_def { hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module), -- cgit v1.2.3