diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-11 02:39:35 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-11 02:39:35 +0900 |
| commit | 6ae7e0d4b3eaf20e2d2cd3d000cf61ab0c9b6e83 (patch) | |
| tree | e39261f4aa7314fe8c75142670c76591cdaccb92 /crates/shirabe/src/util/error_handler.rs | |
| parent | 5d3232a80be4b989e89cc7ae4e3642cc5acae030 (diff) | |
| download | php-shirabe-6ae7e0d4b3eaf20e2d2cd3d000cf61ab0c9b6e83.tar.gz php-shirabe-6ae7e0d4b3eaf20e2d2cd3d000cf61ab0c9b6e83.tar.zst php-shirabe-6ae7e0d4b3eaf20e2d2cd3d000cf61ab0c9b6e83.zip | |
feat(console): resolve phase-b TODOs in doRun and IO wiring
Wire up ConsoleIO with HelperSet/QuestionHelper, register the
ErrorHandler with the IO instance, and fall back to a default output
in run(). Replace resolved phase-b TODOs across the console, command,
io, factory, installer, dependency_resolver, and util modules; reclassify
the remaining blockers (typed Symfony command registry, stdin resource
caching) as phase-c.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/util/error_handler.rs')
| -rw-r--r-- | crates/shirabe/src/util/error_handler.rs | 39 |
1 files changed, 20 insertions, 19 deletions
diff --git a/crates/shirabe/src/util/error_handler.rs b/crates/shirabe/src/util/error_handler.rs index c0648be..e0590d9 100644 --- a/crates/shirabe/src/util/error_handler.rs +++ b/crates/shirabe/src/util/error_handler.rs @@ -1,18 +1,21 @@ //! ref: composer/src/Composer/Util/ErrorHandler.php use crate::io::IOInterface; +use crate::io::IOInterfaceImmutable; use shirabe_php_shim::{ E_ALL, E_DEPRECATED, E_USER_DEPRECATED, E_USER_WARNING, E_WARNING, ErrorException, FILTER_VALIDATE_BOOLEAN, PHP_EOL, PhpMixed, STDERR, debug_backtrace, error_reporting, filter_var, ini_get, is_resource, set_error_handler, }; -use std::sync::{Mutex, OnceLock}; +use std::cell::{Cell, RefCell}; +use std::rc::Rc; -static IO: OnceLock<Mutex<Option<Box<dyn IOInterface + Send>>>> = OnceLock::new(); -static HAS_SHOWN_DEPRECATION_NOTICE: Mutex<i64> = Mutex::new(0); - -fn io() -> &'static Mutex<Option<Box<dyn IOInterface + Send>>> { - IO.get_or_init(|| Mutex::new(None)) +// PHP keeps `$io` / `$hasShownDeprecationNotice` as process-global statics. Composer runs +// single-threaded, so thread-locals on the main thread reproduce that faithfully while letting +// us hold the same shared (`Rc<RefCell<dyn IOInterface>>`) IO instance the application uses. +thread_local! { + static IO: RefCell<Option<Rc<RefCell<dyn IOInterface>>>> = const { RefCell::new(None) }; + static HAS_SHOWN_DEPRECATION_NOTICE: Cell<i64> = const { Cell::new(0) }; } pub struct ErrorHandler; @@ -65,18 +68,17 @@ impl ErrorHandler { }); } - let mut io_guard = io().lock().unwrap(); - if io_guard.is_some() { - let has_shown = *HAS_SHOWN_DEPRECATION_NOTICE.lock().unwrap(); - if has_shown > 0 && !io_guard.as_ref().unwrap().is_verbose() { + let io = IO.with(|cell| cell.borrow().clone()); + if let Some(io) = io { + let has_shown = HAS_SHOWN_DEPRECATION_NOTICE.with(|c| c.get()); + if has_shown > 0 && !io.is_verbose() { if has_shown == 1 { - io_guard.as_mut().unwrap().write_error("<warning>More deprecation notices were hidden, run again with `-v` to show them.</warning>"); - *HAS_SHOWN_DEPRECATION_NOTICE.lock().unwrap() = 2; + io.write_error("<warning>More deprecation notices were hidden, run again with `-v` to show them.</warning>"); + HAS_SHOWN_DEPRECATION_NOTICE.with(|c| c.set(2)); } return Ok(true); } - *HAS_SHOWN_DEPRECATION_NOTICE.lock().unwrap() = 1; - drop(io_guard); + HAS_SHOWN_DEPRECATION_NOTICE.with(|c| c.set(1)); Self::output_warning( &format!("Deprecation Notice: {} in {}:{}", message, file, line), false, @@ -86,17 +88,17 @@ impl ErrorHandler { Ok(true) } - pub fn register(io: Option<Box<dyn IOInterface + Send>>) { + pub fn register(io: Option<Rc<RefCell<dyn IOInterface>>>) { set_error_handler(|level, message, file, line| { Self::handle(level, message.to_string(), file.to_string(), line).unwrap_or(true) }); error_reporting(Some(E_ALL)); - *self::io().lock().unwrap() = io; + IO.with(|cell| *cell.borrow_mut() = io); } fn output_warning(message: &str, output_even_without_io: bool) { - let mut io_guard = io().lock().unwrap(); - if let Some(io) = io_guard.as_mut() { + let io = IO.with(|cell| cell.borrow().clone()); + if let Some(io) = io { io.write_error(&format!("<warning>{}</warning>", message)); if io.is_verbose() { io.write_error("<warning>Stack trace:</warning>"); @@ -122,7 +124,6 @@ impl ErrorHandler { } return; } - drop(io_guard); if output_even_without_io { if is_resource(&PhpMixed::Int(STDERR)) { |
