Detailed changes
@@ -4,16 +4,16 @@ use super::{
MAX_LINE_LEN,
};
use crate::{
- display_map::{BlockStyle, DisplaySnapshot, FoldStatus, InlayOffset, TransformBlock},
+ display_map::{BlockStyle, DisplaySnapshot, FoldStatus, TransformBlock},
editor_settings::ShowScrollbar,
git::{diff_hunk_to_display, DisplayDiffHunk},
hover_popover::{
- hide_hover, hover_at, hover_at_inlay, InlayHover, HOVER_POPOVER_GAP,
- MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT,
+ hide_hover, hover_at, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH,
+ MIN_POPOVER_LINE_HEIGHT,
},
link_go_to_definition::{
go_to_fetched_definition, go_to_fetched_type_definition, update_go_to_definition_link,
- GoToDefinitionTrigger, InlayRange,
+ update_inlay_link_and_hover_points, GoToDefinitionTrigger,
},
mouse_context_menu, EditorSettings, EditorStyle, GutterHover, UnfoldAt,
};
@@ -43,8 +43,7 @@ use language::{
};
use project::{
project_settings::{GitGutterSetting, ProjectSettings},
- HoverBlock, HoverBlockKind, InlayHintLabelPart, InlayHintLabelPartTooltip, InlayHintTooltip,
- Location, LocationLink, ProjectPath, ResolveState,
+ ProjectPath,
};
use smallvec::SmallVec;
use std::{
@@ -478,10 +477,11 @@ impl EditorElement {
}
None => {
update_inlay_link_and_hover_points(
- position_map,
+ &position_map.snapshot,
point_for_position,
editor,
- (cmd, shift),
+ cmd,
+ shift,
cx,
);
}
@@ -1835,214 +1835,6 @@ impl EditorElement {
}
}
-fn update_inlay_link_and_hover_points(
- position_map: &PositionMap,
- point_for_position: PointForPosition,
- editor: &mut Editor,
- (cmd_held, shift_held): (bool, bool),
- cx: &mut ViewContext<'_, '_, Editor>,
-) {
- let hint_start_offset = position_map
- .snapshot
- .display_point_to_inlay_offset(point_for_position.previous_valid, Bias::Left);
- let hint_end_offset = position_map
- .snapshot
- .display_point_to_inlay_offset(point_for_position.next_valid, Bias::Right);
- let offset_overshoot = point_for_position.column_overshoot_after_line_end as usize;
- let hovered_offset = if offset_overshoot == 0 {
- Some(
- position_map
- .snapshot
- .display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left),
- )
- } else if (hint_end_offset - hint_start_offset).0 >= offset_overshoot {
- Some(InlayOffset(hint_start_offset.0 + offset_overshoot))
- } else {
- None
- };
- if let Some(hovered_offset) = hovered_offset {
- let snapshot = editor.buffer().read(cx).snapshot(cx);
- let previous_valid_anchor = snapshot.anchor_at(
- point_for_position
- .previous_valid
- .to_point(&position_map.snapshot.display_snapshot),
- Bias::Left,
- );
- let next_valid_anchor = snapshot.anchor_at(
- point_for_position
- .next_valid
- .to_point(&position_map.snapshot.display_snapshot),
- Bias::Right,
- );
-
- let mut go_to_definition_updated = false;
- let mut hover_updated = false;
- if let Some(hovered_hint) = editor
- .visible_inlay_hints(cx)
- .into_iter()
- .skip_while(|hint| hint.position.cmp(&previous_valid_anchor, &snapshot).is_lt())
- .take_while(|hint| hint.position.cmp(&next_valid_anchor, &snapshot).is_le())
- .max_by_key(|hint| hint.id)
- {
- 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 {
- 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,
- cx,
- );
- }
- }
- ResolveState::Resolved => {
- match cached_hint.label {
- project::InlayHintLabel::String(_) => {
- if let Some(tooltip) = cached_hint.tooltip {
- hover_at_inlay(
- editor,
- InlayHover {
- excerpt: excerpt_id,
- tooltip: match tooltip {
- InlayHintTooltip::String(text) => HoverBlock {
- text,
- kind: HoverBlockKind::PlainText,
- },
- InlayHintTooltip::MarkupContent(content) => {
- HoverBlock {
- text: content.value,
- kind: content.kind,
- }
- }
- },
- triggered_from: hovered_offset,
- range: InlayRange {
- inlay_position: hovered_hint.position,
- highlight_start: hint_start_offset,
- highlight_end: hint_end_offset,
- },
- },
- cx,
- );
- hover_updated = true;
- }
- }
- project::InlayHintLabel::LabelParts(label_parts) => {
- if let Some((hovered_hint_part, part_range)) =
- find_hovered_hint_part(
- label_parts,
- hint_start_offset..hint_end_offset,
- hovered_offset,
- )
- {
- if let Some(tooltip) = hovered_hint_part.tooltip {
- hover_at_inlay(
- editor,
- InlayHover {
- excerpt: excerpt_id,
- tooltip: match tooltip {
- InlayHintLabelPartTooltip::String(text) => {
- HoverBlock {
- text,
- kind: HoverBlockKind::PlainText,
- }
- }
- InlayHintLabelPartTooltip::MarkupContent(
- content,
- ) => HoverBlock {
- text: content.value,
- kind: content.kind,
- },
- },
- triggered_from: hovered_offset,
- range: InlayRange {
- inlay_position: hovered_hint.position,
- highlight_start: part_range.start,
- highlight_end: part_range.end,
- },
- },
- cx,
- );
- hover_updated = true;
- }
- if let Some(location) = hovered_hint_part.location {
- if let Some(buffer) =
- cached_hint.position.buffer_id.and_then(|buffer_id| {
- editor.buffer().read(cx).buffer(buffer_id)
- })
- {
- go_to_definition_updated = true;
- update_go_to_definition_link(
- editor,
- GoToDefinitionTrigger::InlayHint(
- InlayRange {
- inlay_position: hovered_hint.position,
- highlight_start: part_range.start,
- highlight_end: part_range.end,
- },
- LocationLink {
- origin: Some(Location {
- buffer,
- range: cached_hint.position
- ..cached_hint.position,
- }),
- target: location,
- },
- ),
- cmd_held,
- shift_held,
- cx,
- );
- }
- }
- }
- }
- };
- }
- ResolveState::Resolving => {}
- }
- }
- }
-
- if !go_to_definition_updated {
- update_go_to_definition_link(
- editor,
- GoToDefinitionTrigger::None,
- cmd_held,
- shift_held,
- cx,
- );
- }
- if !hover_updated {
- hover_at(editor, None, cx);
- }
- }
-}
-
-fn find_hovered_hint_part(
- label_parts: Vec<InlayHintLabelPart>,
- hint_range: Range<InlayOffset>,
- hovered_offset: InlayOffset,
-) -> Option<(InlayHintLabelPart, Range<InlayOffset>)> {
- if hovered_offset >= hint_range.start && hovered_offset <= hint_range.end {
- let mut hovered_character = (hovered_offset - hint_range.start).0;
- let mut part_start = hint_range.start;
- for part in label_parts {
- let part_len = part.value.chars().count();
- if hovered_character >= part_len {
- hovered_character -= part_len;
- part_start.0 += part_len;
- } else {
- return Some((part, part_start..InlayOffset(part_start.0 + part_len)));
- }
- }
- }
- None
-}
-
struct HighlightedChunk<'a> {
chunk: &'a str,
style: Option<HighlightStyle>,
@@ -2871,12 +2663,12 @@ struct PositionMap {
snapshot: EditorSnapshot,
}
-#[derive(Debug)]
+#[derive(Debug, Copy, Clone)]
pub struct PointForPosition {
- previous_valid: DisplayPoint,
+ pub previous_valid: DisplayPoint,
pub next_valid: DisplayPoint,
- exact_unclipped: DisplayPoint,
- column_overshoot_after_line_end: u32,
+ pub exact_unclipped: DisplayPoint,
+ pub column_overshoot_after_line_end: u32,
}
impl PointForPosition {
@@ -13,7 +13,7 @@ use gpui::{
AnyElement, AppContext, CursorRegion, Element, ModelHandle, MouseRegion, Task, ViewContext,
};
use language::{Bias, DiagnosticEntry, DiagnosticSeverity, Language, LanguageRegistry};
-use project::{HoverBlock, HoverBlockKind, Project};
+use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart, Project};
use std::{ops::Range, sync::Arc, time::Duration};
use util::TryFutureExt;
@@ -55,6 +55,27 @@ pub struct InlayHover {
pub tooltip: HoverBlock,
}
+pub fn find_hovered_hint_part(
+ label_parts: Vec<InlayHintLabelPart>,
+ hint_range: Range<InlayOffset>,
+ hovered_offset: InlayOffset,
+) -> Option<(InlayHintLabelPart, Range<InlayOffset>)> {
+ if hovered_offset >= hint_range.start && hovered_offset <= hint_range.end {
+ let mut hovered_character = (hovered_offset - hint_range.start).0;
+ let mut part_start = hint_range.start;
+ for part in label_parts {
+ let part_len = part.value.chars().count();
+ if hovered_character >= part_len {
+ hovered_character -= part_len;
+ part_start.0 += part_len;
+ } else {
+ return Some((part, part_start..InlayOffset(part_start.0 + part_len)));
+ }
+ }
+ }
+ None
+}
+
pub fn hover_at_inlay(editor: &mut Editor, inlay_hover: InlayHover, cx: &mut ViewContext<Editor>) {
if settings::get::<EditorSettings>(cx).hover_popover_enabled {
if editor.pending_rename.is_some() {
@@ -904,7 +904,7 @@ fn apply_hint_update(
}
#[cfg(test)]
-mod tests {
+pub mod tests {
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use crate::{
@@ -2989,15 +2989,11 @@ all hints should be invalidated and requeried for all of its visible excerpts"
("/a/main.rs", editor, fake_server)
}
- fn cached_hint_labels(editor: &Editor) -> Vec<String> {
+ pub fn cached_hint_labels(editor: &Editor) -> Vec<String> {
let mut labels = Vec::new();
for (_, excerpt_hints) in &editor.inlay_hint_cache().hints {
- let excerpt_hints = excerpt_hints.read();
- for (_, inlay) in excerpt_hints.hints.iter() {
- match &inlay.label {
- project::InlayHintLabel::String(s) => labels.push(s.to_string()),
- _ => unreachable!(),
- }
+ for (_, inlay) in &excerpt_hints.read().hints {
+ labels.push(inlay.text());
}
}
@@ -3005,7 +3001,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
labels
}
- fn visible_hint_labels(editor: &Editor, cx: &ViewContext<'_, '_, Editor>) -> Vec<String> {
+ pub fn visible_hint_labels(editor: &Editor, cx: &ViewContext<'_, '_, Editor>) -> Vec<String> {
let mut hints = editor
.visible_inlay_hints(cx)
.into_iter()
@@ -1,10 +1,15 @@
use crate::{
- display_map::InlayOffset, element::PointForPosition, Anchor, DisplayPoint, Editor,
- EditorSnapshot, SelectPhase,
+ display_map::{DisplaySnapshot, InlayOffset},
+ element::PointForPosition,
+ hover_popover::{self, InlayHover},
+ Anchor, DisplayPoint, Editor, EditorSnapshot, SelectPhase,
};
use gpui::{Task, ViewContext};
use language::{Bias, ToOffset};
-use project::LocationLink;
+use project::{
+ HoverBlock, HoverBlockKind, InlayHintLabelPartTooltip, InlayHintTooltip, Location,
+ LocationLink, ResolveState,
+};
use std::ops::Range;
use util::TryFutureExt;
@@ -23,7 +28,7 @@ pub enum GoToDefinitionTrigger {
None,
}
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct InlayRange {
pub inlay_position: Anchor,
pub highlight_start: InlayOffset,
@@ -140,6 +145,192 @@ pub fn update_go_to_definition_link(
hide_link_definition(editor, cx);
}
+pub fn update_inlay_link_and_hover_points(
+ snapshot: &DisplaySnapshot,
+ point_for_position: PointForPosition,
+ editor: &mut Editor,
+ cmd_held: bool,
+ shift_held: bool,
+ cx: &mut ViewContext<'_, '_, Editor>,
+) {
+ let hint_start_offset =
+ snapshot.display_point_to_inlay_offset(point_for_position.previous_valid, Bias::Left);
+ let hint_end_offset =
+ snapshot.display_point_to_inlay_offset(point_for_position.next_valid, Bias::Right);
+ let offset_overshoot = point_for_position.column_overshoot_after_line_end as usize;
+ let hovered_offset = if offset_overshoot == 0 {
+ Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
+ } else if (hint_end_offset - hint_start_offset).0 >= offset_overshoot {
+ Some(InlayOffset(hint_start_offset.0 + offset_overshoot))
+ } else {
+ None
+ };
+ if let Some(hovered_offset) = hovered_offset {
+ let buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
+ let previous_valid_anchor = buffer_snapshot.anchor_at(
+ point_for_position.previous_valid.to_point(snapshot),
+ Bias::Left,
+ );
+ let next_valid_anchor = buffer_snapshot.anchor_at(
+ point_for_position.next_valid.to_point(snapshot),
+ Bias::Right,
+ );
+
+ let mut go_to_definition_updated = false;
+ let mut hover_updated = false;
+ if let Some(hovered_hint) = editor
+ .visible_inlay_hints(cx)
+ .into_iter()
+ .skip_while(|hint| {
+ hint.position
+ .cmp(&previous_valid_anchor, &buffer_snapshot)
+ .is_lt()
+ })
+ .take_while(|hint| {
+ hint.position
+ .cmp(&next_valid_anchor, &buffer_snapshot)
+ .is_le()
+ })
+ .max_by_key(|hint| hint.id)
+ {
+ 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 {
+ 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,
+ cx,
+ );
+ }
+ }
+ ResolveState::Resolved => {
+ match cached_hint.label {
+ project::InlayHintLabel::String(_) => {
+ if let Some(tooltip) = cached_hint.tooltip {
+ hover_popover::hover_at_inlay(
+ editor,
+ InlayHover {
+ excerpt: excerpt_id,
+ tooltip: match tooltip {
+ InlayHintTooltip::String(text) => HoverBlock {
+ text,
+ kind: HoverBlockKind::PlainText,
+ },
+ InlayHintTooltip::MarkupContent(content) => {
+ HoverBlock {
+ text: content.value,
+ kind: content.kind,
+ }
+ }
+ },
+ triggered_from: hovered_offset,
+ range: InlayRange {
+ inlay_position: hovered_hint.position,
+ highlight_start: hint_start_offset,
+ highlight_end: hint_end_offset,
+ },
+ },
+ cx,
+ );
+ hover_updated = true;
+ }
+ }
+ project::InlayHintLabel::LabelParts(label_parts) => {
+ if let Some((hovered_hint_part, part_range)) =
+ hover_popover::find_hovered_hint_part(
+ label_parts,
+ hint_start_offset..hint_end_offset,
+ hovered_offset,
+ )
+ {
+ if let Some(tooltip) = hovered_hint_part.tooltip {
+ hover_popover::hover_at_inlay(
+ editor,
+ InlayHover {
+ excerpt: excerpt_id,
+ tooltip: match tooltip {
+ InlayHintLabelPartTooltip::String(text) => {
+ HoverBlock {
+ text,
+ kind: HoverBlockKind::PlainText,
+ }
+ }
+ InlayHintLabelPartTooltip::MarkupContent(
+ content,
+ ) => HoverBlock {
+ text: content.value,
+ kind: content.kind,
+ },
+ },
+ triggered_from: hovered_offset,
+ range: InlayRange {
+ inlay_position: hovered_hint.position,
+ highlight_start: part_range.start,
+ highlight_end: part_range.end,
+ },
+ },
+ cx,
+ );
+ hover_updated = true;
+ }
+ if let Some(location) = hovered_hint_part.location {
+ if let Some(buffer) =
+ cached_hint.position.buffer_id.and_then(|buffer_id| {
+ editor.buffer().read(cx).buffer(buffer_id)
+ })
+ {
+ go_to_definition_updated = true;
+ update_go_to_definition_link(
+ editor,
+ GoToDefinitionTrigger::InlayHint(
+ InlayRange {
+ inlay_position: hovered_hint.position,
+ highlight_start: part_range.start,
+ highlight_end: part_range.end,
+ },
+ LocationLink {
+ origin: Some(Location {
+ buffer,
+ range: cached_hint.position
+ ..cached_hint.position,
+ }),
+ target: location,
+ },
+ ),
+ cmd_held,
+ shift_held,
+ cx,
+ );
+ }
+ }
+ }
+ }
+ };
+ }
+ ResolveState::Resolving => {}
+ }
+ }
+ }
+
+ if !go_to_definition_updated {
+ update_go_to_definition_link(
+ editor,
+ GoToDefinitionTrigger::None,
+ cmd_held,
+ shift_held,
+ cx,
+ );
+ }
+ if !hover_updated {
+ hover_popover::hover_at(editor, None, cx);
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LinkDefinitionKind {
Symbol,
@@ -391,14 +582,21 @@ fn go_to_fetched_definition_of_kind(
#[cfg(test)]
mod tests {
use super::*;
- use crate::{editor_tests::init_test, test::editor_lsp_test_context::EditorLspTestContext};
+ use crate::{
+ display_map::ToDisplayPoint,
+ editor_tests::init_test,
+ inlay_hint_cache::tests::{cached_hint_labels, visible_hint_labels},
+ test::editor_lsp_test_context::EditorLspTestContext,
+ };
use futures::StreamExt;
use gpui::{
platform::{self, Modifiers, ModifiersChangedEvent},
View,
};
use indoc::indoc;
+ use language::language_settings::InlayHintSettings;
use lsp::request::{GotoDefinition, GotoTypeDefinition};
+ use util::assert_set_eq;
#[gpui::test]
async fn test_link_go_to_type_definition(cx: &mut gpui::TestAppContext) {
@@ -853,4 +1051,209 @@ mod tests {
"});
cx.foreground().run_until_parked();
}
+
+ #[gpui::test]
+ async fn test_link_go_to_inlay(cx: &mut gpui::TestAppContext) {
+ init_test(cx, |settings| {
+ settings.defaults.inlay_hints = Some(InlayHintSettings {
+ enabled: true,
+ show_type_hints: true,
+ show_parameter_hints: true,
+ show_other_hints: true,
+ })
+ });
+
+ let mut cx = EditorLspTestContext::new_rust(
+ lsp::ServerCapabilities {
+ inlay_hint_provider: Some(lsp::OneOf::Left(true)),
+ ..Default::default()
+ },
+ cx,
+ )
+ .await;
+ cx.set_state(indoc! {"
+ struct TestStruct;
+
+ fn main() {
+ let variableˇ = TestStruct;
+ }
+ "});
+ let hint_start_offset = cx.ranges(indoc! {"
+ struct TestStruct;
+
+ fn main() {
+ let variableˇ = TestStruct;
+ }
+ "})[0]
+ .start;
+ let hint_position = cx.to_lsp(hint_start_offset);
+ let target_range = cx.lsp_range(indoc! {"
+ struct «TestStruct»;
+
+ fn main() {
+ let variable = TestStruct;
+ }
+ "});
+
+ let expected_uri = cx.buffer_lsp_url.clone();
+ let inlay_label = ": TestStruct";
+ cx.lsp
+ .handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
+ let expected_uri = expected_uri.clone();
+ async move {
+ assert_eq!(params.text_document.uri, expected_uri);
+ Ok(Some(vec![lsp::InlayHint {
+ position: hint_position,
+ label: lsp::InlayHintLabel::LabelParts(vec![lsp::InlayHintLabelPart {
+ value: inlay_label.to_string(),
+ location: Some(lsp::Location {
+ uri: params.text_document.uri,
+ range: target_range,
+ }),
+ ..Default::default()
+ }]),
+ kind: Some(lsp::InlayHintKind::TYPE),
+ text_edits: None,
+ tooltip: None,
+ padding_left: Some(false),
+ padding_right: Some(false),
+ data: None,
+ }]))
+ }
+ })
+ .next()
+ .await;
+ cx.foreground().run_until_parked();
+ cx.update_editor(|editor, cx| {
+ let expected_layers = vec![inlay_label.to_string()];
+ assert_eq!(expected_layers, cached_hint_labels(editor));
+ assert_eq!(expected_layers, visible_hint_labels(editor, cx));
+ });
+
+ let inlay_range = cx
+ .ranges(indoc! {"
+ struct TestStruct;
+
+ fn main() {
+ let variable« »= TestStruct;
+ }
+ "})
+ .get(0)
+ .cloned()
+ .unwrap();
+ let hint_hover_position = cx.update_editor(|editor, cx| {
+ let snapshot = editor.snapshot(cx);
+ PointForPosition {
+ previous_valid: inlay_range.start.to_display_point(&snapshot),
+ next_valid: inlay_range.end.to_display_point(&snapshot),
+ exact_unclipped: inlay_range.end.to_display_point(&snapshot),
+ column_overshoot_after_line_end: (inlay_label.len() / 2) as u32,
+ }
+ });
+ // Press cmd to trigger highlight
+ cx.update_editor(|editor, cx| {
+ update_inlay_link_and_hover_points(
+ &editor.snapshot(cx),
+ hint_hover_position,
+ editor,
+ true,
+ false,
+ cx,
+ );
+ });
+ cx.foreground().run_until_parked();
+ cx.update_editor(|editor, cx| {
+ let snapshot = editor.snapshot(cx);
+ let actual_ranges = snapshot
+ .highlight_ranges::<LinkGoToDefinitionState>()
+ .map(|ranges| ranges.as_ref().clone().1)
+ .unwrap_or_default()
+ .into_iter()
+ .map(|range| match range {
+ DocumentRange::Text(range) => {
+ panic!("Unexpected regular text selection range {range:?}")
+ }
+ DocumentRange::Inlay(inlay_range) => inlay_range,
+ })
+ .collect::<Vec<_>>();
+
+ let buffer_snapshot = editor.buffer().update(cx, |buffer, cx| buffer.snapshot(cx));
+ let expected_highlight_start = snapshot.display_point_to_inlay_offset(
+ inlay_range.start.to_display_point(&snapshot),
+ Bias::Left,
+ );
+ let expected_ranges = vec![InlayRange {
+ inlay_position: buffer_snapshot.anchor_at(inlay_range.start, Bias::Right),
+ highlight_start: expected_highlight_start,
+ highlight_end: InlayOffset(expected_highlight_start.0 + inlay_label.len()),
+ }];
+ assert_set_eq!(actual_ranges, expected_ranges);
+ });
+
+ // Unpress cmd causes highlight to go away
+ cx.update_editor(|editor, cx| {
+ editor.modifiers_changed(
+ &platform::ModifiersChangedEvent {
+ modifiers: Modifiers {
+ cmd: false,
+ ..Default::default()
+ },
+ ..Default::default()
+ },
+ cx,
+ );
+ });
+ // Assert no link highlights
+ cx.update_editor(|editor, cx| {
+ let snapshot = editor.snapshot(cx);
+ let actual_ranges = snapshot
+ .highlight_ranges::<LinkGoToDefinitionState>()
+ .map(|ranges| ranges.as_ref().clone().1)
+ .unwrap_or_default()
+ .into_iter()
+ .map(|range| match range {
+ DocumentRange::Text(range) => {
+ panic!("Unexpected regular text selection range {range:?}")
+ }
+ DocumentRange::Inlay(inlay_range) => inlay_range,
+ })
+ .collect::<Vec<_>>();
+
+ assert!(actual_ranges.is_empty(), "When no cmd is pressed, should have no hint label selected, but got: {actual_ranges:?}");
+ });
+
+ // Cmd+click without existing definition requests and jumps
+ cx.update_editor(|editor, cx| {
+ editor.modifiers_changed(
+ &platform::ModifiersChangedEvent {
+ modifiers: Modifiers {
+ cmd: true,
+ ..Default::default()
+ },
+ ..Default::default()
+ },
+ cx,
+ );
+ update_inlay_link_and_hover_points(
+ &editor.snapshot(cx),
+ hint_hover_position,
+ editor,
+ true,
+ false,
+ cx,
+ );
+ });
+ cx.foreground().run_until_parked();
+ cx.update_editor(|editor, cx| {
+ go_to_fetched_type_definition(editor, hint_hover_position, false, cx);
+ });
+ cx.foreground().run_until_parked();
+ cx.assert_editor_state(indoc! {"
+ struct «TestStructˇ»;
+
+ fn main() {
+ let variable = TestStruct;
+ }
+ "});
+ }
}