From c3cc3612948be235577ccfd55990062829c8cfbb Mon Sep 17 00:00:00 2001 From: Robin van Dijk Date: Mon, 5 Oct 2020 19:27:29 +0200 Subject: honor content_format clientcap This removes all markdown when the client does not support the markdown MarkupKind Otherwise the output on the editor will have some markdown boilerplate, making it less readable --- crates/ide/src/hover.rs | 51 +++++++++++++++++++++++++++++++----- crates/ide/src/lib.rs | 4 ++- crates/ide/src/markdown_remove.rs | 16 +++++++++++ crates/rust-analyzer/src/config.rs | 6 ++++- crates/rust-analyzer/src/handlers.rs | 6 ++++- 5 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 crates/ide/src/markdown_remove.rs diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 9cf02f0a3..ba67dd9f8 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -15,6 +15,7 @@ use test_utils::mark; use crate::{ display::{macro_label, ShortLabel, ToNav, TryToNav}, link_rewrite::{remove_links, rewrite_links}, + markdown_remove::remove_markdown, markup::Markup, runnables::runnable, FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, @@ -27,6 +28,7 @@ pub struct HoverConfig { pub debug: bool, pub goto_type_def: bool, pub links_in_hover: bool, + pub markdown: bool, } impl Default for HoverConfig { @@ -37,6 +39,7 @@ impl Default for HoverConfig { debug: true, goto_type_def: true, links_in_hover: true, + markdown: true, } } } @@ -48,6 +51,7 @@ impl HoverConfig { debug: false, goto_type_def: false, links_in_hover: true, + markdown: true, }; pub fn any(&self) -> bool { @@ -91,6 +95,7 @@ pub(crate) fn hover( db: &RootDatabase, position: FilePosition, links_in_hover: bool, + markdown: bool, ) -> Option> { let sema = Semantics::new(db); let file = sema.parse(position.file_id).syntax().clone(); @@ -109,7 +114,9 @@ pub(crate) fn hover( }; if let Some(definition) = definition { if let Some(markup) = hover_for_definition(db, definition) { - let markup = if links_in_hover { + let markup = if !markdown { + remove_markdown(&markup.as_str()) + } else if links_in_hover { rewrite_links(db, &markup.as_str(), &definition) } else { remove_links(&markup.as_str()) @@ -147,7 +154,11 @@ pub(crate) fn hover( } }; - res.markup = Markup::fenced_block(&ty.display(db)); + res.markup = if markdown { + Markup::fenced_block(&ty.display(db)) + } else { + ty.display(db).to_string().into() + }; let range = sema.original_range(&node).range; Some(RangeInfo::new(range, res)) } @@ -383,12 +394,12 @@ mod tests { fn check_hover_no_result(ra_fixture: &str) { let (analysis, position) = fixture::position(ra_fixture); - assert!(analysis.hover(position, true).unwrap().is_none()); + assert!(analysis.hover(position, true, true).unwrap().is_none()); } fn check(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); - let hover = analysis.hover(position, true).unwrap().unwrap(); + let hover = analysis.hover(position, true, true).unwrap().unwrap(); let content = analysis.db.file_text(position.file_id); let hovered_element = &content[hover.range]; @@ -399,7 +410,18 @@ mod tests { fn check_hover_no_links(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); - let hover = analysis.hover(position, false).unwrap().unwrap(); + let hover = analysis.hover(position, false, true).unwrap().unwrap(); + + let content = analysis.db.file_text(position.file_id); + let hovered_element = &content[hover.range]; + + let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup); + expect.assert_eq(&actual) + } + + fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) { + let (analysis, position) = fixture::position(ra_fixture); + let hover = analysis.hover(position, true, false).unwrap().unwrap(); let content = analysis.db.file_text(position.file_id); let hovered_element = &content[hover.range]; @@ -410,7 +432,7 @@ mod tests { fn check_actions(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); - let hover = analysis.hover(position, true).unwrap().unwrap(); + let hover = analysis.hover(position, true, true).unwrap().unwrap(); expect.assert_debug_eq(&hover.info.actions) } @@ -433,6 +455,23 @@ fn main() { ); } + #[test] + fn hover_remove_markdown_if_configured() { + check_hover_no_markdown( + r#" +pub fn foo() -> u32 { 1 } + +fn main() { + let foo_test = foo()<|>; +} +"#, + expect![[r#" + *foo()* + u32 + "#]], + ); + } + #[test] fn hover_shows_long_type_of_an_expression() { check( diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 1aa673cf8..57f3581b6 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -46,6 +46,7 @@ mod syntax_highlighting; mod syntax_tree; mod typing; mod link_rewrite; +mod markdown_remove; use std::sync::Arc; @@ -376,8 +377,9 @@ impl Analysis { &self, position: FilePosition, links_in_hover: bool, + markdown: bool, ) -> Cancelable>> { - self.with_db(|db| hover::hover(db, position, links_in_hover)) + self.with_db(|db| hover::hover(db, position, links_in_hover, markdown)) } /// Computes parameter information for the given call expression. diff --git a/crates/ide/src/markdown_remove.rs b/crates/ide/src/markdown_remove.rs new file mode 100644 index 000000000..62b2aa1e7 --- /dev/null +++ b/crates/ide/src/markdown_remove.rs @@ -0,0 +1,16 @@ +use pulldown_cmark::{Event, Parser}; + +pub fn remove_markdown(markdown: &str) -> String { + let mut out = String::new(); + let parser = Parser::new(markdown); + + for event in parser { + match event { + Event::Text(text) | Event::Code(text) => out.push_str(&text), + Event::SoftBreak | Event::HardBreak | Event::Rule => out.push('\n'), + _ => {} + } + } + + out +} diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 0ab4c37bf..f66487789 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -14,7 +14,7 @@ use ide::{ AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig, MergeBehaviour, }; -use lsp_types::ClientCapabilities; +use lsp_types::{ClientCapabilities, MarkupKind}; use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; use rustc_hash::FxHashSet; use serde::Deserialize; @@ -327,6 +327,7 @@ impl Config { debug: data.hoverActions_enable && data.hoverActions_debug, goto_type_def: data.hoverActions_enable && data.hoverActions_gotoTypeDef, links_in_hover: data.hoverActions_linksInHover, + markdown: true, }; log::info!("Config::update() = {:#?}", self); @@ -334,6 +335,9 @@ impl Config { pub fn update_caps(&mut self, caps: &ClientCapabilities) { if let Some(doc_caps) = caps.text_document.as_ref() { + if let Some(value) = doc_caps.hover.as_ref().and_then(|it| it.content_format.as_ref()) { + self.hover.markdown = value.contains(&MarkupKind::Markdown) + } if let Some(value) = doc_caps.definition.as_ref().and_then(|it| it.link_support) { self.client_caps.location_link = value; } diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index e970abb7c..468655f9c 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -618,7 +618,11 @@ pub(crate) fn handle_hover( ) -> Result> { let _p = profile::span("handle_hover"); let position = from_proto::file_position(&snap, params.text_document_position_params)?; - let info = match snap.analysis.hover(position, snap.config.hover.links_in_hover)? { + let info = match snap.analysis.hover( + position, + snap.config.hover.links_in_hover, + snap.config.hover.markdown, + )? { None => return Ok(None), Some(info) => info, }; -- cgit v1.2.3