aboutsummaryrefslogtreecommitdiffhomepage
path: root/scripts/plugin-stub-generator/generate-stubs
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/plugin-stub-generator/generate-stubs')
-rwxr-xr-xscripts/plugin-stub-generator/generate-stubs97
1 files changed, 97 insertions, 0 deletions
diff --git a/scripts/plugin-stub-generator/generate-stubs b/scripts/plugin-stub-generator/generate-stubs
new file mode 100755
index 00000000..c6b03c97
--- /dev/null
+++ b/scripts/plugin-stub-generator/generate-stubs
@@ -0,0 +1,97 @@
+#!/usr/bin/env php
+<?php
+
+declare(strict_types=1);
+
+require __DIR__ . '/vendor/autoload.php';
+
+use Shirabe\PluginStubGenerator\GenerationError;
+use Shirabe\PluginStubGenerator\Generator;
+use Shirabe\PluginStubGenerator\Report;
+
+$repoRoot = dirname(__DIR__, 2);
+$composerRoot = $repoRoot . '/composer';
+$reportPath = $repoRoot . '/scripts/plugin-class-classifier/report.json';
+$stubsDir = $repoRoot . '/crates/shirabe-php-rpc/php/stubs';
+$libRs = $repoRoot . '/crates/shirabe-php-rpc/src/lib.rs';
+$check = false;
+
+foreach (array_slice($argv, 1) as $arg) {
+ if (str_starts_with($arg, '--composer-root=')) {
+ $composerRoot = substr($arg, strlen('--composer-root='));
+ } elseif (str_starts_with($arg, '--report=')) {
+ $reportPath = substr($arg, strlen('--report='));
+ } elseif (str_starts_with($arg, '--stubs-dir=')) {
+ $stubsDir = substr($arg, strlen('--stubs-dir='));
+ } elseif ($arg === '--check') {
+ $check = true;
+ } else {
+ fwrite(STDERR, "usage: generate-stubs [--composer-root=DIR] [--report=FILE] [--stubs-dir=DIR] [--check]\n");
+ exit(2);
+ }
+}
+
+$targets = [];
+foreach (file(__DIR__ . '/targets.list', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
+ $line = trim($line);
+ if ($line !== '' && !str_starts_with($line, '#')) {
+ $targets[] = $line;
+ }
+}
+
+try {
+ $generator = new Generator($composerRoot, Report::load($reportPath), $targets);
+ $files = $generator->generate();
+} catch (GenerationError $e) {
+ foreach ($e->errors as $error) {
+ fwrite(STDERR, "error: $error\n");
+ }
+ exit(1);
+}
+
+$problems = [];
+
+$iterator = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator($stubsDir, FilesystemIterator::SKIP_DOTS)
+);
+foreach ($iterator as $entry) {
+ if ($entry->isFile() && str_ends_with($entry->getFilename(), '.php')) {
+ $relative = substr($entry->getPathname(), strlen($stubsDir) + 1);
+ if (!isset($files[$relative])) {
+ $problems[] = "stale stub not covered by targets.list: $stubsDir/$relative";
+ }
+ }
+}
+
+// The Rust side embeds every stub with include_str!; the two lists must not drift apart.
+$libRsText = (string) file_get_contents($libRs);
+foreach ($files as $relative => $_) {
+ if (!str_contains($libRsText, "include_str!(\"../php/stubs/$relative\")")) {
+ $problems[] = "STUB_FILES in $libRs does not embed $relative";
+ }
+}
+
+if ($check) {
+ foreach ($files as $relative => $content) {
+ $current = @file_get_contents("$stubsDir/$relative");
+ if ($current === false) {
+ $problems[] = "missing stub (regenerate): $stubsDir/$relative";
+ } elseif ($current !== $content) {
+ $problems[] = "stale stub (regenerate): $stubsDir/$relative";
+ }
+ }
+} else {
+ foreach ($files as $relative => $content) {
+ $path = "$stubsDir/$relative";
+ if (!is_dir(dirname($path))) {
+ mkdir(dirname($path), 0777, true);
+ }
+ file_put_contents($path, $content);
+ }
+ fwrite(STDERR, count($files) . " stubs written to $stubsDir\n");
+}
+
+foreach ($problems as $problem) {
+ fwrite(STDERR, "error: $problem\n");
+}
+exit($problems === [] ? 0 : 1);