diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/hover.rs | 75 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/markup.rs | 38 |
3 files changed, 67 insertions, 48 deletions
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 61359c770..e469f4166 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -16,6 +16,7 @@ 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 | } |
@@ -406,19 +392,12 @@ mod tests { | |||
406 | fn check_hover_result(ra_fixture: &str, expected: &[&str]) -> (String, Vec<HoverAction>) { | 392 | fn check_hover_result(ra_fixture: &str, expected: &[&str]) -> (String, Vec<HoverAction>) { |
407 | let (analysis, position) = analysis_and_position(ra_fixture); | 393 | let (analysis, position) = analysis_and_position(ra_fixture); |
408 | let hover = analysis.hover(position).unwrap().unwrap(); | 394 | let hover = analysis.hover(position).unwrap().unwrap(); |
409 | let mut results = hover.info.results.clone(); | 395 | let expected = expected.join("\n\n___\n"); |
410 | results.sort(); | 396 | let actual = trim_markup(hover.info.markup.as_str()); |
411 | 397 | assert_eq!(expected, actual); | |
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 | 398 | ||
420 | let content = analysis.db.file_text(position.file_id); | 399 | let content = analysis.db.file_text(position.file_id); |
421 | (content[hover.range].to_string(), hover.info.actions().to_vec()) | 400 | (content[hover.range].to_string(), hover.info.actions.clone()) |
422 | } | 401 | } |
423 | 402 | ||
424 | fn check_hover_no_result(ra_fixture: &str) { | 403 | fn check_hover_no_result(ra_fixture: &str) { |
@@ -439,7 +418,7 @@ fn main() { | |||
439 | ); | 418 | ); |
440 | let hover = analysis.hover(position).unwrap().unwrap(); | 419 | let hover = analysis.hover(position).unwrap().unwrap(); |
441 | assert_eq!(hover.range, TextRange::new(58.into(), 63.into())); | 420 | assert_eq!(hover.range, TextRange::new(58.into(), 63.into())); |
442 | assert_eq!(trim_markup(&hover.info.results[0]), ("u32")); | 421 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("u32")); |
443 | } | 422 | } |
444 | 423 | ||
445 | #[test] | 424 | #[test] |
@@ -638,7 +617,7 @@ fn main() { | |||
638 | ", | 617 | ", |
639 | ); | 618 | ); |
640 | let hover = analysis.hover(position).unwrap().unwrap(); | 619 | let hover = analysis.hover(position).unwrap().unwrap(); |
641 | assert_eq!(trim_markup(&hover.info.results[0]), ("Option\n```\n\n```rust\nSome")); | 620 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Option\n```\n\n```rust\nSome")); |
642 | 621 | ||
643 | let (analysis, position) = analysis_and_position( | 622 | let (analysis, position) = analysis_and_position( |
644 | " | 623 | " |
@@ -651,7 +630,7 @@ fn main() { | |||
651 | ", | 630 | ", |
652 | ); | 631 | ); |
653 | let hover = analysis.hover(position).unwrap().unwrap(); | 632 | let hover = analysis.hover(position).unwrap().unwrap(); |
654 | assert_eq!(trim_markup(&hover.info.results[0]), ("Option<i32>")); | 633 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Option<i32>")); |
655 | } | 634 | } |
656 | 635 | ||
657 | #[test] | 636 | #[test] |
@@ -708,14 +687,14 @@ The Some variant | |||
708 | fn hover_for_local_variable() { | 687 | fn hover_for_local_variable() { |
709 | let (analysis, position) = analysis_and_position("fn func(foo: i32) { fo<|>o; }"); | 688 | let (analysis, position) = analysis_and_position("fn func(foo: i32) { fo<|>o; }"); |
710 | let hover = analysis.hover(position).unwrap().unwrap(); | 689 | let hover = analysis.hover(position).unwrap().unwrap(); |
711 | assert_eq!(trim_markup(&hover.info.results[0]), "i32"); | 690 | assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); |
712 | } | 691 | } |
713 | 692 | ||
714 | #[test] | 693 | #[test] |
715 | fn hover_for_local_variable_pat() { | 694 | fn hover_for_local_variable_pat() { |
716 | let (analysis, position) = analysis_and_position("fn func(fo<|>o: i32) {}"); | 695 | let (analysis, position) = analysis_and_position("fn func(fo<|>o: i32) {}"); |
717 | let hover = analysis.hover(position).unwrap().unwrap(); | 696 | let hover = analysis.hover(position).unwrap().unwrap(); |
718 | assert_eq!(trim_markup(&hover.info.results[0]), "i32"); | 697 | assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); |
719 | } | 698 | } |
720 | 699 | ||
721 | #[test] | 700 | #[test] |
@@ -726,14 +705,14 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
726 | ", | 705 | ", |
727 | ); | 706 | ); |
728 | let hover = analysis.hover(position).unwrap().unwrap(); | 707 | let hover = analysis.hover(position).unwrap().unwrap(); |
729 | assert_eq!(trim_markup(&hover.info.results[0]), "i32"); | 708 | assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); |
730 | } | 709 | } |
731 | 710 | ||
732 | #[test] | 711 | #[test] |
733 | fn hover_for_param_edge() { | 712 | fn hover_for_param_edge() { |
734 | let (analysis, position) = analysis_and_position("fn func(<|>foo: i32) {}"); | 713 | let (analysis, position) = analysis_and_position("fn func(<|>foo: i32) {}"); |
735 | let hover = analysis.hover(position).unwrap().unwrap(); | 714 | let hover = analysis.hover(position).unwrap().unwrap(); |
736 | assert_eq!(trim_markup(&hover.info.results[0]), "i32"); | 715 | assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); |
737 | } | 716 | } |
738 | 717 | ||
739 | #[test] | 718 | #[test] |
@@ -754,7 +733,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
754 | ", | 733 | ", |
755 | ); | 734 | ); |
756 | let hover = analysis.hover(position).unwrap().unwrap(); | 735 | let hover = analysis.hover(position).unwrap().unwrap(); |
757 | assert_eq!(trim_markup(&hover.info.results[0]), ("Thing")); | 736 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); |
758 | } | 737 | } |
759 | 738 | ||
760 | #[test] | 739 | #[test] |
@@ -778,7 +757,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
778 | ); | 757 | ); |
779 | let hover = analysis.hover(position).unwrap().unwrap(); | 758 | let hover = analysis.hover(position).unwrap().unwrap(); |
780 | assert_eq!( | 759 | assert_eq!( |
781 | trim_markup(&hover.info.results[0]), | 760 | trim_markup(&hover.info.markup.as_str()), |
782 | ("wrapper::Thing\n```\n\n```rust\nfn new() -> Thing") | 761 | ("wrapper::Thing\n```\n\n```rust\nfn new() -> Thing") |
783 | ); | 762 | ); |
784 | } | 763 | } |
@@ -802,7 +781,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
802 | ", | 781 | ", |
803 | ); | 782 | ); |
804 | let hover = analysis.hover(position).unwrap().unwrap(); | 783 | let hover = analysis.hover(position).unwrap().unwrap(); |
805 | assert_eq!(trim_markup(&hover.info.results[0]), ("const C: u32")); | 784 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("const C: u32")); |
806 | } | 785 | } |
807 | 786 | ||
808 | #[test] | 787 | #[test] |
@@ -818,7 +797,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
818 | ", | 797 | ", |
819 | ); | 798 | ); |
820 | let hover = analysis.hover(position).unwrap().unwrap(); | 799 | let hover = analysis.hover(position).unwrap().unwrap(); |
821 | assert_eq!(trim_markup(&hover.info.results[0]), ("Thing")); | 800 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); |
822 | 801 | ||
823 | /* FIXME: revive these tests | 802 | /* FIXME: revive these tests |
824 | let (analysis, position) = analysis_and_position( | 803 | let (analysis, position) = analysis_and_position( |
@@ -833,7 +812,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
833 | ); | 812 | ); |
834 | 813 | ||
835 | let hover = analysis.hover(position).unwrap().unwrap(); | 814 | let hover = analysis.hover(position).unwrap().unwrap(); |
836 | assert_eq!(trim_markup(&hover.info.results[0]), ("Thing")); | 815 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); |
837 | 816 | ||
838 | let (analysis, position) = analysis_and_position( | 817 | let (analysis, position) = analysis_and_position( |
839 | " | 818 | " |
@@ -846,7 +825,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
846 | ", | 825 | ", |
847 | ); | 826 | ); |
848 | let hover = analysis.hover(position).unwrap().unwrap(); | 827 | let hover = analysis.hover(position).unwrap().unwrap(); |
849 | assert_eq!(trim_markup(&hover.info.results[0]), ("enum Thing")); | 828 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); |
850 | 829 | ||
851 | let (analysis, position) = analysis_and_position( | 830 | let (analysis, position) = analysis_and_position( |
852 | " | 831 | " |
@@ -858,7 +837,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
858 | ", | 837 | ", |
859 | ); | 838 | ); |
860 | let hover = analysis.hover(position).unwrap().unwrap(); | 839 | let hover = analysis.hover(position).unwrap().unwrap(); |
861 | assert_eq!(trim_markup(&hover.info.results[0]), ("enum Thing")); | 840 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); |
862 | */ | 841 | */ |
863 | } | 842 | } |
864 | 843 | ||
@@ -875,7 +854,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
875 | ", | 854 | ", |
876 | ); | 855 | ); |
877 | let hover = analysis.hover(position).unwrap().unwrap(); | 856 | let hover = analysis.hover(position).unwrap().unwrap(); |
878 | assert_eq!(trim_markup(&hover.info.results[0]), "i32"); | 857 | assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); |
879 | } | 858 | } |
880 | 859 | ||
881 | #[test] | 860 | #[test] |
@@ -892,7 +871,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
892 | ", | 871 | ", |
893 | ); | 872 | ); |
894 | let hover = analysis.hover(position).unwrap().unwrap(); | 873 | let hover = analysis.hover(position).unwrap().unwrap(); |
895 | assert_eq!(trim_markup(&hover.info.results[0]), ("macro_rules! foo")); | 874 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("macro_rules! foo")); |
896 | } | 875 | } |
897 | 876 | ||
898 | #[test] | 877 | #[test] |
@@ -903,7 +882,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
903 | ", | 882 | ", |
904 | ); | 883 | ); |
905 | let hover = analysis.hover(position).unwrap().unwrap(); | 884 | let hover = analysis.hover(position).unwrap().unwrap(); |
906 | assert_eq!(trim_markup(&hover.info.results[0]), "i32"); | 885 | assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); |
907 | } | 886 | } |
908 | 887 | ||
909 | #[test] | 888 | #[test] |
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 | } | ||