diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index d4cd126f32..1f324e3b2f 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1238,8 +1238,8 @@ impl EditorElement { hover_at(editor, Some(anchor), window, cx); Self::update_visible_cursor(editor, point, position_map, window, cx); } else { - // Don't call hover_at with None when we're over an inlay - // The inlay hover is already handled by update_hovered_link + // When over an inlay or invalid position, clear any existing hover + hover_at(editor, None, window, cx); } } else { editor.hide_hovered_link(cx); diff --git a/crates/editor/src/hover_links.rs b/crates/editor/src/hover_links.rs index f355eb3564..6bfca303c2 100644 --- a/crates/editor/src/hover_links.rs +++ b/crates/editor/src/hover_links.rs @@ -303,12 +303,13 @@ pub fn update_inlay_link_and_hover_points( let hovered_offset = snapshot.display_point_to_inlay_offset(clipped_point, Bias::Left); let mut go_to_definition_updated = false; + let mut hover_updated = false; // Get all visible inlay hints let visible_hints = editor.visible_inlay_hints(cx); // Find if we're hovering over an inlay hint - let found_inlay = visible_hints.into_iter().find(|inlay| { + if let Some(hovered_inlay) = visible_hints.into_iter().find(|inlay| { // Only process hint inlays if !matches!(inlay.id, InlayId::Hint(_)) { return false; @@ -319,9 +320,7 @@ pub fn update_inlay_link_and_hover_points( let inlay_end = InlayOffset(inlay_start.0 + inlay.text.len()); hovered_offset >= inlay_start && hovered_offset < inlay_end - }); - - if let Some(hovered_inlay) = found_inlay { + }) { let inlay_hint_cache = editor.inlay_hint_cache(); let excerpt_id = hovered_inlay.position.excerpt_id; @@ -387,20 +386,18 @@ pub fn update_inlay_link_and_hover_points( window, cx, ); + hover_updated = true; } } project::InlayHintLabel::LabelParts(label_parts) => { - // Find which specific part is being hovered - let hint_start = + // VS Code shows hover for the meaningful part regardless of where you hover + // Find the first part with actual hover information (tooltip or location) + let _hint_start = snapshot.anchor_to_inlay_offset(hovered_inlay.position); + let mut part_offset = 0; - if let Some((part, part_range)) = hover_popover::find_hovered_hint_part( - label_parts, - hint_start, - hovered_offset, - ) { - let part_offset = (part_range.start - hint_start).0; - let part_len = (part_range.end - part_range.start).0; + for part in label_parts { + let part_len = part.value.chars().count(); if part.tooltip.is_some() || part.location.is_some() { // Found the meaningful part - show hover for it @@ -436,6 +433,7 @@ pub fn update_inlay_link_and_hover_points( window, cx, ); + hover_updated = true; } else if let Some((_language_server_id, location)) = part.location.clone() { @@ -460,8 +458,9 @@ pub fn update_inlay_link_and_hover_points( window, cx, ); + hover_updated = true; + // Now perform the "Go to Definition" flow to get hover documentation - // Prepare data needed for the async task if let Some(project) = editor.project.clone() { let highlight = highlight.clone(); let hint_value = part.value.clone(); @@ -674,28 +673,27 @@ pub fn update_inlay_link_and_hover_points( ); } } + + // Found and processed the meaningful part + break; } + + part_offset += part_len; } } }; } } } - } else { - // No inlay is being hovered, hide any existing inlay hover - if editor - .hover_state - .info_popovers - .iter() - .any(|popover| matches!(popover.symbol_range, RangeInEditor::Inlay(_))) - { - hover_popover::hide_hover(editor, cx); - } } if !go_to_definition_updated { editor.hide_hovered_link(cx) } + if !hover_updated { + hover_popover::hover_at(editor, None, window, cx); + editor.clear_background_highlights::(cx); + } } pub fn show_link_definition( diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index a3f3f7beaa..80eb56645e 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -193,12 +193,6 @@ pub fn hover_at_inlay( }; this.update(cx, |this, cx| { - // Check if we should still show this hover (haven't moved to different location) - if this.hover_state.info_task.is_none() { - // Task was cancelled, don't show the hover - return; - } - // Highlight the inlay using background highlighting let highlight_range = inlay_hover.range.clone(); this.highlight_inlays::( @@ -562,19 +556,16 @@ fn same_info_hover(editor: &Editor, snapshot: &EditorSnapshot, anchor: Anchor) - .info_popovers .iter() .any(|InfoPopover { symbol_range, .. }| { - match symbol_range { - RangeInEditor::Text(range) => { + symbol_range + .as_text_range() + .map(|range| { let hover_range = range.to_offset(&snapshot.buffer_snapshot); let offset = anchor.to_offset(&snapshot.buffer_snapshot); // LSP returns a hover result for the end index of ranges that should be hovered, so we need to // use an inclusive range here to check if we should dismiss the popover (hover_range.start..=hover_range.end).contains(&offset) - } - RangeInEditor::Inlay(_) => { - // If we have an inlay hover and we're checking a text position, they're not the same - false - } - } + }) + .unwrap_or(false) }) }