(fixture: &ParsedFixture)
| 485 | } |
| 486 | |
| 487 | async fn run_hover(fixture: &ParsedFixture) -> Result<(), String> { |
| 488 | let backend = create_fixture_backend(); |
| 489 | let uri = open_files(&backend, fixture).await; |
| 490 | let source = &fixture.files[fixture.cursor_file].content; |
| 491 | |
| 492 | // If there are explicit expect_hover assertions (symbol => substring), |
| 493 | // find each symbol in the source and hover over it. |
| 494 | if !fixture.meta.expect_hover.is_empty() { |
| 495 | for (symbol, expected_substring) in &fixture.meta.expect_hover { |
| 496 | let offset = source.find(symbol.as_str()).ok_or_else(|| { |
| 497 | format!("Symbol `{symbol}` not found in fixture source for hover assertion") |
| 498 | })?; |
| 499 | |
| 500 | let before = &source[..offset]; |
| 501 | let line = before.chars().filter(|&c| c == '\n').count() as u32; |
| 502 | let last_nl = before.rfind('\n').map(|i| i + 1).unwrap_or(0); |
| 503 | let character = before[last_nl..].len() as u32; |
| 504 | |
| 505 | let params = HoverParams { |
| 506 | text_document_position_params: TextDocumentPositionParams { |
| 507 | text_document: TextDocumentIdentifier { uri: uri.clone() }, |
| 508 | position: Position { line, character }, |
| 509 | }, |
| 510 | work_done_progress_params: WorkDoneProgressParams::default(), |
| 511 | }; |
| 512 | |
| 513 | let hover = backend |
| 514 | .hover(params) |
| 515 | .await |
| 516 | .map_err(|e| format!("Hover request failed: {e}"))?; |
| 517 | |
| 518 | match hover { |
| 519 | Some(h) => { |
| 520 | let hover_text = extract_hover_text(&h); |
| 521 | if !hover_text.contains(expected_substring.as_str()) { |
| 522 | return Err(format!( |
| 523 | "Hover on `{symbol}` expected to contain `{expected_substring}`, got:\n{hover_text}" |
| 524 | )); |
| 525 | } |
| 526 | } |
| 527 | None => { |
| 528 | return Err(format!("No hover result for symbol `{symbol}`")); |
| 529 | } |
| 530 | } |
| 531 | } |
| 532 | return Ok(()); |
| 533 | } |
| 534 | |
| 535 | // Fallback: hover at the cursor position and check expect lines as substrings. |
| 536 | let position = Position { |
| 537 | line: fixture.cursor_line, |
| 538 | character: fixture.cursor_char, |
| 539 | }; |
| 540 | |
| 541 | let params = HoverParams { |
| 542 | text_document_position_params: TextDocumentPositionParams { |
| 543 | text_document: TextDocumentIdentifier { uri }, |
| 544 | position, |
no test coverage detected