Merge pull request #1244 from zed-industries/address-go-hover-panic

Keith Simmons created

Address hover panic add hint for installing go language server

Change summary

crates/editor/src/hover_popover.rs | 11 +++++++----
crates/gpui/src/elements/text.rs   | 11 ++++++++++-
crates/project/src/lsp_command.rs  | 11 +++++++----
crates/settings/src/settings.rs    |  6 ++++++
crates/zed/src/languages/go.rs     |  2 +-
5 files changed, 31 insertions(+), 10 deletions(-)

Detailed changes

crates/editor/src/hover_popover.rs 🔗

@@ -7,6 +7,7 @@ use gpui::{
 };
 use language::Bias;
 use project::{HoverBlock, Project};
+use settings::Settings;
 use std::{ops::Range, time::Duration};
 use util::TryFutureExt;
 
@@ -40,10 +41,12 @@ pub fn hover(editor: &mut Editor, _: &Hover, cx: &mut ViewContext<Editor>) {
 /// The internal hover action dispatches between `show_hover` or `hide_hover`
 /// depending on whether a point to hover over is provided.
 pub fn hover_at(editor: &mut Editor, action: &HoverAt, cx: &mut ViewContext<Editor>) {
-    if let Some(point) = action.point {
-        show_hover(editor, point, false, cx);
-    } else {
-        hide_hover(editor, cx);
+    if cx.global::<Settings>().hover_popover_enabled {
+        if let Some(point) = action.point {
+            show_hover(editor, point, false, cx);
+        } else {
+            hide_hover(editor, cx);
+        }
     }
 }
 

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));

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,

crates/settings/src/settings.rs 🔗

@@ -23,6 +23,7 @@ pub struct Settings {
     pub buffer_font_family: FamilyId,
     pub buffer_font_size: f32,
     pub default_buffer_font_size: f32,
+    pub hover_popover_enabled: bool,
     pub vim_mode: bool,
     pub language_settings: LanguageSettings,
     pub language_defaults: HashMap<Arc<str>, LanguageSettings>,
@@ -57,6 +58,8 @@ pub struct SettingsFileContent {
     #[serde(default)]
     pub buffer_font_size: Option<f32>,
     #[serde(default)]
+    pub hover_popover_enabled: Option<bool>,
+    #[serde(default)]
     pub vim_mode: Option<bool>,
     #[serde(default)]
     pub format_on_save: Option<bool>,
@@ -80,6 +83,7 @@ impl Settings {
             buffer_font_family: font_cache.load_family(&[buffer_font_family])?,
             buffer_font_size: 15.,
             default_buffer_font_size: 15.,
+            hover_popover_enabled: true,
             vim_mode: false,
             language_settings: Default::default(),
             language_defaults: Default::default(),
@@ -151,6 +155,7 @@ impl Settings {
             buffer_font_family: cx.font_cache().load_family(&["Monaco"]).unwrap(),
             buffer_font_size: 14.,
             default_buffer_font_size: 14.,
+            hover_popover_enabled: true,
             vim_mode: false,
             language_settings: Default::default(),
             language_defaults: Default::default(),
@@ -191,6 +196,7 @@ impl Settings {
         );
         merge(&mut self.buffer_font_size, data.buffer_font_size);
         merge(&mut self.default_buffer_font_size, data.buffer_font_size);
+        merge(&mut self.hover_popover_enabled, data.hover_popover_enabled);
         merge(&mut self.vim_mode, data.vim_mode);
         merge_option(
             &mut self.language_settings.format_on_save,

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");