From 087020525d364e1e5bb3d9b41d020704b068c59c Mon Sep 17 00:00:00 2001 From: nsfisis Date: Mon, 20 Jul 2026 05:21:06 +0900 Subject: fix(auditor): restore instanceof ConsoleIO semantics for BufferIO PHP's BufferIO extends ConsoleIO, so $io instanceof ConsoleIO matches it; the port models that inheritance as composition, making the plain ConsoleIO downcast reject BufferIO and throw where PHP renders tables. Also try a BufferIO downcast and unwrap its inner ConsoleIO, which unblocks the two FORMAT_TABLE cases and un-ignores test_audit. Co-Authored-By: Claude Fable 5 --- crates/shirabe/src/advisory/auditor.rs | 18 ++++++++++++++++-- crates/shirabe/tests/advisory/auditor_test.rs | 4 ---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/crates/shirabe/src/advisory/auditor.rs b/crates/shirabe/src/advisory/auditor.rs index 32e34380..ff93268a 100644 --- a/crates/shirabe/src/advisory/auditor.rs +++ b/crates/shirabe/src/advisory/auditor.rs @@ -433,7 +433,14 @@ impl Auditor { match format { Self::FORMAT_TABLE => { let io_ref = io.borrow(); - let io_as_console = io_ref.as_any().downcast_ref::(); + // PHP: `$io instanceof ConsoleIO`. BufferIO extends ConsoleIO in PHP but is + // modeled as composition here, so also unwrap it to its inner ConsoleIO. + let io_as_console = io_ref.as_any().downcast_ref::().or_else(|| { + io_ref + .as_any() + .downcast_ref::() + .map(|buffer_io| &buffer_io.inner) + }); if io_as_console.is_none() { return Err(InvalidArgumentException { message: format!( @@ -605,7 +612,14 @@ impl Auditor { } let io_ref = io.borrow(); - let io_as_console = io_ref.as_any().downcast_ref::(); + // PHP: `$io instanceof ConsoleIO`. BufferIO extends ConsoleIO in PHP but is modeled as + // composition here, so also unwrap it to its inner ConsoleIO. + let io_as_console = io_ref.as_any().downcast_ref::().or_else(|| { + io_ref + .as_any() + .downcast_ref::() + .map(|buffer_io| &buffer_io.inner) + }); if io_as_console.is_none() { return Err(InvalidArgumentException { message: format!( diff --git a/crates/shirabe/tests/advisory/auditor_test.rs b/crates/shirabe/tests/advisory/auditor_test.rs index dd904632..2b86718b 100644 --- a/crates/shirabe/tests/advisory/auditor_test.rs +++ b/crates/shirabe/tests/advisory/auditor_test.rs @@ -390,10 +390,6 @@ fn get_repo_set() -> RepositorySet { /// ref: AuditorTest::testAudit (auditProvider). #[test] -#[ignore = "all 10 cases faithfully ported; the 2 FORMAT_TABLE cases cannot run because \ - BufferIO does not downcast to ConsoleIO (PHP's `BufferIO extends ConsoleIO` is \ - modeled as composition in Rust), so the table-rendering path is unreachable and \ - the whole function stays ignored until the src supports it"] fn test_audit() { #[derive(Clone)] struct Case { -- cgit v1.3.1