From 11cdaae87c37e479fea6c39447041c312410b101 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Tue, 4 Aug 2026 06:33:32 +0900 Subject: feat(plugin): instantiate plugin capabilities through the PHP RPC worker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getPluginCapability was a no-op returning None. Now it runs the real flow: class_exists in the worker, new $capabilityClass($ctorArgs) with the plugin's own phandle spliced in as $ctorArgs['plugin'], both instanceof checks answered by is_a in the child, and a per-interface Rust adapter over the resulting entity (CommandProvider and the plain Capability marker; anything else is an explicit error). getPluginCapabilities now propagates errors instead of swallowing them. Capable::get_capabilities widens from IndexMap to IndexMap: upstream casts the return with (array) and validates only the queried key, so the narrow type both rejected maps Composer accepts and made the invalidImplementationClassNames data provider unrepresentable. The old code also returned ' 0 ' (trimmed to the falsy '0') as a valid class name where upstream throws; the rewritten validation follows upstream's empty/is_string/trim sequence. CommandProvider::get_commands returns BaseCommand adapters whose name is read back over RPC after the PHP constructor ran configure(); executing one still needs the PHP-side Symfony Application and stays an explicit error. The is_array / instanceof BaseCommand checks that upstream's Application::getPluginCommands performs on the raw getCommands value live in the adapter, because Vec> asserts every element up front. Ports testCommandProviderCapability (plugin-v8 end to end against the real worker) and testQueryingWithInvalidCapabilityClassNameThrows (all eight provider cases); the two tests that pass a PHPUnit mock plugin into PHP stay ignored — a Rust-native mock has no PHP-side entity to cross the boundary as $ctorArgs['plugin']. Co-Authored-By: Claude Fable 5 --- crates/shirabe/src/plugin/capable.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'crates/shirabe/src/plugin/capable.rs') diff --git a/crates/shirabe/src/plugin/capable.rs b/crates/shirabe/src/plugin/capable.rs index 830a7dab..3d3b8e3b 100644 --- a/crates/shirabe/src/plugin/capable.rs +++ b/crates/shirabe/src/plugin/capable.rs @@ -1,9 +1,12 @@ //! ref: composer/src/Composer/Plugin/Capable.php use indexmap::IndexMap; +use shirabe_php_shim::PhpMixed; // The sole implementor is the PHP plugin proxy (Composer itself never implements Capable), so -// the trait is fallible: the answer crosses the RPC boundary. +// the trait is fallible: the answer crosses the RPC boundary. Values are PhpMixed, not String: +// PHP's getCapabilities() may return anything, and PluginManager validates only the queried +// key, so narrowing the type here would reject maps upstream Composer accepts. pub trait Capable { - fn get_capabilities(&self) -> anyhow::Result>; + fn get_capabilities(&self) -> anyhow::Result>; } -- cgit v1.3.1