aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/util/error_handler.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-11 02:39:35 +0900
committernsfisis <nsfisis@gmail.com>2026-06-11 02:39:35 +0900
commit6ae7e0d4b3eaf20e2d2cd3d000cf61ab0c9b6e83 (patch)
treee39261f4aa7314fe8c75142670c76591cdaccb92 /crates/shirabe/src/util/error_handler.rs
parent5d3232a80be4b989e89cc7ae4e3642cc5acae030 (diff)
downloadphp-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.rs39
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)) {