diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-23 01:41:33 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-23 01:41:33 +0900 |
| commit | 421d98d9a52dd036acd5632f9049f4503c9add18 (patch) | |
| tree | 578d4bc15a7cb01a591393df85d0b9cdfd7d6ea2 /crates/shirabe/src/io/console_io.rs | |
| parent | 894764ecb04f9c456b9ebda77d155bf6128e2175 (diff) | |
| download | php-shirabe-421d98d9a52dd036acd5632f9049f4503c9add18.tar.gz php-shirabe-421d98d9a52dd036acd5632f9049f4503c9add18.tar.zst php-shirabe-421d98d9a52dd036acd5632f9049f4503c9add18.zip | |
refactor(io): hold QuestionHelper directly in ConsoleIO instead of HelperSet
Every ConsoleIO construction site only ever registers a single QuestionHelper
(production) or none (tests), and routing asks through HelperSet::get('question')
loses the concrete type, forcing a downcast back to QuestionHelper. Receive the
QuestionHelper in the constructor and hold it directly (in a RefCell, since
QuestionHelper::ask takes &mut self while the IOInterfaceImmutable ask methods are
&self), dropping the HelperSet field and the throwaway HelperSet built at each
call site.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/io/console_io.rs')
| -rw-r--r-- | crates/shirabe/src/io/console_io.rs | 50 |
1 files changed, 16 insertions, 34 deletions
diff --git a/crates/shirabe/src/io/console_io.rs b/crates/shirabe/src/io/console_io.rs index e6261c7..d6e10da 100644 --- a/crates/shirabe/src/io/console_io.rs +++ b/crates/shirabe/src/io/console_io.rs @@ -5,7 +5,6 @@ use crate::io::io_interface; use indexmap::IndexMap; use indexmap::indexmap; use shirabe_external_packages::composer::pcre::Preg; -use shirabe_external_packages::symfony::console::helper::HelperSet; use shirabe_external_packages::symfony::console::helper::ProgressBar; use shirabe_external_packages::symfony::console::helper::QuestionHelper; use shirabe_external_packages::symfony::console::helper::Table; @@ -37,26 +36,25 @@ pub struct ConsoleIO { pub(crate) input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>, pub(crate) output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>, - pub(crate) helper_set: HelperSet, + + /// `$helperSet` is flattened to `question_helper`. PHP stores a `HelperSet` and calls + /// `$this->helperSet->get('question')` on every ask. The Application class, which constructs + /// this class, registers a single `QuestionHelper`. So this port holds the `QuestionHelper` + /// directly instead of a `HelperSet`. + question_helper: RefCell<QuestionHelper>, + pub(crate) last_message: RefCell<String>, pub(crate) last_message_err: RefCell<String>, - /// @var float start_time: Option<f64>, - /// @var array<IOInterface::*, OutputInterface::VERBOSITY_*> verbosity_map: IndexMap<i64, i64>, } impl ConsoleIO { - /// Constructor. - /// - /// @param InputInterface $input The input instance - /// @param OutputInterface $output The output instance - /// @param HelperSet $helperSet The helperSet instance pub fn new( input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>, output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>, - helper_set: HelperSet, + question_helper: QuestionHelper, ) -> Self { let mut verbosity_map = IndexMap::new(); verbosity_map.insert(io_interface::QUIET, output_interface::VERBOSITY_QUIET); @@ -71,7 +69,7 @@ impl ConsoleIO { authentications: indexmap![], input, output, - helper_set, + question_helper: RefCell::new(question_helper), last_message: RefCell::new(String::new()), last_message_err: RefCell::new(String::new()), start_time: None, @@ -83,7 +81,6 @@ impl ConsoleIO { self.start_time = Some(start_time); } - /// @param string[]|string $messages fn do_write(&self, messages: PhpMixed, newline: bool, stderr: bool, verbosity: i64, raw: bool) { let mut sf_verbosity = *self.verbosity_map.get(&verbosity).unwrap_or(&0); if sf_verbosity > self.output.borrow().get_verbosity() { @@ -157,7 +154,6 @@ impl ConsoleIO { ); } - /// @param string[]|string $messages fn do_overwrite( &self, messages: PhpMixed, @@ -241,7 +237,6 @@ impl ConsoleIO { } pub fn get_progress_bar(&self, max: i64) -> ProgressBar { - // PHP ProgressBar::__construct default $minSecondsBetweenRedraws = 1 / 25. ProgressBar::new(self.get_error_output(), max, 1.0 / 25.0) } @@ -366,24 +361,16 @@ impl ConsoleIO { } } - /// Resolves the "question" helper and delegates to `QuestionHelper::ask`. + /// Delegates to `QuestionHelper::ask`. /// - /// PHP: `$this->helperSet->get('question')->ask($this->input, $this->getErrorOutput(), $question)`. - /// `HelperSet::get` and `QuestionHelper::ask` both surface PHP exceptions; ConsoleIO does not - /// catch them, so an unrecoverable error here is a PHP fatal. The double `Result` is collapsed: - /// the outer `anyhow::Result` (fatal) and the inner `MissingInputException` (unhandled, hence - /// also fatal in PHP) both abort. + /// PHP: `$helper->ask($this->input, $this->getErrorOutput(), $question)`. + /// `QuestionHelper::ask` surfaces PHP exceptions; ConsoleIO does not catch them, so an + /// unrecoverable error here is a PHP fatal. The double `Result` is collapsed: the outer + /// `anyhow::Result` (fatal) and the inner `MissingInputException` (unhandled, hence also fatal + /// in PHP) both abort. fn ask_question(&self, question: &Question) -> PhpMixed { - let helper_rc = self - .helper_set - .get("question") - .expect("the \"question\" helper is always registered"); let error_output = self.get_error_output(); - let mut helper = helper_rc.borrow_mut(); - let question_helper = (*helper) - .as_any_mut() - .downcast_mut::<QuestionHelper>() - .expect("the \"question\" helper is a QuestionHelper"); + let mut question_helper = self.question_helper.borrow_mut(); let mut input = self.input.borrow_mut(); question_helper .ask(&mut *input, error_output, question) @@ -561,16 +548,11 @@ impl IOInterfaceImmutable for ConsoleIO { question: String, choices: Vec<String>, default: PhpMixed, - // PHP: int|false attempts attempts: PhpMixed, error_message: String, multiselect: bool, ) -> PhpMixed { let choices: PhpMixed = PhpMixed::List(choices.into_iter().map(PhpMixed::String).collect()); - let _helper = self - .helper_set - .get("question") - .expect("the \"question\" helper is always registered"); let sanitized_question = Self::sanitize(PhpMixed::String(question), true) .as_string() .unwrap_or("") |
