From 6ae7e0d4b3eaf20e2d2cd3d000cf61ab0c9b6e83 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Thu, 11 Jun 2026 02:39:35 +0900 Subject: 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) --- crates/shirabe/src/command/base_command.rs | 49 ++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 12 deletions(-) (limited to 'crates/shirabe/src/command/base_command.rs') diff --git a/crates/shirabe/src/command/base_command.rs b/crates/shirabe/src/command/base_command.rs index b1a1837..9218497 100644 --- a/crates/shirabe/src/command/base_command.rs +++ b/crates/shirabe/src/command/base_command.rs @@ -287,7 +287,14 @@ pub trait HasBaseCommandData { impl BaseCommand for C { fn get_application(&self) -> Result { - // TODO(phase-b): requires inner Symfony Command access + // PHP: parent::getApplication() returns Symfony Command::$application, the back-reference + // set by Application::add() -> $command->setApplication($this) when the command is + // registered. + // TODO(phase-c): the command holds no Application back-reference. Establishing it requires + // (1) modelling the Symfony command registry (add/find/run), which is an intentional + // todo!() stub, and (2) making Application shared (Rc>) with a Weak + // back-edge to break the Application<->command cycle. Until command registration runs, + // there is no application to return. todo!() } @@ -296,12 +303,15 @@ impl BaseCommand for C { _disable_plugins: Option, _disable_scripts: Option, ) -> Result { - // TODO(phase-b): depends on Application::get_composer, which is still stubbed. + // PHP: $this->composer ??= $this->getApplication()->getComposer(true, ...). + // TODO(phase-c): blocked on get_application() (see above) — it currently returns an owned + // `Application` by value, which a command cannot hold; a shared Application handle is the + // prerequisite. Application::getComposer itself is already implemented. let _ = RuntimeException { message: String::new(), code: 0, }; - todo!("require_composer pending Application::get_composer") + todo!("require_composer pending get_application() shared-handle support") } fn try_composer( @@ -309,8 +319,10 @@ impl BaseCommand for C { _disable_plugins: Option, _disable_scripts: Option, ) -> Option { - // TODO(phase-b): depends on Application::get_composer, which is still stubbed. - todo!("try_composer pending Application::get_composer") + // PHP: try { return $this->requireComposer(...); } catch (\RuntimeException $e) { return null; } + // TODO(phase-c): blocked on get_application() / require_composer (see above) — needs a + // shared Application handle the command can reach. + todo!("try_composer pending get_application() shared-handle support") } fn set_composer(&mut self, composer: PartialComposerHandle) { @@ -329,7 +341,10 @@ impl BaseCommand for C { fn get_io(&mut self) -> Rc> { if self.io().is_none() { - // TODO(phase-b): requires inner Symfony Application access + // PHP: $this->io = $this->getApplication() instanceof Application + // ? $this->getApplication()->getIO() : new NullIO(); + // TODO(phase-c): the application-IO branch needs get_application() (see above); until + // a shared Application handle exists we take the NullIO fallback (PHP's else branch). *self.io_mut() = Some(Rc::new(RefCell::new(NullIO::new()))); } @@ -348,6 +363,10 @@ impl BaseCommand for C { output: std::rc::Rc>, ) -> Result<()> { // initialize a plugin-enabled Composer instance, either local or global + // PHP also ORs in $this->getApplication()->getDisablePluginsByDefault() / + // getDisableScriptsByDefault(). + // TODO(phase-c): the application-default OR-terms need get_application() (see above); a + // shared Application handle is the prerequisite, so only the input flags are honoured here. let mut disable_plugins = input .borrow() .has_parameter_option(&["--no-plugins"], false); @@ -355,8 +374,6 @@ impl BaseCommand for C { .borrow() .has_parameter_option(&["--no-scripts"], false); - // TODO(phase-b): requires inner Symfony Application access for disable_plugins_by_default / disable_scripts_by_default - if self.is_self_update_command() { disable_plugins = true; disable_scripts = true; @@ -376,7 +393,10 @@ impl BaseCommand for C { composer }; if let Some(composer) = composer.as_ref() { - // TODO(phase-b): requires inner Symfony Command get_name access + // PHP: $this->getName() — the Symfony Command's configured name. + // TODO(phase-c): the command name lives in Symfony Command state (set via configure() + // -> setName()), which this port does not yet carry on BaseCommandData; it requires + // the Symfony Command base-class model (intentional todo!() stub). let command_name: String = todo!(); let mut pre_command_run_event = PreCommandRunEvent::new( PluginEvents::PRE_COMMAND_RUN.to_string(), @@ -505,7 +525,10 @@ impl BaseCommand for C { .borrow() .has_parameter_option(&["--no-scripts"], false); - // TODO(phase-b): requires inner Symfony Application access for disable_plugins_by_default / disable_scripts_by_default + // PHP: if ($app instanceof Application && $app->getDisablePluginsByDefault()) $disablePlugins = true; + // (same for getDisableScriptsByDefault()). + // TODO(phase-c): these application-default overrides need get_application() (see above) — + // a shared Application handle is the prerequisite, so only the passed/flag values apply. let disable_plugins_kind = if disable_plugins { crate::factory::DisablePlugins::All } else { @@ -826,6 +849,8 @@ impl BaseCommand for C { } } -// TODO(phase-b): bridge BaseCommand to Symfony Command for trait-object container usage. +// TODO(phase-c): bridge BaseCommand to Symfony Command for trait-object container usage. // Cannot blanket-impl a foreign trait for a local generic (orphan rule); each concrete -// command must impl symfony Command itself, or a wrapper type must be introduced. +// command must impl symfony Command itself, or a wrapper type must be introduced. This is the +// same orphan-rule blocker as Application::get_default_commands and is gated on the Symfony +// command-registry model, which is an intentional external-package todo!() stub. -- cgit v1.3.1