aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/hover.rs3228
-rw-r--r--crates/ra_ide/src/lib.rs2
-rw-r--r--crates/ra_ide/src/markup.rs38
3 files changed, 1658 insertions, 1610 deletions
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 61359c770..a18c43003 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -10,12 +10,13 @@ use ra_ide_db::{
10 defs::{classify_name, classify_name_ref, Definition}, 10 defs::{classify_name, classify_name_ref, Definition},
11 RootDatabase, 11 RootDatabase,
12}; 12};
13use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; 13use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
14 14
15use crate::{ 15use crate::{
16 display::{ 16 display::{
17 macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav, TryToNav, 17 macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav, TryToNav,
18 }, 18 },
19 markup::Markup,
19 runnables::runnable, 20 runnables::runnable,
20 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, 21 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,
21}; 22};
@@ -68,8 +69,8 @@ pub struct HoverGotoTypeData {
68/// Contains the results when hovering over an item 69/// Contains the results when hovering over an item
69#[derive(Debug, Default)] 70#[derive(Debug, Default)]
70pub struct HoverResult { 71pub struct HoverResult {
71 results: Vec<String>, 72 pub markup: Markup,
72 actions: Vec<HoverAction>, 73 pub actions: Vec<HoverAction>,
73} 74}
74 75
75impl HoverResult { 76impl HoverResult {
@@ -78,22 +79,7 @@ impl HoverResult {
78 } 79 }
79 80
80 pub fn is_empty(&self) -> bool { 81 pub fn is_empty(&self) -> bool {
81 self.results.is_empty() 82 self.markup.is_empty()
82 }
83
84 pub fn len(&self) -> usize {
85 self.results.len()
86 }
87
88 pub fn actions(&self) -> &[HoverAction] {
89 &self.actions
90 }
91 /// Returns the results converted into markup
92 /// for displaying in a UI
93 ///
94 /// Does not process actions!
95 pub fn to_markup(&self) -> String {
96 self.results.join("\n\n___\n")
97 } 83 }
98 84
99 fn push_action(&mut self, action: HoverAction) { 85 fn push_action(&mut self, action: HoverAction) {
@@ -128,7 +114,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
128 if let Some(definition) = definition { 114 if let Some(definition) = definition {
129 let range = sema.original_range(&node).range; 115 let range = sema.original_range(&node).range;
130 if let Some(text) = hover_text_from_name_kind(db, definition) { 116 if let Some(text) = hover_text_from_name_kind(db, definition) {
131 res.results.push(text); 117 res.markup.push_section(&text);
132 } 118 }
133 if !res.is_empty() { 119 if !res.is_empty() {
134 if let Some(action) = show_implementations_action(db, definition) { 120 if let Some(action) = show_implementations_action(db, definition) {
@@ -168,7 +154,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
168 } 154 }
169 }?; 155 }?;
170 156
171 res.results.push(rust_code_markup(&ty.display(db))); 157 res.markup.push_section(&rust_code_markup(&ty.display(db)));
172 let range = sema.original_range(&node).range; 158 let range = sema.original_range(&node).range;
173 Some(RangeInfo::new(range, res)) 159 Some(RangeInfo::new(range, res))
174} 160}
@@ -374,7 +360,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
374 fn priority(n: &SyntaxToken) -> usize { 360 fn priority(n: &SyntaxToken) -> usize {
375 match n.kind() { 361 match n.kind() {
376 IDENT | INT_NUMBER => 3, 362 IDENT | INT_NUMBER => 3,
377 L_PAREN | R_PAREN => 2, 363 T!['('] | T![')'] => 2,
378 kind if kind.is_trivia() => 0, 364 kind if kind.is_trivia() => 0,
379 _ => 1, 365 _ => 1,
380 } 366 }
@@ -383,52 +369,38 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
383 369
384#[cfg(test)] 370#[cfg(test)]
385mod tests { 371mod tests {
386 use super::*; 372 use expect::{expect, Expect};
387 use insta::assert_debug_snapshot;
388
389 use ra_db::FileLoader; 373 use ra_db::FileLoader;
390 use ra_syntax::TextRange;
391 374
392 use crate::mock_analysis::analysis_and_position; 375 use crate::mock_analysis::analysis_and_position;
393 376
394 fn trim_markup(s: &str) -> &str { 377 use super::*;
395 s.trim_start_matches("```rust\n").trim_end_matches("\n```")
396 }
397 378
398 fn assert_impl_action(action: &HoverAction, position: u32) { 379 fn check_hover_no_result(ra_fixture: &str) {
399 let offset = match action { 380 let (analysis, position) = analysis_and_position(ra_fixture);
400 HoverAction::Implementaion(pos) => pos.offset, 381 assert!(analysis.hover(position).unwrap().is_none());
401 it => panic!("Unexpected hover action: {:#?}", it),
402 };
403 assert_eq!(offset, position.into());
404 } 382 }
405 383
406 fn check_hover_result(ra_fixture: &str, expected: &[&str]) -> (String, Vec<HoverAction>) { 384 fn check(ra_fixture: &str, expect: Expect) {
407 let (analysis, position) = analysis_and_position(ra_fixture); 385 let (analysis, position) = analysis_and_position(ra_fixture);
408 let hover = analysis.hover(position).unwrap().unwrap(); 386 let hover = analysis.hover(position).unwrap().unwrap();
409 let mut results = hover.info.results.clone();
410 results.sort();
411
412 for (markup, expected) in
413 results.iter().zip(expected.iter().chain(std::iter::repeat(&"<missing>")))
414 {
415 assert_eq!(trim_markup(&markup), *expected);
416 }
417
418 assert_eq!(hover.info.len(), expected.len());
419 387
420 let content = analysis.db.file_text(position.file_id); 388 let content = analysis.db.file_text(position.file_id);
421 (content[hover.range].to_string(), hover.info.actions().to_vec()) 389 let hovered_element = &content[hover.range];
390
391 let actual = format!("{}:\n{}\n", hovered_element, hover.info.markup);
392 expect.assert_eq(&actual)
422 } 393 }
423 394
424 fn check_hover_no_result(ra_fixture: &str) { 395 fn check_actions(ra_fixture: &str, expect: Expect) {
425 let (analysis, position) = analysis_and_position(ra_fixture); 396 let (analysis, position) = analysis_and_position(ra_fixture);
426 assert!(analysis.hover(position).unwrap().is_none()); 397 let hover = analysis.hover(position).unwrap().unwrap();
398 expect.assert_debug_eq(&hover.info.actions)
427 } 399 }
428 400
429 #[test] 401 #[test]
430 fn hover_shows_type_of_an_expression() { 402 fn hover_shows_type_of_an_expression() {
431 let (analysis, position) = analysis_and_position( 403 check(
432 r#" 404 r#"
433pub fn foo() -> u32 { 1 } 405pub fn foo() -> u32 { 1 }
434 406
@@ -436,603 +408,643 @@ fn main() {
436 let foo_test = foo()<|>; 408 let foo_test = foo()<|>;
437} 409}
438"#, 410"#,
411 expect![[r#"
412 foo():
413 ```rust
414 u32
415 ```
416 "#]],
439 ); 417 );
440 let hover = analysis.hover(position).unwrap().unwrap();
441 assert_eq!(hover.range, TextRange::new(58.into(), 63.into()));
442 assert_eq!(trim_markup(&hover.info.results[0]), ("u32"));
443 } 418 }
444 419
445 #[test] 420 #[test]
446 fn hover_shows_long_type_of_an_expression() { 421 fn hover_shows_long_type_of_an_expression() {
447 check_hover_result( 422 check(
448 r#" 423 r#"
449 //- /main.rs 424struct Scan<A, B, C> { a: A, b: B, c: C }
450 struct Scan<A, B, C> { 425struct Iter<I> { inner: I }
451 a: A, 426enum Option<T> { Some(T), None }
452 b: B,
453 c: C,
454 }
455 427
456 struct FakeIter<I> { 428struct OtherStruct<T> { i: T }
457 inner: I,
458 }
459
460 struct OtherStruct<T> {
461 i: T,
462 }
463 429
464 enum FakeOption<T> { 430fn scan<A, B, C>(a: A, b: B, c: C) -> Iter<Scan<OtherStruct<A>, B, C>> {
465 Some(T), 431 Iter { inner: Scan { a, b, c } }
466 None, 432}
467 }
468
469 fn scan<A, B, C>(a: A, b: B, c: C) -> FakeIter<Scan<OtherStruct<A>, B, C>> {
470 FakeIter { inner: Scan { a, b, c } }
471 }
472 433
473 fn main() { 434fn main() {
474 let num: i32 = 55; 435 let num: i32 = 55;
475 let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> FakeOption<u32> { 436 let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> Option<u32> {
476 FakeOption::Some(*memo + value) 437 Option::Some(*memo + value)
477 }; 438 };
478 let number = 5u32; 439 let number = 5u32;
479 let mut iter<|> = scan(OtherStruct { i: num }, closure, number); 440 let mut iter<|> = scan(OtherStruct { i: num }, closure, number);
480 } 441}
481 "#, 442"#,
482 &["FakeIter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> FakeOption<u32>, u32>>"], 443 expect![[r#"
444 iter:
445 ```rust
446 Iter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> Option<u32>, u32>>
447 ```
448 "#]],
483 ); 449 );
484 } 450 }
485 451
486 #[test] 452 #[test]
487 fn hover_shows_fn_signature() { 453 fn hover_shows_fn_signature() {
488 // Single file with result 454 // Single file with result
489 check_hover_result( 455 check(
490 r#" 456 r#"
491 //- /main.rs 457pub fn foo() -> u32 { 1 }
492 pub fn foo() -> u32 { 1 }
493 458
494 fn main() { 459fn main() { let foo_test = fo<|>o(); }
495 let foo_test = fo<|>o(); 460"#,
496 } 461 expect![[r#"
497 "#, 462 foo:
498 &["pub fn foo() -> u32"], 463 ```rust
464 pub fn foo() -> u32
465 ```
466 "#]],
499 ); 467 );
500 468
501 // Multiple candidates but results are ambiguous. 469 // Multiple candidates but results are ambiguous.
502 check_hover_result( 470 check(
503 r#" 471 r#"
504 //- /a.rs 472//- /a.rs
505 pub fn foo() -> u32 { 1 } 473pub fn foo() -> u32 { 1 }
506 474
507 //- /b.rs 475//- /b.rs
508 pub fn foo() -> &str { "" } 476pub fn foo() -> &str { "" }
509 477
510 //- /c.rs 478//- /c.rs
511 pub fn foo(a: u32, b: u32) {} 479pub fn foo(a: u32, b: u32) {}
512 480
513 //- /main.rs 481//- /main.rs
514 mod a; 482mod a;
515 mod b; 483mod b;
516 mod c; 484mod c;
517 485
518 fn main() { 486fn main() { let foo_test = fo<|>o(); }
519 let foo_test = fo<|>o();
520 }
521 "#, 487 "#,
522 &["{unknown}"], 488 expect![[r#"
489 foo:
490 ```rust
491 {unknown}
492 ```
493 "#]],
523 ); 494 );
524 } 495 }
525 496
526 #[test] 497 #[test]
527 fn hover_shows_fn_signature_with_type_params() { 498 fn hover_shows_fn_signature_with_type_params() {
528 check_hover_result( 499 check(
529 r#" 500 r#"
530 //- /main.rs 501pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
531 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
532 502
533 fn main() { 503fn main() { let foo_test = fo<|>o(); }
534 let foo_test = fo<|>o();
535 }
536 "#, 504 "#,
537 &["pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str"], 505 expect![[r#"
506 foo:
507 ```rust
508 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str
509 ```
510 "#]],
538 ); 511 );
539 } 512 }
540 513
541 #[test] 514 #[test]
542 fn hover_shows_fn_signature_on_fn_name() { 515 fn hover_shows_fn_signature_on_fn_name() {
543 check_hover_result( 516 check(
544 r#" 517 r#"
545 //- /main.rs 518pub fn foo<|>(a: u32, b: u32) -> u32 {}
546 pub fn foo<|>(a: u32, b: u32) -> u32 {}
547 519
548 fn main() { 520fn main() { }
549 } 521"#,
550 "#, 522 expect![[r#"
551 &["pub fn foo(a: u32, b: u32) -> u32"], 523 foo:
524 ```rust
525 pub fn foo(a: u32, b: u32) -> u32
526 ```
527 "#]],
552 ); 528 );
553 } 529 }
554 530
555 #[test] 531 #[test]
556 fn hover_shows_struct_field_info() { 532 fn hover_shows_struct_field_info() {
557 // Hovering over the field when instantiating 533 // Hovering over the field when instantiating
558 check_hover_result( 534 check(
559 r#" 535 r#"
560 //- /main.rs 536struct Foo { field_a: u32 }
561 struct Foo {
562 field_a: u32,
563 }
564 537
565 fn main() { 538fn main() {
566 let foo = Foo { 539 let foo = Foo { field_a<|>: 0, };
567 field_a<|>: 0, 540}
568 }; 541"#,
569 } 542 expect![[r#"
570 "#, 543 field_a:
571 &["Foo\n```\n\n```rust\nfield_a: u32"], 544 ```rust
545 Foo
546 ```
547
548 ```rust
549 field_a: u32
550 ```
551 "#]],
572 ); 552 );
573 553
574 // Hovering over the field in the definition 554 // Hovering over the field in the definition
575 check_hover_result( 555 check(
576 r#" 556 r#"
577 //- /main.rs 557struct Foo { field_a<|>: u32 }
578 struct Foo {
579 field_a<|>: u32,
580 }
581 558
582 fn main() { 559fn main() {
583 let foo = Foo { 560 let foo = Foo { field_a: 0 };
584 field_a: 0, 561}
585 }; 562"#,
586 } 563 expect![[r#"
587 "#, 564 field_a:
588 &["Foo\n```\n\n```rust\nfield_a: u32"], 565 ```rust
566 Foo
567 ```
568
569 ```rust
570 field_a: u32
571 ```
572 "#]],
589 ); 573 );
590 } 574 }
591 575
592 #[test] 576 #[test]
593 fn hover_const_static() { 577 fn hover_const_static() {
594 check_hover_result( 578 check(
595 r#" 579 r#"const foo<|>: u32 = 0;"#,
596 //- /main.rs 580 expect![[r#"
597 const foo<|>: u32 = 0; 581 foo:
598 "#, 582 ```rust
599 &["const foo: u32"], 583 const foo: u32
600 ); 584 ```
601 585 "#]],
602 check_hover_result( 586 );
603 r#" 587 check(
604 //- /main.rs 588 r#"static foo<|>: u32 = 0;"#,
605 static foo<|>: u32 = 0; 589 expect![[r#"
606 "#, 590 foo:
607 &["static foo: u32"], 591 ```rust
592 static foo: u32
593 ```
594 "#]],
608 ); 595 );
609 } 596 }
610 597
611 #[test] 598 #[test]
612 fn hover_default_generic_types() { 599 fn hover_default_generic_types() {
613 check_hover_result( 600 check(
614 r#" 601 r#"
615//- /main.rs 602struct Test<K, T = u8> { k: K, t: T }
616struct Test<K, T = u8> {
617 k: K,
618 t: T,
619}
620 603
621fn main() { 604fn main() {
622 let zz<|> = Test { t: 23u8, k: 33 }; 605 let zz<|> = Test { t: 23u8, k: 33 };
623}"#, 606}"#,
624 &["Test<i32, u8>"], 607 expect![[r#"
608 zz:
609 ```rust
610 Test<i32, u8>
611 ```
612 "#]],
625 ); 613 );
626 } 614 }
627 615
628 #[test] 616 #[test]
629 fn hover_some() { 617 fn hover_some() {
630 let (analysis, position) = analysis_and_position( 618 check(
631 " 619 r#"
632 enum Option<T> { Some(T) } 620enum Option<T> { Some(T) }
633 use Option::Some; 621use Option::Some;
634 622
635 fn main() { 623fn main() { So<|>me(12); }
636 So<|>me(12); 624"#,
637 } 625 expect![[r#"
638 ", 626 Some:
627 ```rust
628 Option
629 ```
630
631 ```rust
632 Some
633 ```
634 "#]],
639 ); 635 );
640 let hover = analysis.hover(position).unwrap().unwrap();
641 assert_eq!(trim_markup(&hover.info.results[0]), ("Option\n```\n\n```rust\nSome"));
642 636
643 let (analysis, position) = analysis_and_position( 637 check(
644 " 638 r#"
645 enum Option<T> { Some(T) } 639enum Option<T> { Some(T) }
646 use Option::Some; 640use Option::Some;
647 641
648 fn main() { 642fn main() { let b<|>ar = Some(12); }
649 let b<|>ar = Some(12); 643"#,
650 } 644 expect![[r#"
651 ", 645 bar:
646 ```rust
647 Option<i32>
648 ```
649 "#]],
652 ); 650 );
653 let hover = analysis.hover(position).unwrap().unwrap();
654 assert_eq!(trim_markup(&hover.info.results[0]), ("Option<i32>"));
655 } 651 }
656 652
657 #[test] 653 #[test]
658 fn hover_enum_variant() { 654 fn hover_enum_variant() {
659 check_hover_result( 655 check(
660 r#" 656 r#"
661 //- /main.rs 657enum Option<T> {
662 enum Option<T> { 658 /// The None variant
663 /// The None variant 659 Non<|>e
664 Non<|>e 660}
665 } 661"#,
666 "#, 662 expect![[r#"
667 &[" 663 None:
668Option 664 ```rust
669``` 665 Option
666 ```
670 667
671```rust 668 ```rust
672None 669 None
673``` 670 ```
674___ 671 ___
675 672
676The None variant 673 The None variant
677 " 674 "#]],
678 .trim()],
679 ); 675 );
680 676
681 check_hover_result( 677 check(
682 r#" 678 r#"
683 //- /main.rs 679enum Option<T> {
684 enum Option<T> { 680 /// The Some variant
685 /// The Some variant 681 Some(T)
686 Some(T) 682}
687 } 683fn main() {
688 fn main() { 684 let s = Option::Som<|>e(12);
689 let s = Option::Som<|>e(12); 685}
690 } 686"#,
691 "#, 687 expect![[r#"
692 &[" 688 Some:
693Option 689 ```rust
694``` 690 Option
691 ```
695 692
696```rust 693 ```rust
697Some 694 Some
698``` 695 ```
699___ 696 ___
700 697
701The Some variant 698 The Some variant
702 " 699 "#]],
703 .trim()],
704 ); 700 );
705 } 701 }
706 702
707 #[test] 703 #[test]
708 fn hover_for_local_variable() { 704 fn hover_for_local_variable() {
709 let (analysis, position) = analysis_and_position("fn func(foo: i32) { fo<|>o; }"); 705 check(
710 let hover = analysis.hover(position).unwrap().unwrap(); 706 r#"fn func(foo: i32) { fo<|>o; }"#,
711 assert_eq!(trim_markup(&hover.info.results[0]), "i32"); 707 expect![[r#"
708 foo:
709 ```rust
710 i32
711 ```
712 "#]],
713 )
712 } 714 }
713 715
714 #[test] 716 #[test]
715 fn hover_for_local_variable_pat() { 717 fn hover_for_local_variable_pat() {
716 let (analysis, position) = analysis_and_position("fn func(fo<|>o: i32) {}"); 718 check(
717 let hover = analysis.hover(position).unwrap().unwrap(); 719 r#"fn func(fo<|>o: i32) {}"#,
718 assert_eq!(trim_markup(&hover.info.results[0]), "i32"); 720 expect![[r#"
721 foo:
722 ```rust
723 i32
724 ```
725 "#]],
726 )
719 } 727 }
720 728
721 #[test] 729 #[test]
722 fn hover_local_var_edge() { 730 fn hover_local_var_edge() {
723 let (analysis, position) = analysis_and_position( 731 check(
724 " 732 r#"fn func(foo: i32) { if true { <|>foo; }; }"#,
725fn func(foo: i32) { if true { <|>foo; }; } 733 expect![[r#"
726", 734 foo:
727 ); 735 ```rust
728 let hover = analysis.hover(position).unwrap().unwrap(); 736 i32
729 assert_eq!(trim_markup(&hover.info.results[0]), "i32"); 737 ```
738 "#]],
739 )
730 } 740 }
731 741
732 #[test] 742 #[test]
733 fn hover_for_param_edge() { 743 fn hover_for_param_edge() {
734 let (analysis, position) = analysis_and_position("fn func(<|>foo: i32) {}"); 744 check(
735 let hover = analysis.hover(position).unwrap().unwrap(); 745 r#"fn func(<|>foo: i32) {}"#,
736 assert_eq!(trim_markup(&hover.info.results[0]), "i32"); 746 expect![[r#"
747 foo:
748 ```rust
749 i32
750 ```
751 "#]],
752 )
737 } 753 }
738 754
739 #[test] 755 #[test]
740 fn test_hover_infer_associated_method_result() { 756 fn test_hover_infer_associated_method_result() {
741 let (analysis, position) = analysis_and_position( 757 check(
742 " 758 r#"
743 struct Thing { x: u32 } 759struct Thing { x: u32 }
744 760
745 impl Thing { 761impl Thing {
746 fn new() -> Thing { 762 fn new() -> Thing { Thing { x: 0 } }
747 Thing { x: 0 } 763}
748 }
749 }
750 764
751 fn main() { 765fn main() { let foo_<|>test = Thing::new(); }
752 let foo_<|>test = Thing::new(); 766 "#,
753 } 767 expect![[r#"
754 ", 768 foo_test:
755 ); 769 ```rust
756 let hover = analysis.hover(position).unwrap().unwrap(); 770 Thing
757 assert_eq!(trim_markup(&hover.info.results[0]), ("Thing")); 771 ```
772 "#]],
773 )
758 } 774 }
759 775
760 #[test] 776 #[test]
761 fn test_hover_infer_associated_method_exact() { 777 fn test_hover_infer_associated_method_exact() {
762 let (analysis, position) = analysis_and_position( 778 check(
763 " 779 r#"
764 mod wrapper { 780mod wrapper {
765 struct Thing { x: u32 } 781 struct Thing { x: u32 }
766 782
767 impl Thing { 783 impl Thing {
768 fn new() -> Thing { 784 fn new() -> Thing { Thing { x: 0 } }
769 Thing { x: 0 } 785 }
770 } 786}
771 }
772 }
773 787
774 fn main() { 788fn main() { let foo_test = wrapper::Thing::new<|>(); }
775 let foo_test = wrapper::Thing::new<|>(); 789"#,
776 } 790 expect![[r#"
777 ", 791 new:
778 ); 792 ```rust
779 let hover = analysis.hover(position).unwrap().unwrap(); 793 wrapper::Thing
780 assert_eq!( 794 ```
781 trim_markup(&hover.info.results[0]), 795
782 ("wrapper::Thing\n```\n\n```rust\nfn new() -> Thing") 796 ```rust
783 ); 797 fn new() -> Thing
798 ```
799 "#]],
800 )
784 } 801 }
785 802
786 #[test] 803 #[test]
787 fn test_hover_infer_associated_const_in_pattern() { 804 fn test_hover_infer_associated_const_in_pattern() {
788 let (analysis, position) = analysis_and_position( 805 check(
789 " 806 r#"
790 struct X; 807struct X;
791 impl X { 808impl X {
792 const C: u32 = 1; 809 const C: u32 = 1;
793 } 810}
794 811
795 fn main() { 812fn main() {
796 match 1 { 813 match 1 {
797 X::C<|> => {}, 814 X::C<|> => {},
798 2 => {}, 815 2 => {},
799 _ => {} 816 _ => {}
800 }; 817 };
801 } 818}
802 ", 819"#,
803 ); 820 expect![[r#"
804 let hover = analysis.hover(position).unwrap().unwrap(); 821 C:
805 assert_eq!(trim_markup(&hover.info.results[0]), ("const C: u32")); 822 ```rust
823 const C: u32
824 ```
825 "#]],
826 )
806 } 827 }
807 828
808 #[test] 829 #[test]
809 fn test_hover_self() { 830 fn test_hover_self() {
810 let (analysis, position) = analysis_and_position( 831 check(
811 " 832 r#"
812 struct Thing { x: u32 } 833struct Thing { x: u32 }
813 impl Thing { 834impl Thing {
814 fn new() -> Self { 835 fn new() -> Self { Self<|> { x: 0 } }
815 Self<|> { x: 0 } 836}
816 } 837"#,
817 } 838 expect![[r#"
818 ", 839 Self { x: 0 }:
819 ); 840 ```rust
820 let hover = analysis.hover(position).unwrap().unwrap(); 841 Thing
821 assert_eq!(trim_markup(&hover.info.results[0]), ("Thing")); 842 ```
822 843 "#]],
823 /* FIXME: revive these tests 844 )
824 let (analysis, position) = analysis_and_position( 845 } /* FIXME: revive these tests
825 " 846 let (analysis, position) = analysis_and_position(
826 struct Thing { x: u32 } 847 "
827 impl Thing { 848 struct Thing { x: u32 }
828 fn new() -> Self<|> { 849 impl Thing {
829 Self { x: 0 } 850 fn new() -> Self<|> {
830 } 851 Self { x: 0 }
831 } 852 }
832 ", 853 }
833 ); 854 ",
834 855 );
835 let hover = analysis.hover(position).unwrap().unwrap(); 856
836 assert_eq!(trim_markup(&hover.info.results[0]), ("Thing")); 857 let hover = analysis.hover(position).unwrap().unwrap();
837 858 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing"));
838 let (analysis, position) = analysis_and_position( 859
839 " 860 let (analysis, position) = analysis_and_position(
840 enum Thing { A } 861 "
841 impl Thing { 862 enum Thing { A }
842 pub fn new() -> Self<|> { 863 impl Thing {
843 Thing::A 864 pub fn new() -> Self<|> {
844 } 865 Thing::A
845 } 866 }
846 ", 867 }
847 ); 868 ",
848 let hover = analysis.hover(position).unwrap().unwrap(); 869 );
849 assert_eq!(trim_markup(&hover.info.results[0]), ("enum Thing")); 870 let hover = analysis.hover(position).unwrap().unwrap();
850 871 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing"));
851 let (analysis, position) = analysis_and_position( 872
852 " 873 let (analysis, position) = analysis_and_position(
853 enum Thing { A } 874 "
854 impl Thing { 875 enum Thing { A }
855 pub fn thing(a: Self<|>) { 876 impl Thing {
856 } 877 pub fn thing(a: Self<|>) {
857 } 878 }
858 ", 879 }
859 ); 880 ",
860 let hover = analysis.hover(position).unwrap().unwrap(); 881 );
861 assert_eq!(trim_markup(&hover.info.results[0]), ("enum Thing")); 882 let hover = analysis.hover(position).unwrap().unwrap();
862 */ 883 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing"));
863 } 884 */
864 885
865 #[test] 886 #[test]
866 fn test_hover_shadowing_pat() { 887 fn test_hover_shadowing_pat() {
867 let (analysis, position) = analysis_and_position( 888 check(
868 " 889 r#"
869 fn x() {} 890fn x() {}
870 891
871 fn y() { 892fn y() {
872 let x = 0i32; 893 let x = 0i32;
873 x<|>; 894 x<|>;
874 } 895}
875 ", 896"#,
876 ); 897 expect![[r#"
877 let hover = analysis.hover(position).unwrap().unwrap(); 898 x:
878 assert_eq!(trim_markup(&hover.info.results[0]), "i32"); 899 ```rust
900 i32
901 ```
902 "#]],
903 )
879 } 904 }
880 905
881 #[test] 906 #[test]
882 fn test_hover_macro_invocation() { 907 fn test_hover_macro_invocation() {
883 let (analysis, position) = analysis_and_position( 908 check(
884 " 909 r#"
885 macro_rules! foo { 910macro_rules! foo { () => {} }
886 () => {}
887 }
888 911
889 fn f() { 912fn f() { fo<|>o!(); }
890 fo<|>o!(); 913"#,
891 } 914 expect![[r#"
892 ", 915 foo:
893 ); 916 ```rust
894 let hover = analysis.hover(position).unwrap().unwrap(); 917 macro_rules! foo
895 assert_eq!(trim_markup(&hover.info.results[0]), ("macro_rules! foo")); 918 ```
919 "#]],
920 )
896 } 921 }
897 922
898 #[test] 923 #[test]
899 fn test_hover_tuple_field() { 924 fn test_hover_tuple_field() {
900 let (analysis, position) = analysis_and_position( 925 check(
901 " 926 r#"struct TS(String, i32<|>);"#,
902 struct TS(String, i32<|>); 927 expect![[r#"
903 ", 928 i32:
904 ); 929 i32
905 let hover = analysis.hover(position).unwrap().unwrap(); 930 "#]],
906 assert_eq!(trim_markup(&hover.info.results[0]), "i32"); 931 )
907 } 932 }
908 933
909 #[test] 934 #[test]
910 fn test_hover_through_macro() { 935 fn test_hover_through_macro() {
911 let (hover_on, _) = check_hover_result( 936 check(
912 r" 937 r#"
913 //- /lib.rs 938macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
914 macro_rules! id { 939fn foo() {}
915 ($($tt:tt)*) => { $($tt)* } 940id! {
916 } 941 fn bar() { fo<|>o(); }
917 fn foo() {} 942}
918 id! { 943"#,
919 fn bar() { 944 expect![[r#"
920 fo<|>o(); 945 foo:
921 } 946 ```rust
922 } 947 fn foo()
923 ", 948 ```
924 &["fn foo()"], 949 "#]],
925 ); 950 );
926
927 assert_eq!(hover_on, "foo")
928 } 951 }
929 952
930 #[test] 953 #[test]
931 fn test_hover_through_expr_in_macro() { 954 fn test_hover_through_expr_in_macro() {
932 let (hover_on, _) = check_hover_result( 955 check(
933 r" 956 r#"
934 //- /lib.rs 957macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
935 macro_rules! id { 958fn foo(bar:u32) { let a = id!(ba<|>r); }
936 ($($tt:tt)*) => { $($tt)* } 959"#,
937 } 960 expect![[r#"
938 fn foo(bar:u32) { 961 bar:
939 let a = id!(ba<|>r); 962 ```rust
940 } 963 u32
941 ", 964 ```
942 &["u32"], 965 "#]],
943 ); 966 );
944
945 assert_eq!(hover_on, "bar")
946 } 967 }
947 968
948 #[test] 969 #[test]
949 fn test_hover_through_expr_in_macro_recursive() { 970 fn test_hover_through_expr_in_macro_recursive() {
950 let (hover_on, _) = check_hover_result( 971 check(
951 r" 972 r#"
952 //- /lib.rs 973macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
953 macro_rules! id_deep { 974macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
954 ($($tt:tt)*) => { $($tt)* } 975fn foo(bar:u32) { let a = id!(ba<|>r); }
955 } 976"#,
956 macro_rules! id { 977 expect![[r#"
957 ($($tt:tt)*) => { id_deep!($($tt)*) } 978 bar:
958 } 979 ```rust
959 fn foo(bar:u32) { 980 u32
960 let a = id!(ba<|>r); 981 ```
961 } 982 "#]],
962 ",
963 &["u32"],
964 ); 983 );
965
966 assert_eq!(hover_on, "bar")
967 } 984 }
968 985
969 #[test] 986 #[test]
970 fn test_hover_through_func_in_macro_recursive() { 987 fn test_hover_through_func_in_macro_recursive() {
971 let (hover_on, _) = check_hover_result( 988 check(
972 r" 989 r#"
973 //- /lib.rs 990macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
974 macro_rules! id_deep { 991macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
975 ($($tt:tt)*) => { $($tt)* } 992fn bar() -> u32 { 0 }
976 } 993fn foo() { let a = id!([0u32, bar(<|>)] ); }
977 macro_rules! id { 994"#,
978 ($($tt:tt)*) => { id_deep!($($tt)*) } 995 expect![[r#"
979 } 996 bar():
980 fn bar() -> u32 { 997 ```rust
981 0 998 u32
982 } 999 ```
983 fn foo() { 1000 "#]],
984 let a = id!([0u32, bar(<|>)] );
985 }
986 ",
987 &["u32"],
988 ); 1001 );
989
990 assert_eq!(hover_on, "bar()")
991 } 1002 }
992 1003
993 #[test] 1004 #[test]
994 fn test_hover_through_literal_string_in_macro() { 1005 fn test_hover_through_literal_string_in_macro() {
995 let (hover_on, _) = check_hover_result( 1006 check(
996 r#" 1007 r#"
997 //- /lib.rs 1008macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } }
998 macro_rules! arr { 1009fn foo() {
999 ($($tt:tt)*) => { [$($tt)*)] } 1010 let mastered_for_itunes = "";
1000 } 1011 let _ = arr!("Tr<|>acks", &mastered_for_itunes);
1001 fn foo() { 1012}
1002 let mastered_for_itunes = ""; 1013"#,
1003 let _ = arr!("Tr<|>acks", &mastered_for_itunes); 1014 expect![[r#"
1004 } 1015 "Tracks":
1005 "#, 1016 ```rust
1006 &["&str"], 1017 &str
1018 ```
1019 "#]],
1007 ); 1020 );
1008
1009 assert_eq!(hover_on, "\"Tracks\"");
1010 } 1021 }
1011 1022
1012 #[test] 1023 #[test]
1013 fn test_hover_through_assert_macro() { 1024 fn test_hover_through_assert_macro() {
1014 let (hover_on, _) = check_hover_result( 1025 check(
1015 r" 1026 r#"
1016 //- /lib.rs 1027#[rustc_builtin_macro]
1017 #[rustc_builtin_macro] 1028macro_rules! assert {}
1018 macro_rules! assert {}
1019 1029
1020 fn bar() -> bool { true } 1030fn bar() -> bool { true }
1021 fn foo() { 1031fn foo() {
1022 assert!(ba<|>r()); 1032 assert!(ba<|>r());
1023 } 1033}
1024 ", 1034"#,
1025 &["fn bar() -> bool"], 1035 expect![[r#"
1036 bar:
1037 ```rust
1038 fn bar() -> bool
1039 ```
1040 "#]],
1026 ); 1041 );
1027
1028 assert_eq!(hover_on, "bar");
1029 } 1042 }
1030 1043
1031 #[test] 1044 #[test]
1032 fn test_hover_through_literal_string_in_builtin_macro() { 1045 fn test_hover_through_literal_string_in_builtin_macro() {
1033 check_hover_no_result( 1046 check_hover_no_result(
1034 r#" 1047 r#"
1035 //- /lib.rs
1036 #[rustc_builtin_macro] 1048 #[rustc_builtin_macro]
1037 macro_rules! format {} 1049 macro_rules! format {}
1038 1050
@@ -1045,122 +1057,159 @@ fn func(foo: i32) { if true { <|>foo; }; }
1045 1057
1046 #[test] 1058 #[test]
1047 fn test_hover_non_ascii_space_doc() { 1059 fn test_hover_non_ascii_space_doc() {
1048 check_hover_result( 1060 check(
1049 " 1061 "
1050 //- /lib.rs 1062/// <- `\u{3000}` here
1051 /// <- `\u{3000}` here 1063fn foo() { }
1052 fn foo() {
1053 }
1054 1064
1055 fn bar() { 1065fn bar() { fo<|>o(); }
1056 fo<|>o(); 1066",
1057 } 1067 expect![[r#"
1058 ", 1068 foo:
1059 &["fn foo()\n```\n___\n\n<- `\u{3000}` here"], 1069 ```rust
1070 fn foo()
1071 ```
1072 ___
1073
1074 <- ` ` here
1075 "#]],
1060 ); 1076 );
1061 } 1077 }
1062 1078
1063 #[test] 1079 #[test]
1064 fn test_hover_function_show_qualifiers() { 1080 fn test_hover_function_show_qualifiers() {
1065 check_hover_result( 1081 check(
1066 r" 1082 r#"async fn foo<|>() {}"#,
1067 //- /lib.rs 1083 expect![[r#"
1068 async fn foo<|>() {} 1084 foo:
1069 ", 1085 ```rust
1070 &["async fn foo()"], 1086 async fn foo()
1071 ); 1087 ```
1072 check_hover_result( 1088 "#]],
1073 r" 1089 );
1074 //- /lib.rs 1090 check(
1075 pub const unsafe fn foo<|>() {} 1091 r#"pub const unsafe fn foo<|>() {}"#,
1076 ", 1092 expect![[r#"
1077 &["pub const unsafe fn foo()"], 1093 foo:
1078 ); 1094 ```rust
1079 check_hover_result( 1095 pub const unsafe fn foo()
1080 r#" 1096 ```
1081 //- /lib.rs 1097 "#]],
1082 pub(crate) async unsafe extern "C" fn foo<|>() {} 1098 );
1083 "#, 1099 check(
1084 &[r#"pub(crate) async unsafe extern "C" fn foo()"#], 1100 r#"pub(crate) async unsafe extern "C" fn foo<|>() {}"#,
1101 expect![[r#"
1102 foo:
1103 ```rust
1104 pub(crate) async unsafe extern "C" fn foo()
1105 ```
1106 "#]],
1085 ); 1107 );
1086 } 1108 }
1087 1109
1088 #[test] 1110 #[test]
1089 fn test_hover_trait_show_qualifiers() { 1111 fn test_hover_trait_show_qualifiers() {
1090 let (_, actions) = check_hover_result( 1112 check_actions(
1091 r" 1113 r"unsafe trait foo<|>() {}",
1092 //- /lib.rs 1114 expect![[r#"
1093 unsafe trait foo<|>() {} 1115 [
1094 ", 1116 Implementaion(
1095 &["unsafe trait foo"], 1117 FilePosition {
1118 file_id: FileId(
1119 1,
1120 ),
1121 offset: 13,
1122 },
1123 ),
1124 ]
1125 "#]],
1096 ); 1126 );
1097 assert_impl_action(&actions[0], 13);
1098 } 1127 }
1099 1128
1100 #[test] 1129 #[test]
1101 fn test_hover_mod_with_same_name_as_function() { 1130 fn test_hover_mod_with_same_name_as_function() {
1102 check_hover_result( 1131 check(
1103 r" 1132 r#"
1104 //- /lib.rs 1133use self::m<|>y::Bar;
1105 use self::m<|>y::Bar; 1134mod my { pub struct Bar; }
1106
1107 mod my {
1108 pub struct Bar;
1109 }
1110 1135
1111 fn my() {} 1136fn my() {}
1112 ", 1137"#,
1113 &["mod my"], 1138 expect![[r#"
1139 my:
1140 ```rust
1141 mod my
1142 ```
1143 "#]],
1114 ); 1144 );
1115 } 1145 }
1116 1146
1117 #[test] 1147 #[test]
1118 fn test_hover_struct_doc_comment() { 1148 fn test_hover_struct_doc_comment() {
1119 check_hover_result( 1149 check(
1120 r#" 1150 r#"
1121 //- /lib.rs 1151/// bar docs
1122 /// bar docs 1152struct Bar;
1123 struct Bar;
1124 1153
1125 fn foo() { 1154fn foo() { let bar = Ba<|>r; }
1126 let bar = Ba<|>r; 1155"#,
1127 } 1156 expect![[r#"
1128 "#, 1157 Bar:
1129 &["struct Bar\n```\n___\n\nbar docs"], 1158 ```rust
1159 struct Bar
1160 ```
1161 ___
1162
1163 bar docs
1164 "#]],
1130 ); 1165 );
1131 } 1166 }
1132 1167
1133 #[test] 1168 #[test]
1134 fn test_hover_struct_doc_attr() { 1169 fn test_hover_struct_doc_attr() {
1135 check_hover_result( 1170 check(
1136 r#" 1171 r#"
1137 //- /lib.rs 1172#[doc = "bar docs"]
1138 #[doc = "bar docs"] 1173struct Bar;
1139 struct Bar;
1140 1174
1141 fn foo() { 1175fn foo() { let bar = Ba<|>r; }
1142 let bar = Ba<|>r; 1176"#,
1143 } 1177 expect![[r#"
1144 "#, 1178 Bar:
1145 &["struct Bar\n```\n___\n\nbar docs"], 1179 ```rust
1180 struct Bar
1181 ```
1182 ___
1183
1184 bar docs
1185 "#]],
1146 ); 1186 );
1147 } 1187 }
1148 1188
1149 #[test] 1189 #[test]
1150 fn test_hover_struct_doc_attr_multiple_and_mixed() { 1190 fn test_hover_struct_doc_attr_multiple_and_mixed() {
1151 check_hover_result( 1191 check(
1152 r#" 1192 r#"
1153 //- /lib.rs 1193/// bar docs 0
1154 /// bar docs 0 1194#[doc = "bar docs 1"]
1155 #[doc = "bar docs 1"] 1195#[doc = "bar docs 2"]
1156 #[doc = "bar docs 2"] 1196struct Bar;
1157 struct Bar;
1158 1197
1159 fn foo() { 1198fn foo() { let bar = Ba<|>r; }
1160 let bar = Ba<|>r; 1199"#,
1161 } 1200 expect![[r#"
1162 "#, 1201 Bar:
1163 &["struct Bar\n```\n___\n\nbar docs 0\n\nbar docs 1\n\nbar docs 2"], 1202 ```rust
1203 struct Bar
1204 ```
1205 ___
1206
1207 bar docs 0
1208
1209 bar docs 1
1210
1211 bar docs 2
1212 "#]],
1164 ); 1213 );
1165 } 1214 }
1166 1215
@@ -1168,27 +1217,35 @@ fn func(foo: i32) { if true { <|>foo; }; }
1168 fn test_hover_macro_generated_struct_fn_doc_comment() { 1217 fn test_hover_macro_generated_struct_fn_doc_comment() {
1169 mark::check!(hover_macro_generated_struct_fn_doc_comment); 1218 mark::check!(hover_macro_generated_struct_fn_doc_comment);
1170 1219
1171 check_hover_result( 1220 check(
1172 r#" 1221 r#"
1173 //- /lib.rs 1222macro_rules! bar {
1174 macro_rules! bar { 1223 () => {
1175 () => { 1224 struct Bar;
1176 struct Bar; 1225 impl Bar {
1177 impl Bar { 1226 /// Do the foo
1178 /// Do the foo 1227 fn foo(&self) {}
1179 fn foo(&self) {} 1228 }
1180 } 1229 }
1181 } 1230}
1182 }
1183 1231
1184 bar!(); 1232bar!();
1185 1233
1186 fn foo() { 1234fn foo() { let bar = Bar; bar.fo<|>o(); }
1187 let bar = Bar; 1235"#,
1188 bar.fo<|>o(); 1236 expect![[r#"
1189 } 1237 foo:
1190 "#, 1238 ```rust
1191 &["Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\n Do the foo"], 1239 Bar
1240 ```
1241
1242 ```rust
1243 fn foo(&self)
1244 ```
1245 ___
1246
1247 Do the foo
1248 "#]],
1192 ); 1249 );
1193 } 1250 }
1194 1251
@@ -1196,1204 +1253,1155 @@ fn func(foo: i32) { if true { <|>foo; }; }
1196 fn test_hover_macro_generated_struct_fn_doc_attr() { 1253 fn test_hover_macro_generated_struct_fn_doc_attr() {
1197 mark::check!(hover_macro_generated_struct_fn_doc_attr); 1254 mark::check!(hover_macro_generated_struct_fn_doc_attr);
1198 1255
1199 check_hover_result( 1256 check(
1200 r#" 1257 r#"
1201 //- /lib.rs 1258macro_rules! bar {
1202 macro_rules! bar { 1259 () => {
1203 () => { 1260 struct Bar;
1204 struct Bar; 1261 impl Bar {
1205 impl Bar { 1262 #[doc = "Do the foo"]
1206 #[doc = "Do the foo"] 1263 fn foo(&self) {}
1207 fn foo(&self) {} 1264 }
1208 } 1265 }
1209 } 1266}
1210 }
1211 1267
1212 bar!(); 1268bar!();
1213 1269
1214 fn foo() { 1270fn foo() { let bar = Bar; bar.fo<|>o(); }
1215 let bar = Bar; 1271"#,
1216 bar.fo<|>o(); 1272 expect![[r#"
1217 } 1273 foo:
1218 "#, 1274 ```rust
1219 &["Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\nDo the foo"], 1275 Bar
1276 ```
1277
1278 ```rust
1279 fn foo(&self)
1280 ```
1281 ___
1282
1283 Do the foo
1284 "#]],
1220 ); 1285 );
1221 } 1286 }
1222 1287
1223 #[test] 1288 #[test]
1224 fn test_hover_trait_has_impl_action() { 1289 fn test_hover_trait_has_impl_action() {
1225 let (_, actions) = check_hover_result( 1290 check_actions(
1226 r" 1291 r#"trait foo<|>() {}"#,
1227 //- /lib.rs 1292 expect![[r#"
1228 trait foo<|>() {} 1293 [
1229 ", 1294 Implementaion(
1230 &["trait foo"], 1295 FilePosition {
1296 file_id: FileId(
1297 1,
1298 ),
1299 offset: 6,
1300 },
1301 ),
1302 ]
1303 "#]],
1231 ); 1304 );
1232 assert_impl_action(&actions[0], 6);
1233 } 1305 }
1234 1306
1235 #[test] 1307 #[test]
1236 fn test_hover_struct_has_impl_action() { 1308 fn test_hover_struct_has_impl_action() {
1237 let (_, actions) = check_hover_result( 1309 check_actions(
1238 r" 1310 r"struct foo<|>() {}",
1239 //- /lib.rs 1311 expect![[r#"
1240 struct foo<|>() {} 1312 [
1241 ", 1313 Implementaion(
1242 &["struct foo"], 1314 FilePosition {
1315 file_id: FileId(
1316 1,
1317 ),
1318 offset: 7,
1319 },
1320 ),
1321 ]
1322 "#]],
1243 ); 1323 );
1244 assert_impl_action(&actions[0], 7);
1245 } 1324 }
1246 1325
1247 #[test] 1326 #[test]
1248 fn test_hover_union_has_impl_action() { 1327 fn test_hover_union_has_impl_action() {
1249 let (_, actions) = check_hover_result( 1328 check_actions(
1250 r" 1329 r#"union foo<|>() {}"#,
1251 //- /lib.rs 1330 expect![[r#"
1252 union foo<|>() {} 1331 [
1253 ", 1332 Implementaion(
1254 &["union foo"], 1333 FilePosition {
1255 );
1256 assert_impl_action(&actions[0], 6);
1257 }
1258
1259 #[test]
1260 fn test_hover_enum_has_impl_action() {
1261 let (_, actions) = check_hover_result(
1262 r"
1263 //- /lib.rs
1264 enum foo<|>() {
1265 A,
1266 B
1267 }
1268 ",
1269 &["enum foo"],
1270 );
1271 assert_impl_action(&actions[0], 5);
1272 }
1273
1274 #[test]
1275 fn test_hover_test_has_action() {
1276 let (_, actions) = check_hover_result(
1277 r"
1278 //- /lib.rs
1279 #[test]
1280 fn foo_<|>test() {}
1281 ",
1282 &["fn foo_test()"],
1283 );
1284 assert_debug_snapshot!(actions,
1285 @r###"
1286 [
1287 Runnable(
1288 Runnable {
1289 nav: NavigationTarget {
1290 file_id: FileId( 1334 file_id: FileId(
1291 1, 1335 1,
1292 ), 1336 ),
1293 full_range: 0..24, 1337 offset: 6,
1294 name: "foo_test",
1295 kind: FN_DEF,
1296 focus_range: Some(
1297 11..19,
1298 ),
1299 container_name: None,
1300 description: None,
1301 docs: None,
1302 },
1303 kind: Test {
1304 test_id: Path(
1305 "foo_test",
1306 ),
1307 attr: TestAttr {
1308 ignore: false,
1309 },
1310 }, 1338 },
1311 cfg_exprs: [], 1339 ),
1312 }, 1340 ]
1313 ), 1341 "#]],
1314 ] 1342 );
1315 "###);
1316 } 1343 }
1317 1344
1318 #[test] 1345 #[test]
1319 fn test_hover_test_mod_has_action() { 1346 fn test_hover_enum_has_impl_action() {
1320 let (_, actions) = check_hover_result( 1347 check_actions(
1321 r" 1348 r"enum foo<|>() { A, B }",
1322 //- /lib.rs 1349 expect![[r#"
1323 mod tests<|> { 1350 [
1324 #[test] 1351 Implementaion(
1325 fn foo_test() {} 1352 FilePosition {
1326 }
1327 ",
1328 &["mod tests"],
1329 );
1330 assert_debug_snapshot!(actions,
1331 @r###"
1332 [
1333 Runnable(
1334 Runnable {
1335 nav: NavigationTarget {
1336 file_id: FileId( 1353 file_id: FileId(
1337 1, 1354 1,
1338 ), 1355 ),
1339 full_range: 0..46, 1356 offset: 5,
1340 name: "tests",
1341 kind: MODULE,
1342 focus_range: Some(
1343 4..9,
1344 ),
1345 container_name: None,
1346 description: None,
1347 docs: None,
1348 },
1349 kind: TestMod {
1350 path: "tests",
1351 }, 1357 },
1352 cfg_exprs: [], 1358 ),
1353 }, 1359 ]
1354 ), 1360 "#]],
1355 ] 1361 );
1356 "###);
1357 } 1362 }
1358 1363
1359 #[test] 1364 #[test]
1360 fn test_hover_struct_has_goto_type_action() { 1365 fn test_hover_test_has_action() {
1361 let (_, actions) = check_hover_result( 1366 check_actions(
1362 r" 1367 r#"
1363 //- /main.rs 1368#[test]
1364 struct S{ f1: u32 } 1369fn foo_<|>test() {}
1365 1370"#,
1366 fn main() { 1371 expect![[r#"
1367 let s<|>t = S{ f1:0 }; 1372 [
1368 } 1373 Runnable(
1369 ", 1374 Runnable {
1370 &["S"],
1371 );
1372 assert_debug_snapshot!(actions,
1373 @r###"
1374 [
1375 GoToType(
1376 [
1377 HoverGotoTypeData {
1378 mod_path: "S",
1379 nav: NavigationTarget { 1375 nav: NavigationTarget {
1380 file_id: FileId( 1376 file_id: FileId(
1381 1, 1377 1,
1382 ), 1378 ),
1383 full_range: 0..19, 1379 full_range: 0..24,
1384 name: "S", 1380 name: "foo_test",
1385 kind: STRUCT_DEF, 1381 kind: FN_DEF,
1386 focus_range: Some( 1382 focus_range: Some(
1387 7..8, 1383 11..19,
1388 ), 1384 ),
1389 container_name: None, 1385 container_name: None,
1390 description: Some( 1386 description: None,
1391 "struct S",
1392 ),
1393 docs: None, 1387 docs: None,
1394 }, 1388 },
1389 kind: Test {
1390 test_id: Path(
1391 "foo_test",
1392 ),
1393 attr: TestAttr {
1394 ignore: false,
1395 },
1396 },
1397 cfg_exprs: [],
1395 }, 1398 },
1396 ], 1399 ),
1397 ), 1400 ]
1398 ] 1401 "#]],
1399 "###); 1402 );
1400 } 1403 }
1401 1404
1402 #[test] 1405 #[test]
1403 fn test_hover_generic_struct_has_goto_type_actions() { 1406 fn test_hover_test_mod_has_action() {
1404 let (_, actions) = check_hover_result( 1407 check_actions(
1405 r" 1408 r#"
1406 //- /main.rs 1409mod tests<|> {
1407 struct Arg(u32); 1410 #[test]
1408 struct S<T>{ f1: T } 1411 fn foo_test() {}
1409 1412}
1410 fn main() { 1413"#,
1411 let s<|>t = S{ f1:Arg(0) }; 1414 expect![[r#"
1412 } 1415 [
1413 ", 1416 Runnable(
1414 &["S<Arg>"], 1417 Runnable {
1415 );
1416 assert_debug_snapshot!(actions,
1417 @r###"
1418 [
1419 GoToType(
1420 [
1421 HoverGotoTypeData {
1422 mod_path: "S",
1423 nav: NavigationTarget { 1418 nav: NavigationTarget {
1424 file_id: FileId( 1419 file_id: FileId(
1425 1, 1420 1,
1426 ), 1421 ),
1427 full_range: 17..37, 1422 full_range: 0..46,
1428 name: "S", 1423 name: "tests",
1429 kind: STRUCT_DEF, 1424 kind: MODULE,
1430 focus_range: Some( 1425 focus_range: Some(
1431 24..25, 1426 4..9,
1432 ), 1427 ),
1433 container_name: None, 1428 container_name: None,
1434 description: Some( 1429 description: None,
1435 "struct S",
1436 ),
1437 docs: None, 1430 docs: None,
1438 }, 1431 },
1439 }, 1432 kind: TestMod {
1440 HoverGotoTypeData { 1433 path: "tests",
1441 mod_path: "Arg",
1442 nav: NavigationTarget {
1443 file_id: FileId(
1444 1,
1445 ),
1446 full_range: 0..16,
1447 name: "Arg",
1448 kind: STRUCT_DEF,
1449 focus_range: Some(
1450 7..10,
1451 ),
1452 container_name: None,
1453 description: Some(
1454 "struct Arg",
1455 ),
1456 docs: None,
1457 }, 1434 },
1435 cfg_exprs: [],
1458 }, 1436 },
1459 ], 1437 ),
1460 ), 1438 ]
1461 ] 1439 "#]],
1462 "###); 1440 );
1463 } 1441 }
1464 1442
1465 #[test] 1443 #[test]
1466 fn test_hover_generic_struct_has_flattened_goto_type_actions() { 1444 fn test_hover_struct_has_goto_type_action() {
1467 let (_, actions) = check_hover_result( 1445 check_actions(
1468 r" 1446 r#"
1469 //- /main.rs 1447struct S{ f1: u32 }
1470 struct Arg(u32); 1448
1471 struct S<T>{ f1: T } 1449fn main() { let s<|>t = S{ f1:0 }; }
1472 1450 "#,
1473 fn main() { 1451 expect![[r#"
1474 let s<|>t = S{ f1: S{ f1: Arg(0) } }; 1452 [
1475 } 1453 GoToType(
1476 ", 1454 [
1477 &["S<S<Arg>>"], 1455 HoverGotoTypeData {
1456 mod_path: "S",
1457 nav: NavigationTarget {
1458 file_id: FileId(
1459 1,
1460 ),
1461 full_range: 0..19,
1462 name: "S",
1463 kind: STRUCT_DEF,
1464 focus_range: Some(
1465 7..8,
1466 ),
1467 container_name: None,
1468 description: Some(
1469 "struct S",
1470 ),
1471 docs: None,
1472 },
1473 },
1474 ],
1475 ),
1476 ]
1477 "#]],
1478 ); 1478 );
1479 assert_debug_snapshot!(actions, 1479 }
1480 @r###" 1480
1481 [ 1481 #[test]
1482 GoToType( 1482 fn test_hover_generic_struct_has_goto_type_actions() {
1483 [ 1483 check_actions(
1484 HoverGotoTypeData { 1484 r#"
1485 mod_path: "S", 1485struct Arg(u32);
1486 nav: NavigationTarget { 1486struct S<T>{ f1: T }
1487 file_id: FileId( 1487
1488 1, 1488fn main() { let s<|>t = S{ f1:Arg(0) }; }
1489 ), 1489"#,
1490 full_range: 17..37, 1490 expect![[r#"
1491 name: "S", 1491 [
1492 kind: STRUCT_DEF, 1492 GoToType(
1493 focus_range: Some( 1493 [
1494 24..25, 1494 HoverGotoTypeData {
1495 ), 1495 mod_path: "S",
1496 container_name: None, 1496 nav: NavigationTarget {
1497 description: Some( 1497 file_id: FileId(
1498 "struct S", 1498 1,
1499 ), 1499 ),
1500 docs: None, 1500 full_range: 17..37,
1501 name: "S",
1502 kind: STRUCT_DEF,
1503 focus_range: Some(
1504 24..25,
1505 ),
1506 container_name: None,
1507 description: Some(
1508 "struct S",
1509 ),
1510 docs: None,
1511 },
1501 }, 1512 },
1502 }, 1513 HoverGotoTypeData {
1503 HoverGotoTypeData { 1514 mod_path: "Arg",
1504 mod_path: "Arg", 1515 nav: NavigationTarget {
1505 nav: NavigationTarget { 1516 file_id: FileId(
1506 file_id: FileId( 1517 1,
1507 1, 1518 ),
1508 ), 1519 full_range: 0..16,
1509 full_range: 0..16, 1520 name: "Arg",
1510 name: "Arg", 1521 kind: STRUCT_DEF,
1511 kind: STRUCT_DEF, 1522 focus_range: Some(
1512 focus_range: Some( 1523 7..10,
1513 7..10, 1524 ),
1514 ), 1525 container_name: None,
1515 container_name: None, 1526 description: Some(
1516 description: Some( 1527 "struct Arg",
1517 "struct Arg", 1528 ),
1518 ), 1529 docs: None,
1519 docs: None, 1530 },
1520 }, 1531 },
1521 }, 1532 ],
1522 ], 1533 ),
1523 ), 1534 ]
1524 ] 1535 "#]],
1525 "###); 1536 );
1526 } 1537 }
1527 1538
1528 #[test] 1539 #[test]
1529 fn test_hover_tuple_has_goto_type_actions() { 1540 fn test_hover_generic_struct_has_flattened_goto_type_actions() {
1530 let (_, actions) = check_hover_result( 1541 check_actions(
1531 r" 1542 r#"
1532 //- /main.rs 1543struct Arg(u32);
1533 struct A(u32); 1544struct S<T>{ f1: T }
1534 struct B(u32);
1535 mod M {
1536 pub struct C(u32);
1537 }
1538 1545
1539 fn main() { 1546fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
1540 let s<|>t = (A(1), B(2), M::C(3) ); 1547 "#,
1541 } 1548 expect![[r#"
1542 ", 1549 [
1543 &["(A, B, C)"], 1550 GoToType(
1551 [
1552 HoverGotoTypeData {
1553 mod_path: "S",
1554 nav: NavigationTarget {
1555 file_id: FileId(
1556 1,
1557 ),
1558 full_range: 17..37,
1559 name: "S",
1560 kind: STRUCT_DEF,
1561 focus_range: Some(
1562 24..25,
1563 ),
1564 container_name: None,
1565 description: Some(
1566 "struct S",
1567 ),
1568 docs: None,
1569 },
1570 },
1571 HoverGotoTypeData {
1572 mod_path: "Arg",
1573 nav: NavigationTarget {
1574 file_id: FileId(
1575 1,
1576 ),
1577 full_range: 0..16,
1578 name: "Arg",
1579 kind: STRUCT_DEF,
1580 focus_range: Some(
1581 7..10,
1582 ),
1583 container_name: None,
1584 description: Some(
1585 "struct Arg",
1586 ),
1587 docs: None,
1588 },
1589 },
1590 ],
1591 ),
1592 ]
1593 "#]],
1544 ); 1594 );
1545 assert_debug_snapshot!(actions, 1595 }
1546 @r###" 1596
1547 [ 1597 #[test]
1548 GoToType( 1598 fn test_hover_tuple_has_goto_type_actions() {
1549 [ 1599 check_actions(
1550 HoverGotoTypeData { 1600 r#"
1551 mod_path: "A", 1601struct A(u32);
1552 nav: NavigationTarget { 1602struct B(u32);
1553 file_id: FileId( 1603mod M {
1554 1, 1604 pub struct C(u32);
1555 ), 1605}
1556 full_range: 0..14, 1606
1557 name: "A", 1607fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
1558 kind: STRUCT_DEF, 1608"#,
1559 focus_range: Some( 1609 expect![[r#"
1560 7..8, 1610 [
1561 ), 1611 GoToType(
1562 container_name: None, 1612 [
1563 description: Some( 1613 HoverGotoTypeData {
1564 "struct A", 1614 mod_path: "A",
1565 ), 1615 nav: NavigationTarget {
1566 docs: None, 1616 file_id: FileId(
1617 1,
1618 ),
1619 full_range: 0..14,
1620 name: "A",
1621 kind: STRUCT_DEF,
1622 focus_range: Some(
1623 7..8,
1624 ),
1625 container_name: None,
1626 description: Some(
1627 "struct A",
1628 ),
1629 docs: None,
1630 },
1567 }, 1631 },
1568 }, 1632 HoverGotoTypeData {
1569 HoverGotoTypeData { 1633 mod_path: "B",
1570 mod_path: "B", 1634 nav: NavigationTarget {
1571 nav: NavigationTarget { 1635 file_id: FileId(
1572 file_id: FileId( 1636 1,
1573 1, 1637 ),
1574 ), 1638 full_range: 15..29,
1575 full_range: 15..29, 1639 name: "B",
1576 name: "B", 1640 kind: STRUCT_DEF,
1577 kind: STRUCT_DEF, 1641 focus_range: Some(
1578 focus_range: Some( 1642 22..23,
1579 22..23, 1643 ),
1580 ), 1644 container_name: None,
1581 container_name: None, 1645 description: Some(
1582 description: Some( 1646 "struct B",
1583 "struct B", 1647 ),
1584 ), 1648 docs: None,
1585 docs: None, 1649 },
1586 }, 1650 },
1587 }, 1651 HoverGotoTypeData {
1588 HoverGotoTypeData { 1652 mod_path: "M::C",
1589 mod_path: "M::C", 1653 nav: NavigationTarget {
1590 nav: NavigationTarget { 1654 file_id: FileId(
1591 file_id: FileId( 1655 1,
1592 1, 1656 ),
1593 ), 1657 full_range: 42..60,
1594 full_range: 42..60, 1658 name: "C",
1595 name: "C", 1659 kind: STRUCT_DEF,
1596 kind: STRUCT_DEF, 1660 focus_range: Some(
1597 focus_range: Some( 1661 53..54,
1598 53..54, 1662 ),
1599 ), 1663 container_name: None,
1600 container_name: None, 1664 description: Some(
1601 description: Some( 1665 "pub struct C",
1602 "pub struct C", 1666 ),
1603 ), 1667 docs: None,
1604 docs: None, 1668 },
1605 }, 1669 },
1606 }, 1670 ],
1607 ], 1671 ),
1608 ), 1672 ]
1609 ] 1673 "#]],
1610 "###); 1674 );
1611 } 1675 }
1612 1676
1613 #[test] 1677 #[test]
1614 fn test_hover_return_impl_trait_has_goto_type_action() { 1678 fn test_hover_return_impl_trait_has_goto_type_action() {
1615 let (_, actions) = check_hover_result( 1679 check_actions(
1616 r" 1680 r#"
1617 //- /main.rs 1681trait Foo {}
1618 trait Foo {} 1682fn foo() -> impl Foo {}
1619
1620 fn foo() -> impl Foo {}
1621 1683
1622 fn main() { 1684fn main() { let s<|>t = foo(); }
1623 let s<|>t = foo(); 1685"#,
1624 } 1686 expect![[r#"
1625 ", 1687 [
1626 &["impl Foo"], 1688 GoToType(
1627 ); 1689 [
1628 assert_debug_snapshot!(actions, 1690 HoverGotoTypeData {
1629 @r###" 1691 mod_path: "Foo",
1630 [ 1692 nav: NavigationTarget {
1631 GoToType( 1693 file_id: FileId(
1632 [ 1694 1,
1633 HoverGotoTypeData { 1695 ),
1634 mod_path: "Foo", 1696 full_range: 0..12,
1635 nav: NavigationTarget { 1697 name: "Foo",
1636 file_id: FileId( 1698 kind: TRAIT_DEF,
1637 1, 1699 focus_range: Some(
1638 ), 1700 6..9,
1639 full_range: 0..12, 1701 ),
1640 name: "Foo", 1702 container_name: None,
1641 kind: TRAIT_DEF, 1703 description: Some(
1642 focus_range: Some( 1704 "trait Foo",
1643 6..9, 1705 ),
1644 ), 1706 docs: None,
1645 container_name: None, 1707 },
1646 description: Some(
1647 "trait Foo",
1648 ),
1649 docs: None,
1650 }, 1708 },
1651 }, 1709 ],
1652 ], 1710 ),
1653 ), 1711 ]
1654 ] 1712 "#]],
1655 "###); 1713 );
1656 } 1714 }
1657 1715
1658 #[test] 1716 #[test]
1659 fn test_hover_generic_return_impl_trait_has_goto_type_action() { 1717 fn test_hover_generic_return_impl_trait_has_goto_type_action() {
1660 let (_, actions) = check_hover_result( 1718 check_actions(
1661 r" 1719 r#"
1662 //- /main.rs 1720trait Foo<T> {}
1663 trait Foo<T> {} 1721struct S;
1664 struct S; 1722fn foo() -> impl Foo<S> {}
1665
1666 fn foo() -> impl Foo<S> {}
1667 1723
1668 fn main() { 1724fn main() { let s<|>t = foo(); }
1669 let s<|>t = foo(); 1725"#,
1670 } 1726 expect![[r#"
1671 ", 1727 [
1672 &["impl Foo<S>"], 1728 GoToType(
1673 ); 1729 [
1674 assert_debug_snapshot!(actions, 1730 HoverGotoTypeData {
1675 @r###" 1731 mod_path: "Foo",
1676 [ 1732 nav: NavigationTarget {
1677 GoToType( 1733 file_id: FileId(
1678 [ 1734 1,
1679 HoverGotoTypeData { 1735 ),
1680 mod_path: "Foo", 1736 full_range: 0..15,
1681 nav: NavigationTarget { 1737 name: "Foo",
1682 file_id: FileId( 1738 kind: TRAIT_DEF,
1683 1, 1739 focus_range: Some(
1684 ), 1740 6..9,
1685 full_range: 0..15, 1741 ),
1686 name: "Foo", 1742 container_name: None,
1687 kind: TRAIT_DEF, 1743 description: Some(
1688 focus_range: Some( 1744 "trait Foo",
1689 6..9, 1745 ),
1690 ), 1746 docs: None,
1691 container_name: None, 1747 },
1692 description: Some(
1693 "trait Foo",
1694 ),
1695 docs: None,
1696 }, 1748 },
1697 }, 1749 HoverGotoTypeData {
1698 HoverGotoTypeData { 1750 mod_path: "S",
1699 mod_path: "S", 1751 nav: NavigationTarget {
1700 nav: NavigationTarget { 1752 file_id: FileId(
1701 file_id: FileId( 1753 1,
1702 1, 1754 ),
1703 ), 1755 full_range: 16..25,
1704 full_range: 16..25, 1756 name: "S",
1705 name: "S", 1757 kind: STRUCT_DEF,
1706 kind: STRUCT_DEF, 1758 focus_range: Some(
1707 focus_range: Some( 1759 23..24,
1708 23..24, 1760 ),
1709 ), 1761 container_name: None,
1710 container_name: None, 1762 description: Some(
1711 description: Some( 1763 "struct S",
1712 "struct S", 1764 ),
1713 ), 1765 docs: None,
1714 docs: None, 1766 },
1715 }, 1767 },
1716 }, 1768 ],
1717 ], 1769 ),
1718 ), 1770 ]
1719 ] 1771 "#]],
1720 "###); 1772 );
1721 } 1773 }
1722 1774
1723 #[test] 1775 #[test]
1724 fn test_hover_return_impl_traits_has_goto_type_action() { 1776 fn test_hover_return_impl_traits_has_goto_type_action() {
1725 let (_, actions) = check_hover_result( 1777 check_actions(
1726 r" 1778 r#"
1727 //- /main.rs 1779trait Foo {}
1728 trait Foo {} 1780trait Bar {}
1729 trait Bar {} 1781fn foo() -> impl Foo + Bar {}
1730
1731 fn foo() -> impl Foo + Bar {}
1732 1782
1733 fn main() { 1783fn main() { let s<|>t = foo(); }
1734 let s<|>t = foo(); 1784 "#,
1735 } 1785 expect![[r#"
1736 ", 1786 [
1737 &["impl Foo + Bar"], 1787 GoToType(
1738 ); 1788 [
1739 assert_debug_snapshot!(actions, 1789 HoverGotoTypeData {
1740 @r###" 1790 mod_path: "Foo",
1741 [ 1791 nav: NavigationTarget {
1742 GoToType( 1792 file_id: FileId(
1743 [ 1793 1,
1744 HoverGotoTypeData { 1794 ),
1745 mod_path: "Foo", 1795 full_range: 0..12,
1746 nav: NavigationTarget { 1796 name: "Foo",
1747 file_id: FileId( 1797 kind: TRAIT_DEF,
1748 1, 1798 focus_range: Some(
1749 ), 1799 6..9,
1750 full_range: 0..12, 1800 ),
1751 name: "Foo", 1801 container_name: None,
1752 kind: TRAIT_DEF, 1802 description: Some(
1753 focus_range: Some( 1803 "trait Foo",
1754 6..9, 1804 ),
1755 ), 1805 docs: None,
1756 container_name: None, 1806 },
1757 description: Some(
1758 "trait Foo",
1759 ),
1760 docs: None,
1761 }, 1807 },
1762 }, 1808 HoverGotoTypeData {
1763 HoverGotoTypeData { 1809 mod_path: "Bar",
1764 mod_path: "Bar", 1810 nav: NavigationTarget {
1765 nav: NavigationTarget { 1811 file_id: FileId(
1766 file_id: FileId( 1812 1,
1767 1, 1813 ),
1768 ), 1814 full_range: 13..25,
1769 full_range: 13..25, 1815 name: "Bar",
1770 name: "Bar", 1816 kind: TRAIT_DEF,
1771 kind: TRAIT_DEF, 1817 focus_range: Some(
1772 focus_range: Some( 1818 19..22,
1773 19..22, 1819 ),
1774 ), 1820 container_name: None,
1775 container_name: None, 1821 description: Some(
1776 description: Some( 1822 "trait Bar",
1777 "trait Bar", 1823 ),
1778 ), 1824 docs: None,
1779 docs: None, 1825 },
1780 }, 1826 },
1781 }, 1827 ],
1782 ], 1828 ),
1783 ), 1829 ]
1784 ] 1830 "#]],
1785 "###); 1831 );
1786 } 1832 }
1787 1833
1788 #[test] 1834 #[test]
1789 fn test_hover_generic_return_impl_traits_has_goto_type_action() { 1835 fn test_hover_generic_return_impl_traits_has_goto_type_action() {
1790 let (_, actions) = check_hover_result( 1836 check_actions(
1791 r" 1837 r#"
1792 //- /main.rs 1838trait Foo<T> {}
1793 trait Foo<T> {} 1839trait Bar<T> {}
1794 trait Bar<T> {} 1840struct S1 {}
1795 struct S1 {} 1841struct S2 {}
1796 struct S2 {} 1842
1797 1843fn foo() -> impl Foo<S1> + Bar<S2> {}
1798 fn foo() -> impl Foo<S1> + Bar<S2> {} 1844
1799 1845fn main() { let s<|>t = foo(); }
1800 fn main() { 1846"#,
1801 let s<|>t = foo(); 1847 expect![[r#"
1802 } 1848 [
1803 ", 1849 GoToType(
1804 &["impl Foo<S1> + Bar<S2>"], 1850 [
1805 ); 1851 HoverGotoTypeData {
1806 assert_debug_snapshot!(actions, 1852 mod_path: "Foo",
1807 @r###" 1853 nav: NavigationTarget {
1808 [ 1854 file_id: FileId(
1809 GoToType( 1855 1,
1810 [ 1856 ),
1811 HoverGotoTypeData { 1857 full_range: 0..15,
1812 mod_path: "Foo", 1858 name: "Foo",
1813 nav: NavigationTarget { 1859 kind: TRAIT_DEF,
1814 file_id: FileId( 1860 focus_range: Some(
1815 1, 1861 6..9,
1816 ), 1862 ),
1817 full_range: 0..15, 1863 container_name: None,
1818 name: "Foo", 1864 description: Some(
1819 kind: TRAIT_DEF, 1865 "trait Foo",
1820 focus_range: Some( 1866 ),
1821 6..9, 1867 docs: None,
1822 ), 1868 },
1823 container_name: None,
1824 description: Some(
1825 "trait Foo",
1826 ),
1827 docs: None,
1828 }, 1869 },
1829 }, 1870 HoverGotoTypeData {
1830 HoverGotoTypeData { 1871 mod_path: "Bar",
1831 mod_path: "Bar", 1872 nav: NavigationTarget {
1832 nav: NavigationTarget { 1873 file_id: FileId(
1833 file_id: FileId( 1874 1,
1834 1, 1875 ),
1835 ), 1876 full_range: 16..31,
1836 full_range: 16..31, 1877 name: "Bar",
1837 name: "Bar", 1878 kind: TRAIT_DEF,
1838 kind: TRAIT_DEF, 1879 focus_range: Some(
1839 focus_range: Some( 1880 22..25,
1840 22..25, 1881 ),
1841 ), 1882 container_name: None,
1842 container_name: None, 1883 description: Some(
1843 description: Some( 1884 "trait Bar",
1844 "trait Bar", 1885 ),
1845 ), 1886 docs: None,
1846 docs: None, 1887 },
1847 }, 1888 },
1848 }, 1889 HoverGotoTypeData {
1849 HoverGotoTypeData { 1890 mod_path: "S1",
1850 mod_path: "S1", 1891 nav: NavigationTarget {
1851 nav: NavigationTarget { 1892 file_id: FileId(
1852 file_id: FileId( 1893 1,
1853 1, 1894 ),
1854 ), 1895 full_range: 32..44,
1855 full_range: 32..44, 1896 name: "S1",
1856 name: "S1", 1897 kind: STRUCT_DEF,
1857 kind: STRUCT_DEF, 1898 focus_range: Some(
1858 focus_range: Some( 1899 39..41,
1859 39..41, 1900 ),
1860 ), 1901 container_name: None,
1861 container_name: None, 1902 description: Some(
1862 description: Some( 1903 "struct S1",
1863 "struct S1", 1904 ),
1864 ), 1905 docs: None,
1865 docs: None, 1906 },
1866 }, 1907 },
1867 }, 1908 HoverGotoTypeData {
1868 HoverGotoTypeData { 1909 mod_path: "S2",
1869 mod_path: "S2", 1910 nav: NavigationTarget {
1870 nav: NavigationTarget { 1911 file_id: FileId(
1871 file_id: FileId( 1912 1,
1872 1, 1913 ),
1873 ), 1914 full_range: 45..57,
1874 full_range: 45..57, 1915 name: "S2",
1875 name: "S2", 1916 kind: STRUCT_DEF,
1876 kind: STRUCT_DEF, 1917 focus_range: Some(
1877 focus_range: Some( 1918 52..54,
1878 52..54, 1919 ),
1879 ), 1920 container_name: None,
1880 container_name: None, 1921 description: Some(
1881 description: Some( 1922 "struct S2",
1882 "struct S2", 1923 ),
1883 ), 1924 docs: None,
1884 docs: None, 1925 },
1885 }, 1926 },
1886 }, 1927 ],
1887 ], 1928 ),
1888 ), 1929 ]
1889 ] 1930 "#]],
1890 "###); 1931 );
1891 } 1932 }
1892 1933
1893 #[test] 1934 #[test]
1894 fn test_hover_arg_impl_trait_has_goto_type_action() { 1935 fn test_hover_arg_impl_trait_has_goto_type_action() {
1895 let (_, actions) = check_hover_result( 1936 check_actions(
1896 r" 1937 r#"
1897 //- /lib.rs 1938trait Foo {}
1898 trait Foo {} 1939fn foo(ar<|>g: &impl Foo) {}
1899 fn foo(ar<|>g: &impl Foo) {} 1940"#,
1900 ", 1941 expect![[r#"
1901 &["&impl Foo"], 1942 [
1902 ); 1943 GoToType(
1903 assert_debug_snapshot!(actions, 1944 [
1904 @r###" 1945 HoverGotoTypeData {
1905 [ 1946 mod_path: "Foo",
1906 GoToType( 1947 nav: NavigationTarget {
1907 [ 1948 file_id: FileId(
1908 HoverGotoTypeData { 1949 1,
1909 mod_path: "Foo", 1950 ),
1910 nav: NavigationTarget { 1951 full_range: 0..12,
1911 file_id: FileId( 1952 name: "Foo",
1912 1, 1953 kind: TRAIT_DEF,
1913 ), 1954 focus_range: Some(
1914 full_range: 0..12, 1955 6..9,
1915 name: "Foo", 1956 ),
1916 kind: TRAIT_DEF, 1957 container_name: None,
1917 focus_range: Some( 1958 description: Some(
1918 6..9, 1959 "trait Foo",
1919 ), 1960 ),
1920 container_name: None, 1961 docs: None,
1921 description: Some( 1962 },
1922 "trait Foo",
1923 ),
1924 docs: None,
1925 }, 1963 },
1926 }, 1964 ],
1927 ], 1965 ),
1928 ), 1966 ]
1929 ] 1967 "#]],
1930 "###); 1968 );
1931 } 1969 }
1932 1970
1933 #[test] 1971 #[test]
1934 fn test_hover_arg_impl_traits_has_goto_type_action() { 1972 fn test_hover_arg_impl_traits_has_goto_type_action() {
1935 let (_, actions) = check_hover_result( 1973 check_actions(
1936 r" 1974 r#"
1937 //- /lib.rs 1975trait Foo {}
1938 trait Foo {} 1976trait Bar<T> {}
1939 trait Bar<T> {} 1977struct S{}
1940 struct S{} 1978
1941 1979fn foo(ar<|>g: &impl Foo + Bar<S>) {}
1942 fn foo(ar<|>g: &impl Foo + Bar<S>) {} 1980"#,
1943 ", 1981 expect![[r#"
1944 &["&impl Foo + Bar<S>"], 1982 [
1945 ); 1983 GoToType(
1946 assert_debug_snapshot!(actions, 1984 [
1947 @r###" 1985 HoverGotoTypeData {
1948 [ 1986 mod_path: "Foo",
1949 GoToType( 1987 nav: NavigationTarget {
1950 [ 1988 file_id: FileId(
1951 HoverGotoTypeData { 1989 1,
1952 mod_path: "Foo", 1990 ),
1953 nav: NavigationTarget { 1991 full_range: 0..12,
1954 file_id: FileId( 1992 name: "Foo",
1955 1, 1993 kind: TRAIT_DEF,
1956 ), 1994 focus_range: Some(
1957 full_range: 0..12, 1995 6..9,
1958 name: "Foo", 1996 ),
1959 kind: TRAIT_DEF, 1997 container_name: None,
1960 focus_range: Some( 1998 description: Some(
1961 6..9, 1999 "trait Foo",
1962 ), 2000 ),
1963 container_name: None, 2001 docs: None,
1964 description: Some( 2002 },
1965 "trait Foo",
1966 ),
1967 docs: None,
1968 }, 2003 },
1969 }, 2004 HoverGotoTypeData {
1970 HoverGotoTypeData { 2005 mod_path: "Bar",
1971 mod_path: "Bar", 2006 nav: NavigationTarget {
1972 nav: NavigationTarget { 2007 file_id: FileId(
1973 file_id: FileId( 2008 1,
1974 1, 2009 ),
1975 ), 2010 full_range: 13..28,
1976 full_range: 13..28, 2011 name: "Bar",
1977 name: "Bar", 2012 kind: TRAIT_DEF,
1978 kind: TRAIT_DEF, 2013 focus_range: Some(
1979 focus_range: Some( 2014 19..22,
1980 19..22, 2015 ),
1981 ), 2016 container_name: None,
1982 container_name: None, 2017 description: Some(
1983 description: Some( 2018 "trait Bar",
1984 "trait Bar", 2019 ),
1985 ), 2020 docs: None,
1986 docs: None, 2021 },
1987 }, 2022 },
1988 }, 2023 HoverGotoTypeData {
1989 HoverGotoTypeData { 2024 mod_path: "S",
1990 mod_path: "S", 2025 nav: NavigationTarget {
1991 nav: NavigationTarget { 2026 file_id: FileId(
1992 file_id: FileId( 2027 1,
1993 1, 2028 ),
1994 ), 2029 full_range: 29..39,
1995 full_range: 29..39, 2030 name: "S",
1996 name: "S", 2031 kind: STRUCT_DEF,
1997 kind: STRUCT_DEF, 2032 focus_range: Some(
1998 focus_range: Some( 2033 36..37,
1999 36..37, 2034 ),
2000 ), 2035 container_name: None,
2001 container_name: None, 2036 description: Some(
2002 description: Some( 2037 "struct S",
2003 "struct S", 2038 ),
2004 ), 2039 docs: None,
2005 docs: None, 2040 },
2006 }, 2041 },
2007 }, 2042 ],
2008 ], 2043 ),
2009 ), 2044 ]
2010 ] 2045 "#]],
2011 "###); 2046 );
2012 } 2047 }
2013 2048
2014 #[test] 2049 #[test]
2015 fn test_hover_arg_generic_impl_trait_has_goto_type_action() { 2050 fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
2016 let (_, actions) = check_hover_result( 2051 check_actions(
2017 r" 2052 r#"
2018 //- /lib.rs 2053trait Foo<T> {}
2019 trait Foo<T> {} 2054struct S {}
2020 struct S {} 2055fn foo(ar<|>g: &impl Foo<S>) {}
2021 fn foo(ar<|>g: &impl Foo<S>) {} 2056"#,
2022 ", 2057 expect![[r#"
2023 &["&impl Foo<S>"], 2058 [
2024 ); 2059 GoToType(
2025 assert_debug_snapshot!(actions, 2060 [
2026 @r###" 2061 HoverGotoTypeData {
2027 [ 2062 mod_path: "Foo",
2028 GoToType( 2063 nav: NavigationTarget {
2029 [ 2064 file_id: FileId(
2030 HoverGotoTypeData { 2065 1,
2031 mod_path: "Foo", 2066 ),
2032 nav: NavigationTarget { 2067 full_range: 0..15,
2033 file_id: FileId( 2068 name: "Foo",
2034 1, 2069 kind: TRAIT_DEF,
2035 ), 2070 focus_range: Some(
2036 full_range: 0..15, 2071 6..9,
2037 name: "Foo", 2072 ),
2038 kind: TRAIT_DEF, 2073 container_name: None,
2039 focus_range: Some( 2074 description: Some(
2040 6..9, 2075 "trait Foo",
2041 ), 2076 ),
2042 container_name: None, 2077 docs: None,
2043 description: Some( 2078 },
2044 "trait Foo",
2045 ),
2046 docs: None,
2047 }, 2079 },
2048 }, 2080 HoverGotoTypeData {
2049 HoverGotoTypeData { 2081 mod_path: "S",
2050 mod_path: "S", 2082 nav: NavigationTarget {
2051 nav: NavigationTarget { 2083 file_id: FileId(
2052 file_id: FileId( 2084 1,
2053 1, 2085 ),
2054 ), 2086 full_range: 16..27,
2055 full_range: 16..27, 2087 name: "S",
2056 name: "S", 2088 kind: STRUCT_DEF,
2057 kind: STRUCT_DEF, 2089 focus_range: Some(
2058 focus_range: Some( 2090 23..24,
2059 23..24, 2091 ),
2060 ), 2092 container_name: None,
2061 container_name: None, 2093 description: Some(
2062 description: Some( 2094 "struct S",
2063 "struct S", 2095 ),
2064 ), 2096 docs: None,
2065 docs: None, 2097 },
2066 }, 2098 },
2067 }, 2099 ],
2068 ], 2100 ),
2069 ), 2101 ]
2070 ] 2102 "#]],
2071 "###); 2103 );
2072 } 2104 }
2073 2105
2074 #[test] 2106 #[test]
2075 fn test_hover_dyn_return_has_goto_type_action() { 2107 fn test_hover_dyn_return_has_goto_type_action() {
2076 let (_, actions) = check_hover_result( 2108 check_actions(
2077 r" 2109 r#"
2078 //- /main.rs 2110trait Foo {}
2079 trait Foo {} 2111struct S;
2080 struct S; 2112impl Foo for S {}
2081 impl Foo for S {}
2082
2083 struct B<T>{}
2084 2113
2085 fn foo() -> B<dyn Foo> {} 2114struct B<T>{}
2115fn foo() -> B<dyn Foo> {}
2086 2116
2087 fn main() { 2117fn main() { let s<|>t = foo(); }
2088 let s<|>t = foo(); 2118"#,
2089 } 2119 expect![[r#"
2090 ",
2091 &["B<dyn Foo>"],
2092 );
2093 assert_debug_snapshot!(actions,
2094 @r###"
2095 [
2096 GoToType(
2097 [ 2120 [
2098 HoverGotoTypeData { 2121 GoToType(
2099 mod_path: "B", 2122 [
2100 nav: NavigationTarget { 2123 HoverGotoTypeData {
2101 file_id: FileId( 2124 mod_path: "B",
2102 1, 2125 nav: NavigationTarget {
2103 ), 2126 file_id: FileId(
2104 full_range: 42..55, 2127 1,
2105 name: "B", 2128 ),
2106 kind: STRUCT_DEF, 2129 full_range: 42..55,
2107 focus_range: Some( 2130 name: "B",
2108 49..50, 2131 kind: STRUCT_DEF,
2109 ), 2132 focus_range: Some(
2110 container_name: None, 2133 49..50,
2111 description: Some( 2134 ),
2112 "struct B", 2135 container_name: None,
2113 ), 2136 description: Some(
2114 docs: None, 2137 "struct B",
2115 }, 2138 ),
2116 }, 2139 docs: None,
2117 HoverGotoTypeData { 2140 },
2118 mod_path: "Foo", 2141 },
2119 nav: NavigationTarget { 2142 HoverGotoTypeData {
2120 file_id: FileId( 2143 mod_path: "Foo",
2121 1, 2144 nav: NavigationTarget {
2122 ), 2145 file_id: FileId(
2123 full_range: 0..12, 2146 1,
2124 name: "Foo", 2147 ),
2125 kind: TRAIT_DEF, 2148 full_range: 0..12,
2126 focus_range: Some( 2149 name: "Foo",
2127 6..9, 2150 kind: TRAIT_DEF,
2128 ), 2151 focus_range: Some(
2129 container_name: None, 2152 6..9,
2130 description: Some( 2153 ),
2131 "trait Foo", 2154 container_name: None,
2132 ), 2155 description: Some(
2133 docs: None, 2156 "trait Foo",
2134 }, 2157 ),
2135 }, 2158 docs: None,
2136 ], 2159 },
2137 ), 2160 },
2138 ] 2161 ],
2139 "###); 2162 ),
2163 ]
2164 "#]],
2165 );
2140 } 2166 }
2141 2167
2142 #[test] 2168 #[test]
2143 fn test_hover_dyn_arg_has_goto_type_action() { 2169 fn test_hover_dyn_arg_has_goto_type_action() {
2144 let (_, actions) = check_hover_result( 2170 check_actions(
2145 r" 2171 r#"
2146 //- /lib.rs 2172trait Foo {}
2147 trait Foo {} 2173fn foo(ar<|>g: &dyn Foo) {}
2148 fn foo(ar<|>g: &dyn Foo) {} 2174"#,
2149 ", 2175 expect![[r#"
2150 &["&dyn Foo"], 2176 [
2151 ); 2177 GoToType(
2152 assert_debug_snapshot!(actions, 2178 [
2153 @r###" 2179 HoverGotoTypeData {
2154 [ 2180 mod_path: "Foo",
2155 GoToType( 2181 nav: NavigationTarget {
2156 [ 2182 file_id: FileId(
2157 HoverGotoTypeData { 2183 1,
2158 mod_path: "Foo", 2184 ),
2159 nav: NavigationTarget { 2185 full_range: 0..12,
2160 file_id: FileId( 2186 name: "Foo",
2161 1, 2187 kind: TRAIT_DEF,
2162 ), 2188 focus_range: Some(
2163 full_range: 0..12, 2189 6..9,
2164 name: "Foo", 2190 ),
2165 kind: TRAIT_DEF, 2191 container_name: None,
2166 focus_range: Some( 2192 description: Some(
2167 6..9, 2193 "trait Foo",
2168 ), 2194 ),
2169 container_name: None, 2195 docs: None,
2170 description: Some( 2196 },
2171 "trait Foo",
2172 ),
2173 docs: None,
2174 }, 2197 },
2175 }, 2198 ],
2176 ], 2199 ),
2177 ), 2200 ]
2178 ] 2201 "#]],
2179 "###); 2202 );
2180 } 2203 }
2181 2204
2182 #[test] 2205 #[test]
2183 fn test_hover_generic_dyn_arg_has_goto_type_action() { 2206 fn test_hover_generic_dyn_arg_has_goto_type_action() {
2184 let (_, actions) = check_hover_result( 2207 check_actions(
2185 r" 2208 r#"
2186 //- /lib.rs 2209trait Foo<T> {}
2187 trait Foo<T> {} 2210struct S {}
2188 struct S {} 2211fn foo(ar<|>g: &dyn Foo<S>) {}
2189 fn foo(ar<|>g: &dyn Foo<S>) {} 2212"#,
2190 ", 2213 expect![[r#"
2191 &["&dyn Foo<S>"], 2214 [
2192 ); 2215 GoToType(
2193 assert_debug_snapshot!(actions, 2216 [
2194 @r###" 2217 HoverGotoTypeData {
2195 [ 2218 mod_path: "Foo",
2196 GoToType( 2219 nav: NavigationTarget {
2197 [ 2220 file_id: FileId(
2198 HoverGotoTypeData { 2221 1,
2199 mod_path: "Foo", 2222 ),
2200 nav: NavigationTarget { 2223 full_range: 0..15,
2201 file_id: FileId( 2224 name: "Foo",
2202 1, 2225 kind: TRAIT_DEF,
2203 ), 2226 focus_range: Some(
2204 full_range: 0..15, 2227 6..9,
2205 name: "Foo", 2228 ),
2206 kind: TRAIT_DEF, 2229 container_name: None,
2207 focus_range: Some( 2230 description: Some(
2208 6..9, 2231 "trait Foo",
2209 ), 2232 ),
2210 container_name: None, 2233 docs: None,
2211 description: Some( 2234 },
2212 "trait Foo",
2213 ),
2214 docs: None,
2215 }, 2235 },
2216 }, 2236 HoverGotoTypeData {
2217 HoverGotoTypeData { 2237 mod_path: "S",
2218 mod_path: "S", 2238 nav: NavigationTarget {
2219 nav: NavigationTarget { 2239 file_id: FileId(
2220 file_id: FileId( 2240 1,
2221 1, 2241 ),
2222 ), 2242 full_range: 16..27,
2223 full_range: 16..27, 2243 name: "S",
2224 name: "S", 2244 kind: STRUCT_DEF,
2225 kind: STRUCT_DEF, 2245 focus_range: Some(
2226 focus_range: Some( 2246 23..24,
2227 23..24, 2247 ),
2228 ), 2248 container_name: None,
2229 container_name: None, 2249 description: Some(
2230 description: Some( 2250 "struct S",
2231 "struct S", 2251 ),
2232 ), 2252 docs: None,
2233 docs: None, 2253 },
2234 }, 2254 },
2235 }, 2255 ],
2236 ], 2256 ),
2237 ), 2257 ]
2238 ] 2258 "#]],
2239 "###); 2259 );
2240 } 2260 }
2241 2261
2242 #[test] 2262 #[test]
2243 fn test_hover_goto_type_action_links_order() { 2263 fn test_hover_goto_type_action_links_order() {
2244 let (_, actions) = check_hover_result( 2264 check_actions(
2245 r" 2265 r#"
2246 //- /lib.rs 2266trait ImplTrait<T> {}
2247 trait ImplTrait<T> {} 2267trait DynTrait<T> {}
2248 trait DynTrait<T> {} 2268struct B<T> {}
2249 struct B<T> {} 2269struct S {}
2250 struct S {} 2270
2251 2271fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
2252 fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {} 2272 "#,
2253 ", 2273 expect![[r#"
2254 &["&impl ImplTrait<B<dyn DynTrait<B<S>>>>"], 2274 [
2255 ); 2275 GoToType(
2256 assert_debug_snapshot!(actions, 2276 [
2257 @r###" 2277 HoverGotoTypeData {
2258 [ 2278 mod_path: "ImplTrait",
2259 GoToType( 2279 nav: NavigationTarget {
2260 [ 2280 file_id: FileId(
2261 HoverGotoTypeData { 2281 1,
2262 mod_path: "ImplTrait", 2282 ),
2263 nav: NavigationTarget { 2283 full_range: 0..21,
2264 file_id: FileId( 2284 name: "ImplTrait",
2265 1, 2285 kind: TRAIT_DEF,
2266 ), 2286 focus_range: Some(
2267 full_range: 0..21, 2287 6..15,
2268 name: "ImplTrait", 2288 ),
2269 kind: TRAIT_DEF, 2289 container_name: None,
2270 focus_range: Some( 2290 description: Some(
2271 6..15, 2291 "trait ImplTrait",
2272 ), 2292 ),
2273 container_name: None, 2293 docs: None,
2274 description: Some( 2294 },
2275 "trait ImplTrait",
2276 ),
2277 docs: None,
2278 }, 2295 },
2279 }, 2296 HoverGotoTypeData {
2280 HoverGotoTypeData { 2297 mod_path: "B",
2281 mod_path: "B", 2298 nav: NavigationTarget {
2282 nav: NavigationTarget { 2299 file_id: FileId(
2283 file_id: FileId( 2300 1,
2284 1, 2301 ),
2285 ), 2302 full_range: 43..57,
2286 full_range: 43..57, 2303 name: "B",
2287 name: "B", 2304 kind: STRUCT_DEF,
2288 kind: STRUCT_DEF, 2305 focus_range: Some(
2289 focus_range: Some( 2306 50..51,
2290 50..51, 2307 ),
2291 ), 2308 container_name: None,
2292 container_name: None, 2309 description: Some(
2293 description: Some( 2310 "struct B",
2294 "struct B", 2311 ),
2295 ), 2312 docs: None,
2296 docs: None, 2313 },
2297 }, 2314 },
2298 }, 2315 HoverGotoTypeData {
2299 HoverGotoTypeData { 2316 mod_path: "DynTrait",
2300 mod_path: "DynTrait", 2317 nav: NavigationTarget {
2301 nav: NavigationTarget { 2318 file_id: FileId(
2302 file_id: FileId( 2319 1,
2303 1, 2320 ),
2304 ), 2321 full_range: 22..42,
2305 full_range: 22..42, 2322 name: "DynTrait",
2306 name: "DynTrait", 2323 kind: TRAIT_DEF,
2307 kind: TRAIT_DEF, 2324 focus_range: Some(
2308 focus_range: Some( 2325 28..36,
2309 28..36, 2326 ),
2310 ), 2327 container_name: None,
2311 container_name: None, 2328 description: Some(
2312 description: Some( 2329 "trait DynTrait",
2313 "trait DynTrait", 2330 ),
2314 ), 2331 docs: None,
2315 docs: None, 2332 },
2316 }, 2333 },
2317 }, 2334 HoverGotoTypeData {
2318 HoverGotoTypeData { 2335 mod_path: "S",
2319 mod_path: "S", 2336 nav: NavigationTarget {
2320 nav: NavigationTarget { 2337 file_id: FileId(
2321 file_id: FileId( 2338 1,
2322 1, 2339 ),
2323 ), 2340 full_range: 58..69,
2324 full_range: 58..69, 2341 name: "S",
2325 name: "S", 2342 kind: STRUCT_DEF,
2326 kind: STRUCT_DEF, 2343 focus_range: Some(
2327 focus_range: Some( 2344 65..66,
2328 65..66, 2345 ),
2329 ), 2346 container_name: None,
2330 container_name: None, 2347 description: Some(
2331 description: Some( 2348 "struct S",
2332 "struct S", 2349 ),
2333 ), 2350 docs: None,
2334 docs: None, 2351 },
2335 }, 2352 },
2336 }, 2353 ],
2337 ], 2354 ),
2338 ), 2355 ]
2339 ] 2356 "#]],
2340 "###); 2357 );
2341 } 2358 }
2342 2359
2343 #[test] 2360 #[test]
2344 fn test_hover_associated_type_has_goto_type_action() { 2361 fn test_hover_associated_type_has_goto_type_action() {
2345 let (_, actions) = check_hover_result( 2362 check_actions(
2346 r" 2363 r#"
2347 //- /main.rs 2364trait Foo {
2348 trait Foo { 2365 type Item;
2349 type Item; 2366 fn get(self) -> Self::Item {}
2350 fn get(self) -> Self::Item {} 2367}
2351 }
2352 2368
2353 struct Bar{} 2369struct Bar{}
2354 struct S{} 2370struct S{}
2355 2371
2356 impl Foo for S{ 2372impl Foo for S { type Item = Bar; }
2357 type Item = Bar;
2358 }
2359 2373
2360 fn test() -> impl Foo { 2374fn test() -> impl Foo { S {} }
2361 S{}
2362 }
2363 2375
2364 fn main() { 2376fn main() { let s<|>t = test().get(); }
2365 let s<|>t = test().get(); 2377"#,
2366 } 2378 expect![[r#"
2367 ", 2379 [
2368 &["Foo::Item<impl Foo>"], 2380 GoToType(
2369 ); 2381 [
2370 assert_debug_snapshot!(actions, 2382 HoverGotoTypeData {
2371 @r###" 2383 mod_path: "Foo",
2372 [ 2384 nav: NavigationTarget {
2373 GoToType( 2385 file_id: FileId(
2374 [ 2386 1,
2375 HoverGotoTypeData { 2387 ),
2376 mod_path: "Foo", 2388 full_range: 0..62,
2377 nav: NavigationTarget { 2389 name: "Foo",
2378 file_id: FileId( 2390 kind: TRAIT_DEF,
2379 1, 2391 focus_range: Some(
2380 ), 2392 6..9,
2381 full_range: 0..62, 2393 ),
2382 name: "Foo", 2394 container_name: None,
2383 kind: TRAIT_DEF, 2395 description: Some(
2384 focus_range: Some( 2396 "trait Foo",
2385 6..9, 2397 ),
2386 ), 2398 docs: None,
2387 container_name: None, 2399 },
2388 description: Some(
2389 "trait Foo",
2390 ),
2391 docs: None,
2392 }, 2400 },
2393 }, 2401 ],
2394 ], 2402 ),
2395 ), 2403 ]
2396 ] 2404 "#]],
2397 "###); 2405 );
2398 } 2406 }
2399} 2407}
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index dcfa186dc..6a4f5cb3d 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -17,6 +17,7 @@ macro_rules! eprintln {
17 17
18pub mod mock_analysis; 18pub mod mock_analysis;
19 19
20mod markup;
20mod prime_caches; 21mod prime_caches;
21mod status; 22mod status;
22mod completion; 23mod completion;
@@ -68,6 +69,7 @@ pub use crate::{
68 folding_ranges::{Fold, FoldKind}, 69 folding_ranges::{Fold, FoldKind},
69 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, 70 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
70 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, 71 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
72 markup::Markup,
71 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, 73 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
72 runnables::{Runnable, RunnableKind, TestId}, 74 runnables::{Runnable, RunnableKind, TestId},
73 syntax_highlighting::{ 75 syntax_highlighting::{
diff --git a/crates/ra_ide/src/markup.rs b/crates/ra_ide/src/markup.rs
new file mode 100644
index 000000000..2f2b3cc25
--- /dev/null
+++ b/crates/ra_ide/src/markup.rs
@@ -0,0 +1,38 @@
1//! Markdown formatting.
2//!
3//! Sometimes, we want to display a "rich text" in the UI. At the moment, we use
4//! markdown for this purpose. It doesn't feel like a right option, but that's
5//! what is used by LSP, so let's keep it simple.
6use std::fmt;
7
8#[derive(Default, Debug)]
9pub struct Markup {
10 text: String,
11}
12
13impl From<Markup> for String {
14 fn from(markup: Markup) -> Self {
15 markup.text
16 }
17}
18
19impl fmt::Display for Markup {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 fmt::Display::fmt(&self.text, f)
22 }
23}
24
25impl Markup {
26 pub fn as_str(&self) -> &str {
27 self.text.as_str()
28 }
29 pub fn is_empty(&self) -> bool {
30 self.text.is_empty()
31 }
32 pub fn push_section(&mut self, section: &str) {
33 if !self.text.is_empty() {
34 self.text.push_str("\n\n___\n");
35 }
36 self.text.push_str(section);
37 }
38}