From ebcb4a7f013c0511dd6617686395cef17822d1e2 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 2 Aug 2026 17:32:35 +0900 Subject: feat(console): return shared style handles from OutputFormatter::get_style PHP's getStyle returns the shared style instance (reference semantics), which the previous Box-returning signature could not express, leaving a todo!(). Store each style behind Rc> and hand out handle clones, per the shared-ownership policy. Co-Authored-By: Claude Fable 5 --- .../symfony/console/formatter/output_formatter.rs | 29 ++++++++++++++-------- .../formatter/output_formatter_interface.rs | 5 +++- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'crates/shirabe-external-packages') diff --git a/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs b/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs index bb04f61d..f8a5db4c 100644 --- a/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs +++ b/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs @@ -13,7 +13,12 @@ use shirabe_php_shim::php_regex; #[derive(Debug)] pub struct OutputFormatter { decorated: bool, - styles: indexmap::IndexMap>, + // PHP objects have reference semantics: get_style must hand out the shared + // style instance, so each style is held behind an Rc> handle. + styles: indexmap::IndexMap< + String, + std::rc::Rc>>, + >, style_stack: OutputFormatterStyleStack, } @@ -99,7 +104,7 @@ impl OutputFormatter { string: &str, ) -> anyhow::Result>> { if let Some(style) = self.styles.get(string) { - return Ok(Some(style.clone_box())); + return Ok(Some(style.borrow().clone_box())); } let mut matches: Vec> = vec![]; @@ -231,8 +236,10 @@ impl OutputFormatterInterface for OutputFormatter { } fn set_style(&mut self, name: &str, style: Box) { - self.styles - .insert(shirabe_php_shim::strtolower(name), style); + self.styles.insert( + shirabe_php_shim::strtolower(name), + std::rc::Rc::new(std::cell::RefCell::new(style)), + ); } fn has_style(&self, name: &str) -> bool { @@ -240,7 +247,11 @@ impl OutputFormatterInterface for OutputFormatter { .contains_key(&shirabe_php_shim::strtolower(name)) } - fn get_style(&self, name: &str) -> anyhow::Result> { + fn get_style( + &self, + name: &str, + ) -> anyhow::Result>>> + { if !self.has_style(name) { return Err(anyhow::anyhow!(InvalidArgumentException( shirabe_php_shim::InvalidArgumentException { @@ -253,11 +264,9 @@ impl OutputFormatterInterface for OutputFormatter { ))); } - // PHP returns the shared style instance; ownership cannot be expressed without Clone on - // the trait object. - // TODO(phase-c): returning a shared style here needs an Rc/Clone strategy in Phase C. - let _ = &self.styles[&shirabe_php_shim::strtolower(name)]; - todo!() + Ok(std::rc::Rc::clone( + &self.styles[&shirabe_php_shim::strtolower(name)], + )) } fn format(&mut self, message: Option<&str>) -> anyhow::Result> { diff --git a/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter_interface.rs b/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter_interface.rs index a436ad8c..ad2b6954 100644 --- a/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter_interface.rs +++ b/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter_interface.rs @@ -19,7 +19,10 @@ pub trait OutputFormatterInterface: shirabe_php_shim::AsAny { /// Gets style options from style with specified name. /// /// Throws InvalidArgumentException when style isn't defined. - fn get_style(&self, name: &str) -> anyhow::Result>; + fn get_style( + &self, + name: &str, + ) -> anyhow::Result>>>; /// Formats a message according to the given styles. fn format(&mut self, message: Option<&str>) -> anyhow::Result>; -- cgit v1.3.1