diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/hover.rs | 3228 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/markup.rs | 38 |
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 | }; |
13 | use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; | 13 | use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; |
14 | 14 | ||
15 | use crate::{ | 15 | use 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)] |
70 | pub struct HoverResult { | 71 | pub struct HoverResult { |
71 | results: Vec<String>, | 72 | pub markup: Markup, |
72 | actions: Vec<HoverAction>, | 73 | pub actions: Vec<HoverAction>, |
73 | } | 74 | } |
74 | 75 | ||
75 | impl HoverResult { | 76 | impl 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)] |
385 | mod tests { | 371 | mod 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#" |
433 | pub fn foo() -> u32 { 1 } | 405 | pub 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 | 424 | struct Scan<A, B, C> { a: A, b: B, c: C } |
450 | struct Scan<A, B, C> { | 425 | struct Iter<I> { inner: I } |
451 | a: A, | 426 | enum Option<T> { Some(T), None } |
452 | b: B, | ||
453 | c: C, | ||
454 | } | ||
455 | 427 | ||
456 | struct FakeIter<I> { | 428 | struct OtherStruct<T> { i: T } |
457 | inner: I, | ||
458 | } | ||
459 | |||
460 | struct OtherStruct<T> { | ||
461 | i: T, | ||
462 | } | ||
463 | 429 | ||
464 | enum FakeOption<T> { | 430 | fn 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() { | 434 | fn 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 | 457 | pub fn foo() -> u32 { 1 } |
492 | pub fn foo() -> u32 { 1 } | ||
493 | 458 | ||
494 | fn main() { | 459 | fn 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 } | 473 | pub fn foo() -> u32 { 1 } |
506 | 474 | ||
507 | //- /b.rs | 475 | //- /b.rs |
508 | pub fn foo() -> &str { "" } | 476 | pub fn foo() -> &str { "" } |
509 | 477 | ||
510 | //- /c.rs | 478 | //- /c.rs |
511 | pub fn foo(a: u32, b: u32) {} | 479 | pub fn foo(a: u32, b: u32) {} |
512 | 480 | ||
513 | //- /main.rs | 481 | //- /main.rs |
514 | mod a; | 482 | mod a; |
515 | mod b; | 483 | mod b; |
516 | mod c; | 484 | mod c; |
517 | 485 | ||
518 | fn main() { | 486 | fn 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 | 501 | pub 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() { | 503 | fn 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 | 518 | pub fn foo<|>(a: u32, b: u32) -> u32 {} |
546 | pub fn foo<|>(a: u32, b: u32) -> u32 {} | ||
547 | 519 | ||
548 | fn main() { | 520 | fn 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 | 536 | struct Foo { field_a: u32 } |
561 | struct Foo { | ||
562 | field_a: u32, | ||
563 | } | ||
564 | 537 | ||
565 | fn main() { | 538 | fn 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 | 557 | struct Foo { field_a<|>: u32 } |
578 | struct Foo { | ||
579 | field_a<|>: u32, | ||
580 | } | ||
581 | 558 | ||
582 | fn main() { | 559 | fn 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 | 602 | struct Test<K, T = u8> { k: K, t: T } |
616 | struct Test<K, T = u8> { | ||
617 | k: K, | ||
618 | t: T, | ||
619 | } | ||
620 | 603 | ||
621 | fn main() { | 604 | fn 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) } | 620 | enum Option<T> { Some(T) } |
633 | use Option::Some; | 621 | use Option::Some; |
634 | 622 | ||
635 | fn main() { | 623 | fn 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) } | 639 | enum Option<T> { Some(T) } |
646 | use Option::Some; | 640 | use Option::Some; |
647 | 641 | ||
648 | fn main() { | 642 | fn 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 | 657 | enum 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: |
668 | Option | 664 | ```rust |
669 | ``` | 665 | Option |
666 | ``` | ||
670 | 667 | ||
671 | ```rust | 668 | ```rust |
672 | None | 669 | None |
673 | ``` | 670 | ``` |
674 | ___ | 671 | ___ |
675 | 672 | ||
676 | The 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 | 679 | enum Option<T> { |
684 | enum Option<T> { | 680 | /// The Some variant |
685 | /// The Some variant | 681 | Some(T) |
686 | Some(T) | 682 | } |
687 | } | 683 | fn 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: |
693 | Option | 689 | ```rust |
694 | ``` | 690 | Option |
691 | ``` | ||
695 | 692 | ||
696 | ```rust | 693 | ```rust |
697 | Some | 694 | Some |
698 | ``` | 695 | ``` |
699 | ___ | 696 | ___ |
700 | 697 | ||
701 | The 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; }; }"#, |
725 | fn 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 } | 759 | struct Thing { x: u32 } |
744 | 760 | ||
745 | impl Thing { | 761 | impl Thing { |
746 | fn new() -> Thing { | 762 | fn new() -> Thing { Thing { x: 0 } } |
747 | Thing { x: 0 } | 763 | } |
748 | } | ||
749 | } | ||
750 | 764 | ||
751 | fn main() { | 765 | fn 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 { | 780 | mod 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() { | 788 | fn 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; | 807 | struct X; |
791 | impl X { | 808 | impl X { |
792 | const C: u32 = 1; | 809 | const C: u32 = 1; |
793 | } | 810 | } |
794 | 811 | ||
795 | fn main() { | 812 | fn 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 } | 833 | struct Thing { x: u32 } |
813 | impl Thing { | 834 | impl 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() {} | 890 | fn x() {} |
870 | 891 | ||
871 | fn y() { | 892 | fn 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 { | 910 | macro_rules! foo { () => {} } |
886 | () => {} | ||
887 | } | ||
888 | 911 | ||
889 | fn f() { | 912 | fn 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 | 938 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } |
914 | macro_rules! id { | 939 | fn foo() {} |
915 | ($($tt:tt)*) => { $($tt)* } | 940 | id! { |
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 | 957 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } |
935 | macro_rules! id { | 958 | fn 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 | 973 | macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } |
953 | macro_rules! id_deep { | 974 | macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } |
954 | ($($tt:tt)*) => { $($tt)* } | 975 | fn 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 | 990 | macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } |
974 | macro_rules! id_deep { | 991 | macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } |
975 | ($($tt:tt)*) => { $($tt)* } | 992 | fn bar() -> u32 { 0 } |
976 | } | 993 | fn 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 | 1008 | macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } } |
998 | macro_rules! arr { | 1009 | fn 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] | 1028 | macro_rules! assert {} |
1018 | macro_rules! assert {} | ||
1019 | 1029 | ||
1020 | fn bar() -> bool { true } | 1030 | fn bar() -> bool { true } |
1021 | fn foo() { | 1031 | fn 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 | 1063 | fn foo() { } |
1052 | fn foo() { | ||
1053 | } | ||
1054 | 1064 | ||
1055 | fn bar() { | 1065 | fn 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 | 1133 | use self::m<|>y::Bar; |
1105 | use self::m<|>y::Bar; | 1134 | mod my { pub struct Bar; } |
1106 | |||
1107 | mod my { | ||
1108 | pub struct Bar; | ||
1109 | } | ||
1110 | 1135 | ||
1111 | fn my() {} | 1136 | fn 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 | 1152 | struct Bar; |
1123 | struct Bar; | ||
1124 | 1153 | ||
1125 | fn foo() { | 1154 | fn 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"] | 1173 | struct Bar; |
1139 | struct Bar; | ||
1140 | 1174 | ||
1141 | fn foo() { | 1175 | fn 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"] | 1196 | struct Bar; |
1157 | struct Bar; | ||
1158 | 1197 | ||
1159 | fn foo() { | 1198 | fn 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 | 1222 | macro_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!(); | 1232 | bar!(); |
1185 | 1233 | ||
1186 | fn foo() { | 1234 | fn 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 | 1258 | macro_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!(); | 1268 | bar!(); |
1213 | 1269 | ||
1214 | fn foo() { | 1270 | fn 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 } | 1369 | fn 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 | 1409 | mod 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 | 1447 | struct S{ f1: u32 } |
1470 | struct Arg(u32); | 1448 | |
1471 | struct S<T>{ f1: T } | 1449 | fn 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", | 1485 | struct Arg(u32); |
1486 | nav: NavigationTarget { | 1486 | struct S<T>{ f1: T } |
1487 | file_id: FileId( | 1487 | |
1488 | 1, | 1488 | fn 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 | 1543 | struct Arg(u32); |
1533 | struct A(u32); | 1544 | struct S<T>{ f1: T } |
1534 | struct B(u32); | ||
1535 | mod M { | ||
1536 | pub struct C(u32); | ||
1537 | } | ||
1538 | 1545 | ||
1539 | fn main() { | 1546 | fn 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", | 1601 | struct A(u32); |
1552 | nav: NavigationTarget { | 1602 | struct B(u32); |
1553 | file_id: FileId( | 1603 | mod M { |
1554 | 1, | 1604 | pub struct C(u32); |
1555 | ), | 1605 | } |
1556 | full_range: 0..14, | 1606 | |
1557 | name: "A", | 1607 | fn 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 | 1681 | trait Foo {} |
1618 | trait Foo {} | 1682 | fn foo() -> impl Foo {} |
1619 | |||
1620 | fn foo() -> impl Foo {} | ||
1621 | 1683 | ||
1622 | fn main() { | 1684 | fn 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 | 1720 | trait Foo<T> {} |
1663 | trait Foo<T> {} | 1721 | struct S; |
1664 | struct S; | 1722 | fn foo() -> impl Foo<S> {} |
1665 | |||
1666 | fn foo() -> impl Foo<S> {} | ||
1667 | 1723 | ||
1668 | fn main() { | 1724 | fn 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 | 1779 | trait Foo {} |
1728 | trait Foo {} | 1780 | trait Bar {} |
1729 | trait Bar {} | 1781 | fn foo() -> impl Foo + Bar {} |
1730 | |||
1731 | fn foo() -> impl Foo + Bar {} | ||
1732 | 1782 | ||
1733 | fn main() { | 1783 | fn 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 | 1838 | trait Foo<T> {} |
1793 | trait Foo<T> {} | 1839 | trait Bar<T> {} |
1794 | trait Bar<T> {} | 1840 | struct S1 {} |
1795 | struct S1 {} | 1841 | struct S2 {} |
1796 | struct S2 {} | 1842 | |
1797 | 1843 | fn foo() -> impl Foo<S1> + Bar<S2> {} | |
1798 | fn foo() -> impl Foo<S1> + Bar<S2> {} | 1844 | |
1799 | 1845 | fn 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 | 1938 | trait Foo {} |
1898 | trait Foo {} | 1939 | fn 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 | 1975 | trait Foo {} |
1938 | trait Foo {} | 1976 | trait Bar<T> {} |
1939 | trait Bar<T> {} | 1977 | struct S{} |
1940 | struct S{} | 1978 | |
1941 | 1979 | fn 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 | 2053 | trait Foo<T> {} |
2019 | trait Foo<T> {} | 2054 | struct S {} |
2020 | struct S {} | 2055 | fn 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 | 2110 | trait Foo {} |
2079 | trait Foo {} | 2111 | struct S; |
2080 | struct S; | 2112 | impl Foo for S {} |
2081 | impl Foo for S {} | ||
2082 | |||
2083 | struct B<T>{} | ||
2084 | 2113 | ||
2085 | fn foo() -> B<dyn Foo> {} | 2114 | struct B<T>{} |
2115 | fn foo() -> B<dyn Foo> {} | ||
2086 | 2116 | ||
2087 | fn main() { | 2117 | fn 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 | 2172 | trait Foo {} |
2147 | trait Foo {} | 2173 | fn 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 | 2209 | trait Foo<T> {} |
2187 | trait Foo<T> {} | 2210 | struct S {} |
2188 | struct S {} | 2211 | fn 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 | 2266 | trait ImplTrait<T> {} |
2247 | trait ImplTrait<T> {} | 2267 | trait DynTrait<T> {} |
2248 | trait DynTrait<T> {} | 2268 | struct B<T> {} |
2249 | struct B<T> {} | 2269 | struct S {} |
2250 | struct S {} | 2270 | |
2251 | 2271 | fn 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 | 2364 | trait 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{} | 2369 | struct Bar{} |
2354 | struct S{} | 2370 | struct S{} |
2355 | 2371 | ||
2356 | impl Foo for S{ | 2372 | impl Foo for S { type Item = Bar; } |
2357 | type Item = Bar; | ||
2358 | } | ||
2359 | 2373 | ||
2360 | fn test() -> impl Foo { | 2374 | fn test() -> impl Foo { S {} } |
2361 | S{} | ||
2362 | } | ||
2363 | 2375 | ||
2364 | fn main() { | 2376 | fn 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 | ||
18 | pub mod mock_analysis; | 18 | pub mod mock_analysis; |
19 | 19 | ||
20 | mod markup; | ||
20 | mod prime_caches; | 21 | mod prime_caches; |
21 | mod status; | 22 | mod status; |
22 | mod completion; | 23 | mod 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. | ||
6 | use std::fmt; | ||
7 | |||
8 | #[derive(Default, Debug)] | ||
9 | pub struct Markup { | ||
10 | text: String, | ||
11 | } | ||
12 | |||
13 | impl From<Markup> for String { | ||
14 | fn from(markup: Markup) -> Self { | ||
15 | markup.text | ||
16 | } | ||
17 | } | ||
18 | |||
19 | impl fmt::Display for Markup { | ||
20 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
21 | fmt::Display::fmt(&self.text, f) | ||
22 | } | ||
23 | } | ||
24 | |||
25 | impl 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 | } | ||