From 318ea948f5932dfa7942081a269d62fd7161a9bf Mon Sep 17 00:00:00 2001 From: nsfisis Date: Mon, 8 Jun 2026 01:54:56 +0900 Subject: feat(phase-c): resolve reflection/downcast phase-b TODOs Resolve category F phase-b TODOs (class-string, instanceof, get_class, method_exists, __FILE__, Reflection API, downcast). - VcsRepository: dispatch drivers through a VcsDriverKind enum (instantiate/supports/php_class_name) and add constructors to the concrete VCS drivers - repository downcasts via RepositoryInterfaceHandle::downcast_rc and as_any (init/show commands, vcs ValidatingArrayLoader) - BaseCommand::is_self_update_command override replaces an instanceof - Factory::create narrows PartialComposer to ComposerHandle via as_full - InstalledVersions gains set_self_dir/set_installed_is_local_dir, replacing Reflection-based static property mutation - ClassLoader::as_array_iter ports the PHP (array) cast - drop the unnecessary __FILE__ phar branch in self-update application get_class(command) reclassified TODO(plugin); buffer_io StreamableInputInterface downcast and the ValidatingArrayLoader trait redesign left as tracked TODOs. Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/shirabe/src/console/application.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'crates/shirabe/src/console') diff --git a/crates/shirabe/src/console/application.rs b/crates/shirabe/src/console/application.rs index 0ff2893..fbde9bd 100644 --- a/crates/shirabe/src/console/application.rs +++ b/crates/shirabe/src/console/application.rs @@ -103,10 +103,7 @@ impl Application { pub fn new(name: String, mut version: String) -> Self { let mut inner = BaseApplication::new(&name, &version); - // TODO(phase-b): method_exists check requires reflection-style API on BaseApplication - if true { - inner.set_catch_errors(true); - } + inner.set_catch_errors(true); // PHP: static $shutdownRegistered = false; — register only once globally static SHUTDOWN_REGISTERED: std::sync::OnceLock<()> = std::sync::OnceLock::new(); @@ -436,8 +433,9 @@ impl Application { for command in self.get_plugin_commands()? { let cmd_name = command.get_name().unwrap_or_default(); if self.inner.has(&cmd_name) { - // TODO(phase-b): get_class needs a Command-aware overload; default - // to a placeholder while the trait downcast story is settled. + // TODO(plugin): PHP uses get_class($command) for the skipped-command class + // name. Plugin command discovery (get_plugin_commands) is unimplemented, so + // this loop never runs; wire the concrete class name with the plugin API. let cls = String::new(); plugin_warnings.push(format!("Plugin command {} ({}) would override a Composer command and has been skipped", cmd_name, cls)); } else { @@ -1003,7 +1001,7 @@ impl Application { crate::factory::DisablePlugins::None }; match Factory::create(io_for_factory, None, disable_plugins_enum, disable_scripts) { - Ok(c) => self.composer = Some(c), + Ok(c) => self.composer = Some(c.upcast()), Err(e) => { if e.downcast_ref::().is_some() || e.downcast_ref::().is_some() -- cgit v1.3.1