aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
authorVille Penttinen <[email protected]>2019-03-07 08:32:39 +0000
committerVille Penttinen <[email protected]>2019-03-07 15:34:44 +0000
commit4a0bb3d7c53c2a914649087bf206d52ed5768576 (patch)
treef51670df82dfc0df68e6fda77d40878297af2ad6 /crates/ra_ide_api
parenta41d8e140ca65cb87bf6e69a35c3e86410aba374 (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.rs96
-rw-r--r--crates/ra_ide_api/src/hover.rs58
-rw-r--r--crates/ra_ide_api/src/navigation_target.rs13
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),