diff options
Diffstat (limited to 'crates')
11 files changed, 136 insertions, 44 deletions
diff --git a/crates/shirabe-php-rpc/php/stubs/Composer/Composer.php b/crates/shirabe-php-rpc/php/stubs/Composer/Composer.php index 1bb9f64c..de5a6d1b 100644 --- a/crates/shirabe-php-rpc/php/stubs/Composer/Composer.php +++ b/crates/shirabe-php-rpc/php/stubs/Composer/Composer.php @@ -1,17 +1,16 @@ <?php -// Hand-written proxy stub for Composer\Composer, kept in the shape the future stub generator -// will output. Class constants and static methods are materialized (they read no instance -// state); instance methods forward to the Rust-side entity. +// Generated by scripts/plugin-stub-generator; do not edit by hand. +// Proxy stub for Composer\Composer: the public surface forwards to the Rust-side entity over RPC. namespace Composer; -use Composer\Autoload\AutoloadGenerator; -use Composer\Package\Archiver\ArchiveManager; use Composer\Package\Locker; -use Composer\Downloader\DownloadManager; use Composer\Pcre\Preg; use Composer\Plugin\PluginManager; +use Composer\Downloader\DownloadManager; +use Composer\Autoload\AutoloadGenerator; +use Composer\Package\Archiver\ArchiveManager; class Composer extends PartialComposer { diff --git a/crates/shirabe-php-rpc/php/stubs/Composer/EventDispatcher/Event.php b/crates/shirabe-php-rpc/php/stubs/Composer/EventDispatcher/Event.php index 9ce9c12f..fea84c75 100644 --- a/crates/shirabe-php-rpc/php/stubs/Composer/EventDispatcher/Event.php +++ b/crates/shirabe-php-rpc/php/stubs/Composer/EventDispatcher/Event.php @@ -1,7 +1,7 @@ <?php -// Hand-written proxy stub for Composer\EventDispatcher\Event, kept in the shape the future stub -// generator will output: the real public methods, each forwarding to the Rust-side entity. +// Generated by scripts/plugin-stub-generator; do not edit by hand. +// Proxy stub for Composer\EventDispatcher\Event: the public surface forwards to the Rust-side entity over RPC. namespace Composer\EventDispatcher; @@ -12,8 +12,16 @@ class Event implements \ShirabeRustStub /** @var int */ protected $__epoch; - public function __construct(int $rhandle, int $epoch) + public function __construct(int $rhandle = 0, int $epoch = 0) { + if (func_num_args() < 2) { + // Constructing the class from plugin code (a common idiom for e.g. `new BufferIO()`) + // is an open question of the plugin design; only proxy instantiation passes a + // Rust handle. Fail with a diagnosable message instead of an ArgumentCountError. + throw new \RuntimeException( + 'Shirabe does not support constructing ' . static::class . ' inside the plugin process yet' + ); + } $this->__rhandle = $rhandle; $this->__epoch = $epoch; } diff --git a/crates/shirabe-php-rpc/php/stubs/Composer/IO/BaseIO.php b/crates/shirabe-php-rpc/php/stubs/Composer/IO/BaseIO.php index 51cdbe08..55da6415 100644 --- a/crates/shirabe-php-rpc/php/stubs/Composer/IO/BaseIO.php +++ b/crates/shirabe-php-rpc/php/stubs/Composer/IO/BaseIO.php @@ -1,9 +1,7 @@ <?php -// Hand-written proxy stub for Composer\IO\BaseIO, kept in the shape the future stub generator -// will output: every public method of the real class (its own and the IOInterface / -// LoggerInterface surface) forwards to the Rust-side entity. Loading this stub pulls the real -// IOInterface contract from the Composer PHP runtime, which must already be required. +// Generated by scripts/plugin-stub-generator; do not edit by hand. +// Proxy stub for Composer\IO\BaseIO: the public surface forwards to the Rust-side entity over RPC. namespace Composer\IO; @@ -129,22 +127,17 @@ abstract class BaseIO implements IOInterface, \ShirabeRustStub return \ShirabeRpcRuntime::callRust($this->__rhandle, 'getAuthentications', []); } - public function resetAuthentications() - { - return \ShirabeRpcRuntime::callRust($this->__rhandle, 'resetAuthentications', []); - } - - public function hasAuthentication(string $repositoryName) + public function hasAuthentication($repositoryName) { return \ShirabeRpcRuntime::callRust($this->__rhandle, 'hasAuthentication', [$repositoryName]); } - public function getAuthentication(string $repositoryName) + public function getAuthentication($repositoryName) { return \ShirabeRpcRuntime::callRust($this->__rhandle, 'getAuthentication', [$repositoryName]); } - public function setAuthentication(string $repositoryName, string $username, ?string $password = null) + public function setAuthentication($repositoryName, $username, $password = null) { return \ShirabeRpcRuntime::callRust($this->__rhandle, 'setAuthentication', [$repositoryName, $username, $password]); } @@ -198,4 +191,9 @@ abstract class BaseIO implements IOInterface, \ShirabeRustStub { \ShirabeRpcRuntime::callRust($this->__rhandle, 'log', [$level, $message, $context]); } + + public function resetAuthentications() + { + return \ShirabeRpcRuntime::callRust($this->__rhandle, 'resetAuthentications', []); + } } diff --git a/crates/shirabe-php-rpc/php/stubs/Composer/IO/BufferIO.php b/crates/shirabe-php-rpc/php/stubs/Composer/IO/BufferIO.php index e95fb2da..d5e59e90 100644 --- a/crates/shirabe-php-rpc/php/stubs/Composer/IO/BufferIO.php +++ b/crates/shirabe-php-rpc/php/stubs/Composer/IO/BufferIO.php @@ -1,7 +1,7 @@ <?php -// Hand-written proxy stub for Composer\IO\BufferIO, kept in the shape the future stub -// generator will output. +// Generated by scripts/plugin-stub-generator; do not edit by hand. +// Proxy stub for Composer\IO\BufferIO: the public surface forwards to the Rust-side entity over RPC. namespace Composer\IO; diff --git a/crates/shirabe-php-rpc/php/stubs/Composer/IO/ConsoleIO.php b/crates/shirabe-php-rpc/php/stubs/Composer/IO/ConsoleIO.php index 6a4c2ac4..0041363a 100644 --- a/crates/shirabe-php-rpc/php/stubs/Composer/IO/ConsoleIO.php +++ b/crates/shirabe-php-rpc/php/stubs/Composer/IO/ConsoleIO.php @@ -1,15 +1,62 @@ <?php -// Hand-written proxy stub for Composer\IO\ConsoleIO, kept in the shape the future stub -// generator will output. The IOInterface surface is inherited from the BaseIO stub; only the -// public methods ConsoleIO adds are declared here. +// Generated by scripts/plugin-stub-generator; do not edit by hand. +// Proxy stub for Composer\IO\ConsoleIO: the public surface forwards to the Rust-side entity over RPC. namespace Composer\IO; +use Composer\Pcre\Preg; use Symfony\Component\Console\Helper\Table; class ConsoleIO extends BaseIO { + public static function sanitize($messages, bool $allowNewlines = true) + { + // Match ANSI escape sequences: + // - CSI (Control Sequence Introducer): ESC [ params intermediate final + // - OSC (Operating System Command): ESC ] ... ESC \ or BEL + // - Other ESC sequences: ESC followed by any character + $escapePattern = '\x1B\[[\x30-\x3F]*[\x20-\x2F]*[\x40-\x7E]|\x1B\].*?(?:\x1B\\\\|\x07)|\x1B.'; + $pattern = $allowNewlines ? "{{$escapePattern}|[\x01-\x09\x0B\x0C\x0E-\x1A]|\r(?!\n)}u" : "{{$escapePattern}|[\x01-\x1A]}u"; + if (is_string($messages)) { + $messages = self::ensureValidUtf8($messages); + return Preg::replace($pattern, '', $messages); + } + + $sanitized = []; + foreach ($messages as $key => $message) { + $message = self::ensureValidUtf8($message); + $sanitized[$key] = Preg::replace($pattern, '', $message); + } + + return $sanitized; + } + + private static function ensureValidUtf8(string $string): string + { + // Quick check: if string is already valid UTF-8, return as-is + if (function_exists('mb_check_encoding') && mb_check_encoding($string, 'UTF-8')) { + return $string; + } + + // Use mb_convert_encoding to replace invalid sequences with '?' + // This makes it visible when data quality issues occur + if (function_exists('mb_convert_encoding')) { + return (string) mb_convert_encoding($string, 'UTF-8', 'UTF-8'); + } + + // Fallback to iconv if mbstring unavailable + if (function_exists('iconv')) { + $cleaned = @iconv('UTF-8', 'UTF-8//TRANSLIT', $string); + if ($cleaned !== false) { + return $cleaned; + } + } + + // Last resort: return as-is (should never happen - Composer requires mbstring OR iconv) + return $string; + } + public function enableDebugging(float $startTime) { return \ShirabeRpcRuntime::callRust($this->__rhandle, 'enableDebugging', [$startTime]); diff --git a/crates/shirabe-php-rpc/php/stubs/Composer/IO/NullIO.php b/crates/shirabe-php-rpc/php/stubs/Composer/IO/NullIO.php index 92e01700..1234ad4a 100644 --- a/crates/shirabe-php-rpc/php/stubs/Composer/IO/NullIO.php +++ b/crates/shirabe-php-rpc/php/stubs/Composer/IO/NullIO.php @@ -1,7 +1,7 @@ <?php -// Hand-written proxy stub for Composer\IO\NullIO, kept in the shape the future stub generator -// will output. The whole surface is inherited from the BaseIO stub. +// Generated by scripts/plugin-stub-generator; do not edit by hand. +// Proxy stub for Composer\IO\NullIO: the public surface forwards to the Rust-side entity over RPC. namespace Composer\IO; diff --git a/crates/shirabe-php-rpc/php/stubs/Composer/PartialComposer.php b/crates/shirabe-php-rpc/php/stubs/Composer/PartialComposer.php index 2641b267..588800dc 100644 --- a/crates/shirabe-php-rpc/php/stubs/Composer/PartialComposer.php +++ b/crates/shirabe-php-rpc/php/stubs/Composer/PartialComposer.php @@ -1,18 +1,15 @@ <?php -// Hand-written proxy stub for Composer\PartialComposer, kept in the shape the future stub -// generator will output: the real public methods, each forwarding to the Rust-side entity. -// Methods the Rust dispatcher does not support yet surface as explicit RPC errors. +// Generated by scripts/plugin-stub-generator; do not edit by hand. +// Proxy stub for Composer\PartialComposer: the public surface forwards to the Rust-side entity over RPC. namespace Composer; -use Composer\Autoload\AutoloadGenerator; -use Composer\Config; -use Composer\EventDispatcher\EventDispatcher; -use Composer\Installer\InstallationManager; use Composer\Package\RootPackageInterface; -use Composer\Repository\RepositoryManager; use Composer\Util\Loop; +use Composer\Repository\RepositoryManager; +use Composer\Installer\InstallationManager; +use Composer\EventDispatcher\EventDispatcher; class PartialComposer implements \ShirabeRustStub { diff --git a/crates/shirabe-php-rpc/php/stubs/Composer/Script/Event.php b/crates/shirabe-php-rpc/php/stubs/Composer/Script/Event.php index 80afe1b7..a93d0dfc 100644 --- a/crates/shirabe-php-rpc/php/stubs/Composer/Script/Event.php +++ b/crates/shirabe-php-rpc/php/stubs/Composer/Script/Event.php @@ -1,20 +1,22 @@ <?php -// Hand-written proxy stub for Composer\Script\Event, kept in the shape the future stub -// generator will output. See Composer/EventDispatcher/Event.php. +// Generated by scripts/plugin-stub-generator; do not edit by hand. +// Proxy stub for Composer\Script\Event: the public surface forwards to the Rust-side entity over RPC. namespace Composer\Script; +use Composer\Composer; +use Composer\IO\IOInterface; use Composer\EventDispatcher\Event as BaseEvent; class Event extends BaseEvent { - public function getComposer(): \Composer\Composer + public function getComposer(): Composer { return \ShirabeRpcRuntime::callRust($this->__rhandle, 'getComposer', []); } - public function getIO(): \Composer\IO\IOInterface + public function getIO(): IOInterface { return \ShirabeRpcRuntime::callRust($this->__rhandle, 'getIO', []); } diff --git a/crates/shirabe-php-rpc/src/lib.rs b/crates/shirabe-php-rpc/src/lib.rs index 9c5dae55..23996a95 100644 --- a/crates/shirabe-php-rpc/src/lib.rs +++ b/crates/shirabe-php-rpc/src/lib.rs @@ -539,8 +539,9 @@ fn call(name: &str, arg: &str) -> PhpMixed { const GLUE_SCRIPT: &str = include_str!("../php/worker.php"); -/// Hand-written proxy stub classes made autoloadable inside the worker, written in the shape the -/// future stub generator will output. +/// Proxy stub classes made autoloadable inside the worker. Generated by +/// `scripts/plugin-stub-generator/generate-stubs`; this list must cover its targets.list (the +/// generator's `--check` mode verifies both the file contents and this list). const STUB_FILES: &[(&str, &str)] = &[ ( "Composer/EventDispatcher/Event.php", diff --git a/crates/shirabe-php-rpc/tests/generated_stubs.rs b/crates/shirabe-php-rpc/tests/generated_stubs.rs new file mode 100644 index 00000000..b4ff8197 --- /dev/null +++ b/crates/shirabe-php-rpc/tests/generated_stubs.rs @@ -0,0 +1,40 @@ +//! Freshness check for the generated proxy stubs: `generate-stubs --check` verifies that the +//! committed stub files and the `STUB_FILES` list in `lib.rs` match what the generator emits +//! from the current Composer checkout and classifier report. +//! +//! The generator needs a PHP interpreter, its composer vendor directory and the classifier +//! report; when any of those is missing the test returns early, following the non-mock test +//! convention of this crate. + +use shirabe_external_packages::symfony::process::PhpExecutableFinder; +use std::path::Path; + +#[test] +fn generated_stubs_are_fresh() { + let Some(php) = PhpExecutableFinder::new().find(false) else { + return; + }; + let tool_dir = + Path::new(env!("CARGO_MANIFEST_DIR")).join("../../scripts/plugin-stub-generator"); + if !tool_dir.join("vendor/autoload.php").is_file() { + return; + } + if !tool_dir + .join("../plugin-class-classifier/report.json") + .is_file() + { + return; + } + + let output = std::process::Command::new(php) + .arg(tool_dir.join("generate-stubs")) + .arg("--check") + .output() + .expect("failed to spawn the stub generator"); + assert!( + output.status.success(), + "generate-stubs --check failed; regenerate the stubs with \ + scripts/plugin-stub-generator/generate-stubs:\n{}", + String::from_utf8_lossy(&output.stderr), + ); +} diff --git a/crates/shirabe/src/plugin/php_plugin_proxy.rs b/crates/shirabe/src/plugin/php_plugin_proxy.rs index 09867079..2b823fa5 100644 --- a/crates/shirabe/src/plugin/php_plugin_proxy.rs +++ b/crates/shirabe/src/plugin/php_plugin_proxy.rs @@ -90,8 +90,8 @@ pub(crate) fn io_stub_class( } else if any.downcast_ref::<crate::io::null_io::NullIO>().is_some() { Ok("Composer\\IO\\NullIO") } else { - // TODO(plugin): only the IO classes with hand-written proxy stubs can cross the - // boundary until a stub generator exists. + // TODO(plugin): only IO implementations with a generated proxy stub can cross the + // boundary; the rest are an explicit error until stubs of their own are generated. Err(anyhow::anyhow!( "no proxy stub class is available for this IO implementation" )) |
