[ty_test] Extract HoverOutput type from CheckOutput enum

Create a dedicated HoverOutput struct to hold hover result data,
replacing the inline fields in CheckOutput::Hover variant.

This allows implementing Unmatched and UnmatchedWithColumn traits
directly on HoverOutput, simplifying the CheckOutput implementations
to simple delegation.

Benefits:
- Better separation of concerns
- Cleaner trait implementations
- More consistent with Diagnostic handling
- Easier to extend HoverOutput in the future

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Douglas Creager 2025-10-08 13:52:58 -04:00
parent ac1b68c56d
commit 35a5fd767d
3 changed files with 37 additions and 21 deletions

View File

@ -8,6 +8,15 @@ use ruff_source_file::{LineIndex, OneIndexed};
use ruff_text_size::TextSize;
use std::ops::Range;
/// A hover result for testing hover assertions.
#[derive(Debug, Clone)]
pub(crate) struct HoverOutput {
/// The position where hover was requested
pub(crate) offset: TextSize,
/// The inferred type at that position
pub(crate) inferred_type: String,
}
/// Represents either a diagnostic or a hover result for matching against assertions.
#[derive(Debug, Clone)]
pub(crate) enum CheckOutput {
@ -15,12 +24,7 @@ pub(crate) enum CheckOutput {
Diagnostic(Diagnostic),
/// A hover result for testing hover assertions
Hover {
/// The position where hover was requested
offset: TextSize,
/// The inferred type at that position
inferred_type: String,
},
Hover(HoverOutput),
}
impl CheckOutput {
@ -32,7 +36,7 @@ impl CheckOutput {
.map_or(OneIndexed::from_zero_indexed(0), |range| {
line_index.line_index(range.start())
}),
CheckOutput::Hover { offset, .. } => line_index.line_index(*offset),
CheckOutput::Hover(hover) => line_index.line_index(hover.offset),
}
}
}

View File

@ -3,7 +3,7 @@
//! This module provides functionality to extract hover assertions from comments,
//! infer types at specified positions, and generate hover check outputs for matching.
use crate::check_output::CheckOutput;
use crate::check_output::{CheckOutput, HoverOutput};
use ruff_db::files::File;
use ruff_db::parsed::parsed_module;
use ruff_db::source::{line_index, source_text};
@ -107,10 +107,10 @@ pub(crate) fn generate_hover_outputs(
continue;
};
hover_outputs.push(CheckOutput::Hover {
hover_outputs.push(CheckOutput::Hover(HoverOutput {
offset: hover_offset,
inferred_type,
});
}));
}
}

View File

@ -12,7 +12,7 @@ use ruff_db::source::{SourceText, line_index, source_text};
use ruff_source_file::{LineIndex, OneIndexed};
use crate::assertion::{InlineFileAssertions, ParsedAssertion, UnparsedAssertion};
use crate::check_output::{CheckOutput, LineCheckOutputs, SortedCheckOutputs};
use crate::check_output::{CheckOutput, HoverOutput, LineCheckOutputs, SortedCheckOutputs};
use crate::db::Db;
#[derive(Debug, Default)]
@ -174,13 +174,28 @@ impl Unmatched for CheckOutput {
fn unmatched(&self) -> String {
match self {
CheckOutput::Diagnostic(diag) => diag.unmatched(),
CheckOutput::Hover { inferred_type, .. } => {
format!("{} hover result: {inferred_type}", "unexpected:".red())
}
CheckOutput::Hover(hover) => hover.unmatched(),
}
}
}
impl Unmatched for &HoverOutput {
fn unmatched(&self) -> String {
format!("{} hover result: {}", "unexpected:".red(), self.inferred_type)
}
}
impl UnmatchedWithColumn for &HoverOutput {
fn unmatched_with_column(&self, column: OneIndexed) -> String {
format!(
"{} {} hover result: {}",
"unexpected:".red(),
column,
self.inferred_type
)
}
}
impl Unmatched for &Diagnostic {
fn unmatched(&self) -> String {
maybe_add_undefined_reveal_clarification(
@ -267,8 +282,8 @@ impl Matcher {
CheckOutput::Diagnostic(diag) => {
failures.push(diag.unmatched_with_column(self.column(diag)));
}
CheckOutput::Hover { inferred_type, .. } => {
failures.push(format!("{} hover result: {inferred_type}", "unexpected:".red()));
CheckOutput::Hover(hover) => {
failures.push(hover.unmatched());
}
}
}
@ -401,15 +416,12 @@ impl Matcher {
// Find a hover output that matches the expected type
let position = unmatched.iter().position(|output| {
let CheckOutput::Hover {
inferred_type, ..
} = output
else {
let CheckOutput::Hover(hover_output) = output else {
return false;
};
// Compare the inferred type with the expected type
let inferred_type = discard_todo_metadata(inferred_type);
let inferred_type = discard_todo_metadata(&hover_output.inferred_type);
inferred_type == expected_type
});