From 9b444a9a879b75a6af3d3c7ba8b9a4294574c3ec Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 5 Aug 2026 03:58:03 +0900 Subject: feat(plugin): run plugin-provided commands in a worker-side application A same-FQCN Composer\Console\Application, hand-written under the new php/runtime/ tree, hosts CommandProvider commands inside the PHP worker: PhpCommandProxy overrides run() and forwards the stringified input, so the real Symfony machinery binds, validates and executes against the live command object, while help/list render Rust-side from a definition read back at construction. Reverse \Shirabe\RustCommandStub rows let a plugin command invoke built-in commands back in the Rust process, keeping every command on the side whose helper set it was written for. Composer\EventDispatcher\Event moves from a generated stub to a dual-mode runtime class: the real BaseCommand::initialize constructs a PreCommandRunEvent natively in the worker, which a proxy-only constructor guard rejected. Its PRE_COMMAND_RUN dispatch reaches a new EventDispatcher stub whose dispatch supports the observably-no-op no-listener case and fails explicitly otherwise. The stub generator now accepts runtime-provided classes as stub bases (never as targets) and cross-checks the Application handoff property table against the real class. Co-Authored-By: Claude Fable 5 --- crates/shirabe-php-rpc/src/lib.rs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'crates/shirabe-php-rpc/src') diff --git a/crates/shirabe-php-rpc/src/lib.rs b/crates/shirabe-php-rpc/src/lib.rs index ba5443d2..ef11d542 100644 --- a/crates/shirabe-php-rpc/src/lib.rs +++ b/crates/shirabe-php-rpc/src/lib.rs @@ -563,8 +563,8 @@ const GLUE_SCRIPT: &str = include_str!("../php/worker.php"); /// generator's `--check` mode verifies both the file contents and this list). const STUB_FILES: &[(&str, &str)] = &[ ( - "Composer/EventDispatcher/Event.php", - include_str!("../php/stubs/Composer/EventDispatcher/Event.php"), + "Composer/EventDispatcher/EventDispatcher.php", + include_str!("../php/stubs/Composer/EventDispatcher/EventDispatcher.php"), ), ( "Composer/Script/Event.php", @@ -640,6 +640,24 @@ const STUB_FILES: &[(&str, &str)] = &[ ), ]; +/// Hand-written worker-side classes (two-world implementations with behavior of their own, not +/// mechanical proxies), written into the same autoload directory as the generated stubs so the +/// prepended stub autoloader resolves their FQCNs ahead of any real class file. +const RUNTIME_FILES: &[(&str, &str)] = &[ + ( + "Composer/Console/Application.php", + include_str!("../php/runtime/Composer/Console/Application.php"), + ), + ( + "Composer/EventDispatcher/Event.php", + include_str!("../php/runtime/Composer/EventDispatcher/Event.php"), + ), + ( + "Shirabe/RustCommandStub.php", + include_str!("../php/runtime/Shirabe/RustCommandStub.php"), + ), +]; + struct Worker { stream: UnixStream, // Also queried for its exit status when a socket read/write fails, to tell a dead worker @@ -707,7 +725,7 @@ fn spawn_worker() -> anyhow::Result { std::fs::write(&script_path, GLUE_SCRIPT)?; let stubs_dir = tempdir.path().join("stubs"); - for (relative_path, contents) in STUB_FILES { + for (relative_path, contents) in STUB_FILES.iter().chain(RUNTIME_FILES) { let path = stubs_dir.join(relative_path); std::fs::create_dir_all(path.parent().expect("stub paths have a parent"))?; std::fs::write(&path, contents)?; -- cgit v1.3.1