@@ -121,6 +121,22 @@ impl Editor {
cx: &mut Context<Self>,
) {
let hovered_link_modifier = Editor::multi_cursor_modifier(false, &modifiers, cx);
+
+ // Allow inlay hover points to be updated even without modifier key
+ if point_for_position.as_valid().is_none() {
+ // Hovering over inlay - check for hover tooltips
+ update_inlay_link_and_hover_points(
+ snapshot,
+ point_for_position,
+ self,
+ hovered_link_modifier,
+ modifiers.shift,
+ window,
+ cx,
+ );
+ return;
+ }
+
if !hovered_link_modifier || self.has_pending_selection() {
self.hide_hovered_link(cx);
return;
@@ -137,15 +153,7 @@ impl Editor {
show_link_definition(modifiers.shift, self, trigger_point, snapshot, window, cx);
}
None => {
- update_inlay_link_and_hover_points(
- snapshot,
- point_for_position,
- self,
- hovered_link_modifier,
- modifiers.shift,
- window,
- cx,
- );
+ // This case is now handled above
}
}
}
@@ -319,129 +327,155 @@ pub fn update_inlay_link_and_hover_points(
let inlay_hint_cache = editor.inlay_hint_cache();
let excerpt_id = previous_valid_anchor.excerpt_id;
if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) {
- match cached_hint.resolve_state {
+ // Check if we should process this hint for hover
+ let should_process_hint = match cached_hint.resolve_state {
ResolveState::CanResolve(_, _) => {
- if let Some(buffer_id) = previous_valid_anchor.buffer_id {
- inlay_hint_cache.spawn_hint_resolve(
- buffer_id,
- excerpt_id,
- hovered_hint.id,
- window,
- cx,
- );
+ // Check if the hint already has the data we need (tooltip in label parts)
+ if let project::InlayHintLabel::LabelParts(label_parts) = &cached_hint.label
+ {
+ let has_tooltip_parts =
+ label_parts.iter().any(|part| part.tooltip.is_some());
+ if has_tooltip_parts {
+ true // Process the hint
+ } else {
+ if let Some(buffer_id) = previous_valid_anchor.buffer_id {
+ inlay_hint_cache.spawn_hint_resolve(
+ buffer_id,
+ excerpt_id,
+ hovered_hint.id,
+ window,
+ cx,
+ );
+ }
+ false // Don't process further
+ }
+ } else {
+ if let Some(buffer_id) = previous_valid_anchor.buffer_id {
+ inlay_hint_cache.spawn_hint_resolve(
+ buffer_id,
+ excerpt_id,
+ hovered_hint.id,
+ window,
+ cx,
+ );
+ }
+ false // Don't process further
}
}
ResolveState::Resolved => {
- 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;
+ true // Process the hint
+ }
+ ResolveState::Resolving => {
+ false // Don't process yet
+ }
+ };
+
+ 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_hint.id,
+ inlay_position: hovered_hint.position,
+ range: extra_shift_left
+ ..hovered_hint.text.len() + extra_shift_right,
+ },
+ },
+ window,
+ cx,
+ );
+ hover_updated = true;
+ }
}
- match cached_hint.label {
- project::InlayHintLabel::String(_) => {
- if let Some(tooltip) = cached_hint.tooltip {
+ project::InlayHintLabel::LabelParts(label_parts) => {
+ let hint_start = snapshot.anchor_to_inlay_offset(hovered_hint.position);
+ if let Some((hovered_hint_part, part_range)) =
+ hover_popover::find_hovered_hint_part(
+ label_parts,
+ hint_start,
+ hovered_offset,
+ )
+ {
+ let highlight_start =
+ (part_range.start - hint_start).0 + extra_shift_left;
+ let highlight_end =
+ (part_range.end - hint_start).0 + extra_shift_right;
+ let highlight = InlayHighlight {
+ inlay: hovered_hint.id,
+ inlay_position: hovered_hint.position,
+ range: highlight_start..highlight_end,
+ };
+ if let Some(tooltip) = hovered_hint_part.tooltip {
hover_popover::hover_at_inlay(
editor,
InlayHover {
tooltip: match tooltip {
- InlayHintTooltip::String(text) => HoverBlock {
- text,
- kind: HoverBlockKind::PlainText,
- },
- InlayHintTooltip::MarkupContent(content) => {
+ InlayHintLabelPartTooltip::String(text) => {
HoverBlock {
- text: content.value,
- kind: content.kind,
+ text,
+ kind: HoverBlockKind::PlainText,
}
}
+ InlayHintLabelPartTooltip::MarkupContent(
+ content,
+ ) => HoverBlock {
+ text: content.value,
+ kind: content.kind,
+ },
},
- range: InlayHighlight {
- inlay: hovered_hint.id,
- inlay_position: hovered_hint.position,
- range: extra_shift_left
- ..hovered_hint.text.len() + extra_shift_right,
- },
+ range: highlight.clone(),
},
window,
cx,
);
hover_updated = true;
}
- }
- project::InlayHintLabel::LabelParts(label_parts) => {
- let hint_start =
- snapshot.anchor_to_inlay_offset(hovered_hint.position);
- if let Some((hovered_hint_part, part_range)) =
- hover_popover::find_hovered_hint_part(
- label_parts,
- hint_start,
- hovered_offset,
- )
+ if let Some((language_server_id, location)) =
+ hovered_hint_part.location
{
- let highlight_start =
- (part_range.start - hint_start).0 + extra_shift_left;
- let highlight_end =
- (part_range.end - hint_start).0 + extra_shift_right;
- let highlight = InlayHighlight {
- inlay: hovered_hint.id,
- inlay_position: hovered_hint.position,
- range: highlight_start..highlight_end,
- };
- if let Some(tooltip) = hovered_hint_part.tooltip {
- hover_popover::hover_at_inlay(
+ if secondary_held && !editor.has_pending_nonempty_selection() {
+ go_to_definition_updated = true;
+ show_link_definition(
+ shift_held,
editor,
- InlayHover {
- tooltip: match tooltip {
- InlayHintLabelPartTooltip::String(text) => {
- HoverBlock {
- text,
- kind: HoverBlockKind::PlainText,
- }
- }
- InlayHintLabelPartTooltip::MarkupContent(
- content,
- ) => HoverBlock {
- text: content.value,
- kind: content.kind,
- },
- },
- range: highlight.clone(),
- },
+ TriggerPoint::InlayHint(
+ highlight,
+ location,
+ language_server_id,
+ ),
+ snapshot,
window,
cx,
);
- hover_updated = true;
- }
- if let Some((language_server_id, location)) =
- hovered_hint_part.location
- {
- if secondary_held
- && !editor.has_pending_nonempty_selection()
- {
- go_to_definition_updated = true;
- show_link_definition(
- shift_held,
- editor,
- TriggerPoint::InlayHint(
- highlight,
- location,
- language_server_id,
- ),
- snapshot,
- window,
- cx,
- );
- }
}
}
}
- };
- }
- ResolveState::Resolving => {}
+ }
+ };
}
}
}
@@ -21,6 +21,7 @@ use clock::Global;
use futures::future;
use gpui::{AppContext as _, AsyncApp, Context, Entity, Task, Window};
use language::{Buffer, BufferSnapshot, language_settings::InlayHintKind};
+use lsp::LanguageServerId;
use parking_lot::RwLock;
use project::{InlayHint, ResolveState};
@@ -622,45 +623,55 @@ impl InlayHintCache {
let mut guard = excerpt_hints.write();
if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
if let ResolveState::CanResolve(server_id, _) = &cached_hint.resolve_state {
- let hint_to_resolve = cached_hint.clone();
let server_id = *server_id;
+ let mut cached_hint = cached_hint.clone();
cached_hint.resolve_state = ResolveState::Resolving;
drop(guard);
- cx.spawn_in(window, async move |editor, cx| {
- let resolved_hint_task = editor.update(cx, |editor, cx| {
- let buffer = editor.buffer().read(cx).buffer(buffer_id)?;
- editor.semantics_provider.as_ref()?.resolve_inlay_hint(
- hint_to_resolve,
- buffer,
- server_id,
- cx,
- )
- })?;
- if let Some(resolved_hint_task) = resolved_hint_task {
- let mut resolved_hint =
- resolved_hint_task.await.context("hint resolve task")?;
- editor.read_with(cx, |editor, _| {
- if let Some(excerpt_hints) =
- editor.inlay_hint_cache.hints.get(&excerpt_id)
- {
- let mut guard = excerpt_hints.write();
- if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
- if cached_hint.resolve_state == ResolveState::Resolving {
- resolved_hint.resolve_state = ResolveState::Resolved;
- *cached_hint = resolved_hint;
- }
- }
- }
- })?;
- }
-
- anyhow::Ok(())
- })
- .detach_and_log_err(cx);
+ self.resolve_hint(server_id, buffer_id, cached_hint, window, cx)
+ .detach_and_log_err(cx);
}
}
}
}
+
+ fn resolve_hint(
+ &self,
+ server_id: LanguageServerId,
+ buffer_id: BufferId,
+ hint_to_resolve: InlayHint,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+ ) -> Task<anyhow::Result<()>> {
+ cx.spawn_in(window, async move |editor, cx| {
+ let resolved_hint_task = editor.update(cx, |editor, cx| {
+ let buffer = editor.buffer().read(cx).buffer(buffer_id)?;
+ editor.semantics_provider.as_ref()?.resolve_inlay_hint(
+ hint_to_resolve,
+ buffer,
+ server_id,
+ cx,
+ )
+ })?;
+ if let Some(resolved_hint_task) = resolved_hint_task {
+ let mut resolved_hint = resolved_hint_task.await.context("hint resolve task")?;
+ editor.update(cx, |editor, cx| {
+ if let Some(excerpt_hints) = editor.inlay_hint_cache.hints.get(&excerpt_id) {
+ let mut guard = excerpt_hints.write();
+ if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
+ if cached_hint.resolve_state == ResolveState::Resolving {
+ resolved_hint.resolve_state = ResolveState::Resolved;
+ *cached_hint = resolved_hint;
+ }
+ }
+ }
+ // Notify to trigger UI update
+ cx.notify();
+ })?;
+ }
+
+ anyhow::Ok(())
+ })
+ }
}
fn debounce_value(debounce_ms: u64) -> Option<Duration> {