Restore previous hovered_offset logic

Co-authored-by: David Kleingeld <davidsk@zed.dev>
This commit is contained in:
Richard Feldman 2025-08-25 10:49:28 -04:00
parent 70918609d8
commit 81578c0d9e
No known key found for this signature in database

View file

@ -298,120 +298,123 @@ pub fn update_inlay_link_and_hover_points(
window: &mut Window, window: &mut Window,
cx: &mut Context<Editor>, cx: &mut Context<Editor>,
) { ) {
// For inlay hints, we need to use the exact position where the mouse is let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 {
// But we must clip it to valid bounds to avoid panics Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
let clipped_point = snapshot.clip_point(point_for_position.exact_unclipped, Bias::Left); } else {
let hovered_offset = snapshot.display_point_to_inlay_offset(clipped_point, Bias::Left); None
};
let mut go_to_definition_updated = false; let mut go_to_definition_updated = false;
let mut hover_updated = false; let mut hover_updated = false;
// Get all visible inlay hints if let Some(hovered_offset) = hovered_offset {
let visible_hints = editor.visible_inlay_hints(cx); // Get all visible inlay hints
let visible_hints = editor.visible_inlay_hints(cx);
// Find if we're hovering over an inlay hint // Find if we're hovering over an inlay hint
if let Some(hovered_inlay) = visible_hints.into_iter().find(|inlay| { if let Some(hovered_inlay) = visible_hints.into_iter().find(|inlay| {
// Only process hint inlays // Only process hint inlays
if !matches!(inlay.id, InlayId::Hint(_)) { if !matches!(inlay.id, InlayId::Hint(_)) {
return false; return false;
} }
// Check if the hovered position falls within this inlay's display range // Check if the hovered position falls within this inlay's display range
let inlay_start = snapshot.anchor_to_inlay_offset(inlay.position); let inlay_start = snapshot.anchor_to_inlay_offset(inlay.position);
let inlay_end = InlayOffset(inlay_start.0 + inlay.text.len()); let inlay_end = InlayOffset(inlay_start.0 + inlay.text.len());
hovered_offset >= inlay_start && hovered_offset < inlay_end hovered_offset >= inlay_start && hovered_offset < inlay_end
}) { }) {
let inlay_hint_cache = editor.inlay_hint_cache(); let inlay_hint_cache = editor.inlay_hint_cache();
let excerpt_id = hovered_inlay.position.excerpt_id; let excerpt_id = hovered_inlay.position.excerpt_id;
// Extract the hint ID from the inlay // Extract the hint ID from the inlay
if let InlayId::Hint(_hint_id) = hovered_inlay.id { if let InlayId::Hint(_hint_id) = hovered_inlay.id {
if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_inlay.id) { if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_inlay.id)
// Check if we should process this hint for hover {
let should_process_hint = match cached_hint.resolve_state { // Check if we should process this hint for hover
ResolveState::CanResolve(_, _) => { let should_process_hint = match cached_hint.resolve_state {
if let Some(buffer_id) = snapshot ResolveState::CanResolve(_, _) => {
.buffer_snapshot if let Some(buffer_id) = snapshot
.buffer_id_for_anchor(hovered_inlay.position) .buffer_snapshot
{ .buffer_id_for_anchor(hovered_inlay.position)
inlay_hint_cache.spawn_hint_resolve( {
buffer_id, inlay_hint_cache.spawn_hint_resolve(
excerpt_id, buffer_id,
hovered_inlay.id, excerpt_id,
window, hovered_inlay.id,
cx,
);
}
false // Don't process unresolved hints
}
ResolveState::Resolved => true,
ResolveState::Resolving => false,
};
if should_process_hint {
let mut extra_shift_left = 0;
let mut extra_shift_right = 0;
if cached_hint.padding_left {
extra_shift_left += 1;
extra_shift_right += 1;
}
if cached_hint.padding_right {
extra_shift_right += 1;
}
match cached_hint.label {
project::InlayHintLabel::String(_) => {
if let Some(tooltip) = cached_hint.tooltip {
hover_popover::hover_at_inlay(
editor,
InlayHover {
tooltip: match tooltip {
InlayHintTooltip::String(text) => HoverBlock {
text,
kind: HoverBlockKind::PlainText,
},
InlayHintTooltip::MarkupContent(content) => {
HoverBlock {
text: content.value,
kind: content.kind,
}
}
},
range: InlayHighlight {
inlay: hovered_inlay.id,
inlay_position: hovered_inlay.position,
range: extra_shift_left
..hovered_inlay.text.len() + extra_shift_right,
},
},
window, window,
cx, cx,
); );
hover_updated = true;
} }
false // Don't process unresolved hints
} }
project::InlayHintLabel::LabelParts(label_parts) => { ResolveState::Resolved => true,
// Find the first part with actual hover information (tooltip or location) ResolveState::Resolving => false,
let _hint_start = };
snapshot.anchor_to_inlay_offset(hovered_inlay.position);
let mut part_offset = 0;
for part in label_parts { if should_process_hint {
let part_len = part.value.chars().count(); let mut extra_shift_left = 0;
let mut extra_shift_right = 0;
if cached_hint.padding_left {
extra_shift_left += 1;
extra_shift_right += 1;
}
if cached_hint.padding_right {
extra_shift_right += 1;
}
match cached_hint.label {
project::InlayHintLabel::String(_) => {
if let Some(tooltip) = cached_hint.tooltip {
hover_popover::hover_at_inlay(
editor,
InlayHover {
tooltip: match tooltip {
InlayHintTooltip::String(text) => HoverBlock {
text,
kind: HoverBlockKind::PlainText,
},
InlayHintTooltip::MarkupContent(content) => {
HoverBlock {
text: content.value,
kind: content.kind,
}
}
},
range: InlayHighlight {
inlay: hovered_inlay.id,
inlay_position: hovered_inlay.position,
range: extra_shift_left
..hovered_inlay.text.len() + extra_shift_right,
},
},
window,
cx,
);
hover_updated = true;
}
}
project::InlayHintLabel::LabelParts(label_parts) => {
// 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 part.tooltip.is_some() || part.location.is_some() { for part in label_parts {
// Found the meaningful part - show hover for it let part_len = part.value.chars().count();
let highlight_start = part_offset + extra_shift_left;
let highlight_end = part_offset + part_len + extra_shift_right;
let highlight = InlayHighlight { if part.tooltip.is_some() || part.location.is_some() {
inlay: hovered_inlay.id, // Found the meaningful part - show hover for it
inlay_position: hovered_inlay.position, let highlight_start = part_offset + extra_shift_left;
range: highlight_start..highlight_end, let highlight_end =
}; part_offset + part_len + extra_shift_right;
if let Some(tooltip) = part.tooltip { let highlight = InlayHighlight {
hover_popover::hover_at_inlay( inlay: hovered_inlay.id,
inlay_position: hovered_inlay.position,
range: highlight_start..highlight_end,
};
if let Some(tooltip) = part.tooltip {
hover_popover::hover_at_inlay(
editor, editor,
InlayHover { InlayHover {
tooltip: match tooltip { tooltip: match tooltip {
@ -433,41 +436,42 @@ pub fn update_inlay_link_and_hover_points(
window, window,
cx, cx,
); );
hover_updated = true; hover_updated = true;
} }
if let Some((language_server_id, location)) = if let Some((language_server_id, location)) =
part.location.clone() part.location.clone()
{ {
// When there's no tooltip but we have a location, perform a "Go to Definition" style operation // When there's no tooltip but we have a location, perform a "Go to Definition" style operation
let filename = location let filename = location
.uri .uri
.path() .path()
.split('/') .split('/')
.next_back() .next_back()
.unwrap_or("unknown") .unwrap_or("unknown")
.to_string(); .to_string();
hover_popover::hover_at_inlay( hover_popover::hover_at_inlay(
editor, editor,
InlayHover { InlayHover {
tooltip: HoverBlock { tooltip: HoverBlock {
text: "Loading documentation...".to_string(), text: "Loading documentation..."
kind: HoverBlockKind::PlainText, .to_string(),
kind: HoverBlockKind::PlainText,
},
range: highlight.clone(),
}, },
range: highlight.clone(), window,
}, cx,
window, );
cx, hover_updated = true;
);
hover_updated = true;
// Now perform the "Go to Definition" flow to get hover documentation // Now perform the "Go to Definition" flow to get hover documentation
if let Some(project) = editor.project.clone() { if let Some(project) = editor.project.clone() {
let highlight = highlight.clone(); let highlight = highlight.clone();
let hint_value = part.value.clone(); let hint_value = part.value.clone();
let location_uri = location.uri.clone(); let location_uri = location.uri.clone();
cx.spawn_in(window, async move |editor, cx| { cx.spawn_in(window, async move |editor, cx| {
async move { async move {
// Small delay to show the loading message first // Small delay to show the loading message first
cx.background_executor() cx.background_executor()
@ -585,36 +589,38 @@ pub fn update_inlay_link_and_hover_points(
.log_err() .log_err()
.await .await
}).detach(); }).detach();
}
} }
}
if let Some((language_server_id, location)) = &part.location { if let Some((language_server_id, location)) = &part.location
if secondary_held
&& !editor.has_pending_nonempty_selection()
{ {
go_to_definition_updated = true; if secondary_held
show_link_definition( && !editor.has_pending_nonempty_selection()
shift_held, {
editor, go_to_definition_updated = true;
TriggerPoint::InlayHint( show_link_definition(
highlight, shift_held,
location.clone(), editor,
*language_server_id, TriggerPoint::InlayHint(
), highlight,
snapshot, location.clone(),
window, *language_server_id,
cx, ),
); snapshot,
window,
cx,
);
}
} }
break;
} }
break; part_offset += part_len;
} }
part_offset += part_len;
} }
} };
}; }
} }
} }
} }