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
This commit is contained in:
Robin van Dijk 2020-10-05 19:27:29 +02:00
parent e5f252ade7
commit c3cc361294
5 changed files with 74 additions and 9 deletions

View file

@ -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<RangeInfo<HoverResult>> {
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(

View file

@ -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<Option<RangeInfo<HoverResult>>> {
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.

View file

@ -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
}

View file

@ -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;
}

View file

@ -618,7 +618,11 @@ pub(crate) fn handle_hover(
) -> Result<Option<lsp_ext::Hover>> {
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,
};