diff --git a/crates/gpui/src/elements/text.rs b/crates/gpui/src/elements/text.rs index 94be18da4e5587ef12f1b952866a0821bfa29418..fb1e2ea33188c2b0041b8af74b562008d58dd3dc 100644 --- a/crates/gpui/src/elements/text.rs +++ b/crates/gpui/src/elements/text.rs @@ -10,6 +10,7 @@ use crate::{ DebugContext, Element, Event, EventContext, FontCache, LayoutContext, PaintContext, SizeConstraint, TextLayoutCache, }; +use log::warn; use serde_json::json; use std::{borrow::Cow, ops::Range, sync::Arc}; @@ -62,6 +63,7 @@ impl Element for Text { cx: &mut LayoutContext, ) -> (Vector2F, Self::LayoutState) { // Convert the string and highlight ranges into an iterator of highlighted chunks. + let mut offset = 0; let mut highlight_ranges = self.highlights.iter().peekable(); let chunks = std::iter::from_fn(|| { @@ -70,10 +72,17 @@ impl Element for Text { if offset < range.start { result = Some((&self.text[offset..range.start], None)); offset = range.start; - } else { + } else if range.end <= self.text.len() { result = Some((&self.text[range.clone()], Some(*highlight_style))); highlight_ranges.next(); offset = range.end; + } else { + warn!( + "Highlight out of text range. Text len: {}, Highlight range: {}..{}", + self.text.len(), + range.start, + range.end); + result = None; } } else if offset < self.text.len() { result = Some((&self.text[offset..], None)); diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 3af86db0fd371be28866353711c4fe164f4eb5ce..ee2bf37aa1f3e5574e1fc2231e92b515b7ffa85e 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -932,7 +932,9 @@ impl LspCommand for GetHover { } Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(new_language))) => { if !current_text.is_empty() { - let text = std::mem::replace(&mut current_text, String::new()); + let text = std::mem::replace(&mut current_text, String::new()) + .trim() + .to_string(); contents.push(HoverBlock { text, language }); } @@ -948,9 +950,10 @@ impl LspCommand for GetHover { | Event::End(Tag::BlockQuote) | Event::HardBreak => { if !current_text.is_empty() { - let text = std::mem::replace(&mut current_text, String::new()); + let text = std::mem::replace(&mut current_text, String::new()) + .trim() + .to_string(); contents.push(HoverBlock { text, language }); - current_text.clear(); } language = None; } @@ -958,7 +961,7 @@ impl LspCommand for GetHover { } } - if !current_text.is_empty() { + if !current_text.trim().is_empty() { contents.push(HoverBlock { text: current_text, language, diff --git a/crates/zed/src/languages/go.rs b/crates/zed/src/languages/go.rs index 9a8895266c932c530c5cff0ffa9f4e6bf6714337..978af215c1b80852effcab70ccfe0595122028e3 100644 --- a/crates/zed/src/languages/go.rs +++ b/crates/zed/src/languages/go.rs @@ -92,7 +92,7 @@ impl super::LspAdapter for GoLspAdapter { .output() .await?; if !install_output.status.success() { - Err(anyhow!("failed to install gopls"))?; + Err(anyhow!("failed to install gopls. Is go installed?"))?; } let installed_binary_path = gobin_dir.join("gopls");