aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_ide/src/hover.rs75
-rw-r--r--crates/ra_ide/src/lib.rs2
-rw-r--r--crates/ra_ide/src/markup.rs38
-rw-r--r--crates/rust-analyzer/src/handlers.rs15
-rw-r--r--crates/rust-analyzer/src/to_proto.rs8
5 files changed, 79 insertions, 59 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)]
70pub struct HoverResult { 71pub struct HoverResult {
71 results: Vec<String>, 72 pub markup: Markup,
72 actions: Vec<HoverAction>, 73 pub actions: Vec<HoverAction>,
73} 74}
74 75
75impl HoverResult { 76impl HoverResult {
@@ -78,22 +79,7 @@ impl HoverResult {
78 } 79 }
79 80
80 pub fn is_empty(&self) -> bool { 81 pub fn is_empty(&self) -> bool {
81 self.results.is_empty() 82 self.markup.is_empty()
82 }
83
84 pub fn len(&self) -> usize {
85 self.results.len()
86 }
87
88 pub fn actions(&self) -> &[HoverAction] {
89 &self.actions
90 }
91 /// Returns the results converted into markup
92 /// for displaying in a UI
93 ///
94 /// Does not process actions!
95 pub fn to_markup(&self) -> String {
96 self.results.join("\n\n___\n")
97 } 83 }
98 84
99 fn push_action(&mut self, action: HoverAction) { 85 fn push_action(&mut self, action: HoverAction) {
@@ -128,7 +114,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
128 if let Some(definition) = definition { 114 if let Some(definition) = definition {
129 let range = sema.original_range(&node).range; 115 let range = sema.original_range(&node).range;
130 if let Some(text) = hover_text_from_name_kind(db, definition) { 116 if let Some(text) = hover_text_from_name_kind(db, definition) {
131 res.results.push(text); 117 res.markup.push_section(&text);
132 } 118 }
133 if !res.is_empty() { 119 if !res.is_empty() {
134 if let Some(action) = show_implementations_action(db, definition) { 120 if let Some(action) = show_implementations_action(db, definition) {
@@ -168,7 +154,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
168 } 154 }
169 }?; 155 }?;
170 156
171 res.results.push(rust_code_markup(&ty.display(db))); 157 res.markup.push_section(&rust_code_markup(&ty.display(db)));
172 let range = sema.original_range(&node).range; 158 let range = sema.original_range(&node).range;
173 Some(RangeInfo::new(range, res)) 159 Some(RangeInfo::new(range, res))
174} 160}
@@ -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
18pub mod mock_analysis; 18pub mod mock_analysis;
19 19
20mod markup;
20mod prime_caches; 21mod prime_caches;
21mod status; 22mod status;
22mod completion; 23mod completion;
@@ -68,6 +69,7 @@ pub use crate::{
68 folding_ranges::{Fold, FoldKind}, 69 folding_ranges::{Fold, FoldKind},
69 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, 70 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
70 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, 71 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
72 markup::Markup,
71 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, 73 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
72 runnables::{Runnable, RunnableKind, TestId}, 74 runnables::{Runnable, RunnableKind, TestId},
73 syntax_highlighting::{ 75 syntax_highlighting::{
diff --git a/crates/ra_ide/src/markup.rs b/crates/ra_ide/src/markup.rs
new file mode 100644
index 000000000..2f2b3cc25
--- /dev/null
+++ b/crates/ra_ide/src/markup.rs
@@ -0,0 +1,38 @@
1//! Markdown formatting.
2//!
3//! Sometimes, we want to display a "rich text" in the UI. At the moment, we use
4//! markdown for this purpose. It doesn't feel like a right option, but that's
5//! what is used by LSP, so let's keep it simple.
6use std::fmt;
7
8#[derive(Default, Debug)]
9pub struct Markup {
10 text: String,
11}
12
13impl From<Markup> for String {
14 fn from(markup: Markup) -> Self {
15 markup.text
16 }
17}
18
19impl fmt::Display for Markup {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 fmt::Display::fmt(&self.text, f)
22 }
23}
24
25impl Markup {
26 pub fn as_str(&self) -> &str {
27 self.text.as_str()
28 }
29 pub fn is_empty(&self) -> bool {
30 self.text.is_empty()
31 }
32 pub fn push_section(&mut self, section: &str) {
33 if !self.text.is_empty() {
34 self.text.push_str("\n\n___\n");
35 }
36 self.text.push_str(section);
37 }
38}
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index f374334fe..8ce6e1c71 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -12,10 +12,10 @@ use lsp_types::{
12 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, 12 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
13 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, 13 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams,
14 CodeLens, Command, CompletionItem, Diagnostic, DocumentFormattingParams, DocumentHighlight, 14 CodeLens, Command, CompletionItem, Diagnostic, DocumentFormattingParams, DocumentHighlight,
15 DocumentSymbol, FoldingRange, FoldingRangeParams, HoverContents, Location, MarkupContent, 15 DocumentSymbol, FoldingRange, FoldingRangeParams, HoverContents, Location, Position,
16 MarkupKind, Position, PrepareRenameResponse, Range, RenameParams, SemanticTokensParams, 16 PrepareRenameResponse, Range, RenameParams, SemanticTokensParams, SemanticTokensRangeParams,
17 SemanticTokensRangeParams, SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, 17 SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, TextDocumentIdentifier,
18 TextDocumentIdentifier, Url, WorkspaceEdit, 18 Url, WorkspaceEdit,
19}; 19};
20use ra_ide::{ 20use ra_ide::{
21 FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query, 21 FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query,
@@ -584,13 +584,10 @@ pub(crate) fn handle_hover(
584 let range = to_proto::range(&line_index, info.range); 584 let range = to_proto::range(&line_index, info.range);
585 let hover = lsp_ext::Hover { 585 let hover = lsp_ext::Hover {
586 hover: lsp_types::Hover { 586 hover: lsp_types::Hover {
587 contents: HoverContents::Markup(MarkupContent { 587 contents: HoverContents::Markup(to_proto::markup_content(info.info.markup)),
588 kind: MarkupKind::Markdown,
589 value: crate::markdown::format_docs(&info.info.to_markup()),
590 }),
591 range: Some(range), 588 range: Some(range),
592 }, 589 },
593 actions: prepare_hover_actions(&snap, position.file_id, info.info.actions()), 590 actions: prepare_hover_actions(&snap, position.file_id, &info.info.actions),
594 }; 591 };
595 592
596 Ok(Some(hover)) 593 Ok(Some(hover))
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 7fa4ffbc6..263f58a00 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -6,8 +6,8 @@ use ra_db::{FileId, FileRange};
6use ra_ide::{ 6use ra_ide::{
7 Assist, AssistKind, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, 7 Assist, AssistKind, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold,
8 FoldKind, FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, 8 FoldKind, FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange,
9 Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, NavigationTarget, ReferenceAccess, 9 Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget,
10 ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, 10 ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit,
11}; 11};
12use ra_syntax::{SyntaxKind, TextRange, TextSize}; 12use ra_syntax::{SyntaxKind, TextRange, TextSize};
13 13
@@ -696,6 +696,10 @@ pub(crate) fn runnable(
696 }) 696 })
697} 697}
698 698
699pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent {
700 lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value: markup.into() }
701}
702
699#[cfg(test)] 703#[cfg(test)]
700mod tests { 704mod tests {
701 use ra_ide::Analysis; 705 use ra_ide::Analysis;