Reproduce #33715 in a test
This commit is contained in:
parent
64c413b9b6
commit
a61e478152
1 changed files with 234 additions and 0 deletions
|
@ -1883,4 +1883,238 @@ mod tests {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_hover_on_inlay_hint_types(cx: &mut gpui::TestAppContext) {
|
||||||
|
use crate::{DisplayPoint, PointForPosition};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::{self, AtomicUsize};
|
||||||
|
|
||||||
|
init_test(cx, |settings| {
|
||||||
|
settings.defaults.inlay_hints = Some(InlayHintSettings {
|
||||||
|
enabled: true,
|
||||||
|
show_type_hints: true,
|
||||||
|
show_value_hints: true,
|
||||||
|
show_parameter_hints: true,
|
||||||
|
show_other_hints: true,
|
||||||
|
edit_debounce_ms: 0,
|
||||||
|
scroll_debounce_ms: 0,
|
||||||
|
show_background: false,
|
||||||
|
toggle_on_modifiers_press: None,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut cx = EditorLspTestContext::new_rust(
|
||||||
|
lsp::ServerCapabilities {
|
||||||
|
hover_provider: Some(lsp::HoverProviderCapability::Simple(true)),
|
||||||
|
inlay_hint_provider: Some(lsp::OneOf::Right(
|
||||||
|
lsp::InlayHintServerCapabilities::Options(lsp::InlayHintOptions {
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
cx.set_state(indoc! {r#"
|
||||||
|
fn main() {
|
||||||
|
let foo = "foo".to_string();
|
||||||
|
let bar: String = "bar".to_string();ˇ
|
||||||
|
}
|
||||||
|
"#});
|
||||||
|
|
||||||
|
// Set up inlay hint handler
|
||||||
|
let buffer_text = cx.buffer_text();
|
||||||
|
let hint_position = cx.to_lsp(buffer_text.find("foo =").unwrap() + 3);
|
||||||
|
cx.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
|
||||||
|
move |_, _params, _| async move {
|
||||||
|
Ok(Some(vec![lsp::InlayHint {
|
||||||
|
position: hint_position,
|
||||||
|
label: lsp::InlayHintLabel::String(": String".to_string()),
|
||||||
|
kind: Some(lsp::InlayHintKind::TYPE),
|
||||||
|
text_edits: None,
|
||||||
|
tooltip: None,
|
||||||
|
padding_left: Some(false),
|
||||||
|
padding_right: Some(false),
|
||||||
|
data: None,
|
||||||
|
}]))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.next()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
cx.background_executor.run_until_parked();
|
||||||
|
|
||||||
|
// Verify inlay hint is displayed
|
||||||
|
cx.update_editor(|editor, _, cx| {
|
||||||
|
let expected_layers = vec![": String".to_string()];
|
||||||
|
assert_eq!(expected_layers, visible_hint_labels(editor, cx));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up hover handler that should be called for both inlay hint and explicit type
|
||||||
|
let hover_count = Arc::new(AtomicUsize::new(0));
|
||||||
|
let hover_count_clone = hover_count.clone();
|
||||||
|
let _hover_requests =
|
||||||
|
cx.set_request_handler::<lsp::request::HoverRequest, _, _>(move |_, params, _| {
|
||||||
|
let count = hover_count_clone.clone();
|
||||||
|
async move {
|
||||||
|
let current = count.fetch_add(1, atomic::Ordering::SeqCst);
|
||||||
|
println!(
|
||||||
|
"Hover request {} at position: {:?}",
|
||||||
|
current + 1,
|
||||||
|
params.text_document_position_params.position
|
||||||
|
);
|
||||||
|
Ok(Some(lsp::Hover {
|
||||||
|
contents: lsp::HoverContents::Markup(lsp::MarkupContent {
|
||||||
|
kind: lsp::MarkupKind::Markdown,
|
||||||
|
value:
|
||||||
|
"```rust\nstruct String\n```\n\nA UTF-8 encoded, growable string."
|
||||||
|
.to_string(),
|
||||||
|
}),
|
||||||
|
range: None,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test hovering over the inlay hint type
|
||||||
|
// Get the position where the inlay hint is displayed
|
||||||
|
let inlay_range = cx
|
||||||
|
.ranges(indoc! {r#"
|
||||||
|
fn main() {
|
||||||
|
let foo« »= "foo".to_string();
|
||||||
|
let bar: String = "bar".to_string();
|
||||||
|
}
|
||||||
|
"#})
|
||||||
|
.first()
|
||||||
|
.cloned()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Create a PointForPosition that simulates hovering over the inlay hint
|
||||||
|
let point_for_position = cx.update_editor(|editor, window, cx| {
|
||||||
|
let snapshot = editor.snapshot(window, cx);
|
||||||
|
let previous_valid = inlay_range.start.to_display_point(&snapshot);
|
||||||
|
let next_valid = inlay_range.end.to_display_point(&snapshot);
|
||||||
|
// Position over the "S" in "String" of the inlay hint ": String"
|
||||||
|
let exact_unclipped = DisplayPoint::new(
|
||||||
|
previous_valid.row(),
|
||||||
|
previous_valid.column() + 2, // Skip past ": " to hover over "String"
|
||||||
|
);
|
||||||
|
PointForPosition {
|
||||||
|
previous_valid,
|
||||||
|
next_valid,
|
||||||
|
exact_unclipped,
|
||||||
|
column_overshoot_after_line_end: 0,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update hovered link to trigger hover logic for inlay hints
|
||||||
|
cx.update_editor(|editor, window, cx| {
|
||||||
|
let snapshot = editor.snapshot(window, cx);
|
||||||
|
update_inlay_link_and_hover_points(
|
||||||
|
&snapshot,
|
||||||
|
point_for_position,
|
||||||
|
editor,
|
||||||
|
false, // secondary_held
|
||||||
|
false, // shift_held
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for potential hover popover
|
||||||
|
cx.background_executor
|
||||||
|
.advance_clock(Duration::from_millis(get_hover_popover_delay(&cx) + 100));
|
||||||
|
cx.background_executor.run_until_parked();
|
||||||
|
|
||||||
|
// Check if hover request was made for inlay hint
|
||||||
|
let inlay_hover_request_count = hover_count.load(atomic::Ordering::SeqCst);
|
||||||
|
println!(
|
||||||
|
"Hover requests after inlay hint hover: {}",
|
||||||
|
inlay_hover_request_count
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if hover popover is shown for inlay hint
|
||||||
|
let has_inlay_hover = cx.editor(|editor, _, _| {
|
||||||
|
println!(
|
||||||
|
"Inlay hint hover - info_popovers: {}",
|
||||||
|
editor.hover_state.info_popovers.len()
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"Inlay hint hover - info_task: {:?}",
|
||||||
|
editor.hover_state.info_task.is_some()
|
||||||
|
);
|
||||||
|
editor.hover_state.info_popovers.len() > 0
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear hover state
|
||||||
|
cx.update_editor(|editor, _, cx| {
|
||||||
|
hide_hover(editor, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test hovering over the explicit type
|
||||||
|
// Find the position of "String" in the explicit type annotation
|
||||||
|
let explicit_string_point = cx.display_point(indoc! {r#"
|
||||||
|
fn main() {
|
||||||
|
let foo = "foo".to_string();
|
||||||
|
let bar: Sˇtring = "bar".to_string();
|
||||||
|
}
|
||||||
|
"#});
|
||||||
|
|
||||||
|
// Use hover_at to trigger hover on explicit type
|
||||||
|
cx.update_editor(|editor, window, cx| {
|
||||||
|
let snapshot = editor.snapshot(window, cx);
|
||||||
|
let anchor = snapshot
|
||||||
|
.buffer_snapshot
|
||||||
|
.anchor_before(explicit_string_point.to_offset(&snapshot, Bias::Left));
|
||||||
|
hover_at(editor, Some(anchor), window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for hover request
|
||||||
|
cx.background_executor
|
||||||
|
.advance_clock(Duration::from_millis(get_hover_popover_delay(&cx) + 100));
|
||||||
|
cx.background_executor.run_until_parked();
|
||||||
|
|
||||||
|
// Check if hover popover is shown for explicit type
|
||||||
|
let has_explicit_hover = cx.editor(|editor, _, _| {
|
||||||
|
println!(
|
||||||
|
"Explicit type hover - info_popovers: {}",
|
||||||
|
editor.hover_state.info_popovers.len()
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"Explicit type hover - info_task: {:?}",
|
||||||
|
editor.hover_state.info_task.is_some()
|
||||||
|
);
|
||||||
|
editor.hover_state.info_popovers.len() > 0
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check total hover requests
|
||||||
|
let total_requests = hover_count.load(atomic::Ordering::SeqCst);
|
||||||
|
println!("Total hover requests: {}", total_requests);
|
||||||
|
|
||||||
|
// The test should fail here - inlay hints don't show hover popovers but explicit types do
|
||||||
|
println!("Has inlay hover: {}", has_inlay_hover);
|
||||||
|
println!("Has explicit hover: {}", has_explicit_hover);
|
||||||
|
|
||||||
|
// This test demonstrates issue #33715: hovering over type information in inlay hints
|
||||||
|
// does not show hover popovers, while hovering over explicit types does.
|
||||||
|
|
||||||
|
// Expected behavior: Both should show hover popovers
|
||||||
|
// Actual behavior: Only explicit types show hover popovers
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
has_explicit_hover,
|
||||||
|
"Hover popover should be shown when hovering over explicit type"
|
||||||
|
);
|
||||||
|
|
||||||
|
// This assertion should fail, demonstrating the bug
|
||||||
|
assert!(
|
||||||
|
has_inlay_hover,
|
||||||
|
"Hover popover should be shown when hovering over inlay hint type (Issue #33715). \
|
||||||
|
Inlay hint hover requests: {}, Explicit type hover requests: {}",
|
||||||
|
inlay_hover_request_count,
|
||||||
|
total_requests - inlay_hover_request_count
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue