aboutsummaryrefslogtreecommitdiffhomepage
path: root/scripts/plugin-stub-generator/generate-stubs
blob: c6b03c972ffa7189d8a7c2d499a0c17d74de0f67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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);