From fccbac4887c2a420679f08eb24e69f78e83a1e2e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 6 Jun 2023 17:12:24 -0700 Subject: [PATCH 1/4] Handle LSP codeActions capability set to false --- crates/project/src/lsp_command.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 490f3bde17..94a43d79ec 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -1499,7 +1499,11 @@ impl LspCommand for GetCodeActions { type ProtoRequest = proto::GetCodeActions; fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool { - capabilities.code_action_provider.is_some() + match &capabilities.code_action_provider { + None => false, + Some(lsp::CodeActionProviderCapability::Simple(false)) => false, + _ => true, + } } fn to_lsp( From 6f2726524e49ebd02d33da3145356bea25982790 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 6 Jun 2023 17:13:23 -0700 Subject: [PATCH 2/4] Remove stray println --- crates/editor/src/hover_popover.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 9192dc75e1..4c339e52df 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -588,10 +588,7 @@ impl InfoPopover { MouseRegion::new::(view_id, region_id, bounds) .on_click::( MouseButton::Left, - move |_, _, cx| { - println!("clicked link {url}"); - cx.platform().open_url(&url); - }, + move |_, _, cx| cx.platform().open_url(&url), ), ); } From e8479f23f9e0a43d1eb4c91c935950cf035c01da Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 6 Jun 2023 17:13:49 -0700 Subject: [PATCH 3/4] Improve log message on invalid LSP message from server's stdout --- crates/lsp/src/lsp.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 1b01660308..691203d5e8 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -260,9 +260,10 @@ impl LanguageServer { buffer.clear(); stdout.read_until(b'\n', &mut buffer).await?; stdout.read_until(b'\n', &mut buffer).await?; - let message_len: usize = std::str::from_utf8(&buffer)? + let header = std::str::from_utf8(&buffer)?; + let message_len: usize = header .strip_prefix(CONTENT_LEN_HEADER) - .ok_or_else(|| anyhow!("invalid header"))? + .ok_or_else(|| anyhow!("invalid LSP message header {header:?}"))? .trim_end() .parse()?; @@ -301,7 +302,7 @@ impl LanguageServer { } } else { warn!( - "Failed to deserialize message:\n{}", + "failed to deserialize LSP message:\n{}", std::str::from_utf8(&buffer)? ); } From 72372ddf0ed1fa18f57fcbec794acdb5270d8623 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 7 Jun 2023 09:19:31 -0700 Subject: [PATCH 4/4] Highlight hover code blocks as LSP's own language by default The elixir LSP does not include a language name on its elixir code blocks. --- crates/editor/src/hover_popover.rs | 38 ++++++++++---------- crates/project/src/lsp_command.rs | 56 ++++++++++++++++++------------ crates/project/src/project.rs | 1 + 3 files changed, 53 insertions(+), 42 deletions(-) diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 4c339e52df..7a203d54a9 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -221,6 +221,7 @@ fn show_hover( project: project.clone(), symbol_range: range, blocks: hover_result.contents, + language: hover_result.language, rendered_content: None, }) }); @@ -253,6 +254,7 @@ fn render_blocks( theme_id: usize, blocks: &[HoverBlock], language_registry: &Arc, + language: Option<&Arc>, style: &EditorStyle, ) -> RenderedInfo { let mut text = String::new(); @@ -351,11 +353,13 @@ fn render_blocks( } Tag::CodeBlock(kind) => { new_paragraph(&mut text, &mut list_stack); - if let CodeBlockKind::Fenced(language) = kind { - current_language = language_registry + current_language = if let CodeBlockKind::Fenced(language) = kind { + language_registry .language_for_name(language.as_ref()) .now_or_never() - .and_then(Result::ok); + .and_then(Result::ok) + } else { + language.cloned() } } Tag::Emphasis => italic_depth += 1, @@ -414,10 +418,6 @@ fn render_blocks( } } - if !text.is_empty() && !text.ends_with('\n') { - text.push('\n'); - } - RenderedInfo { theme_id, text, @@ -524,6 +524,7 @@ pub struct InfoPopover { pub project: ModelHandle, pub symbol_range: Range, pub blocks: Vec, + language: Option>, rendered_content: Option, } @@ -559,6 +560,7 @@ impl InfoPopover { style.theme_id, &self.blocks, self.project.read(cx).languages(), + self.language.as_ref(), style, ) }); @@ -903,7 +905,7 @@ mod tests { text: "one **two** three".to_string(), kind: HoverBlockKind::Markdown, }], - expected_marked_text: "one «two» three\n".to_string(), + expected_marked_text: "one «two» three".to_string(), expected_styles: vec![HighlightStyle { weight: Some(Weight::BOLD), ..Default::default() @@ -915,7 +917,7 @@ mod tests { text: "one [two](the-url) three".to_string(), kind: HoverBlockKind::Markdown, }], - expected_marked_text: "one «two» three\n".to_string(), + expected_marked_text: "one «two» three".to_string(), expected_styles: vec![HighlightStyle { underline: Some(Underline { thickness: 1.0.into(), @@ -934,8 +936,7 @@ mod tests { - b * two - [c](the-url) - - d - " + - d" .unindent(), kind: HoverBlockKind::Markdown, }], @@ -946,8 +947,7 @@ mod tests { - b - two - «c» - - d - " + - d" .unindent(), expected_styles: vec![HighlightStyle { underline: Some(Underline { @@ -970,9 +970,8 @@ mod tests { nine * ten - * six - " - .unindent(), + * six" + .unindent(), kind: HoverBlockKind::Markdown, }], expected_marked_text: " @@ -982,9 +981,8 @@ mod tests { nine - ten - - six - " - .unindent(), + - six" + .unindent(), expected_styles: vec![HighlightStyle { underline: Some(Underline { thickness: 1.0.into(), @@ -1001,7 +999,7 @@ mod tests { expected_styles, } in &rows[0..] { - let rendered = render_blocks(0, &blocks, &Default::default(), &style); + let rendered = render_blocks(0, &blocks, &Default::default(), None, &style); let (expected_text, ranges) = marked_text_ranges(expected_marked_text, false); let expected_highlights = ranges diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 94a43d79ec..2d4bed760d 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -1111,14 +1111,18 @@ impl LspCommand for GetHover { cx: AsyncAppContext, ) -> Result { Ok(message.and_then(|hover| { - let range = hover.range.map(|range| { - cx.read(|cx| { - let buffer = buffer.read(cx); - let token_start = - buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left); - let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left); - buffer.anchor_after(token_start)..buffer.anchor_before(token_end) - }) + let (language, range) = cx.read(|cx| { + let buffer = buffer.read(cx); + ( + buffer.language().cloned(), + hover.range.map(|range| { + let token_start = + buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left); + let token_end = + buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left); + buffer.anchor_after(token_start)..buffer.anchor_before(token_end) + }), + ) }); fn hover_blocks_from_marked_string( @@ -1163,7 +1167,11 @@ impl LspCommand for GetHover { }], }); - Some(Hover { contents, range }) + Some(Hover { + contents, + range, + language, + }) })) } @@ -1247,16 +1255,9 @@ impl LspCommand for GetHover { self, message: proto::GetHoverResponse, _: ModelHandle, - _: ModelHandle, - _: AsyncAppContext, + buffer: ModelHandle, + cx: AsyncAppContext, ) -> Result { - let range = if let (Some(start), Some(end)) = (message.start, message.end) { - language::proto::deserialize_anchor(start) - .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end)) - } else { - None - }; - let contents: Vec<_> = message .contents .into_iter() @@ -1271,12 +1272,23 @@ impl LspCommand for GetHover { }, }) .collect(); + if contents.is_empty() { + return Ok(None); + } - Ok(if contents.is_empty() { - None + let language = buffer.read_with(&cx, |buffer, _| buffer.language().cloned()); + let range = if let (Some(start), Some(end)) = (message.start, message.end) { + language::proto::deserialize_anchor(start) + .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end)) } else { - Some(Hover { contents, range }) - }) + None + }; + + Ok(Some(Hover { + contents, + range, + language, + })) } fn buffer_id_from_proto(message: &Self::ProtoRequest) -> u64 { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 39d8ea8512..2b2271bf1e 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -359,6 +359,7 @@ pub enum HoverBlockKind { pub struct Hover { pub contents: Vec, pub range: Option>, + pub language: Option>, } #[derive(Default)]