aboutsummaryrefslogtreecommitdiffhomepage
path: root/scripts/linters/src/Linters
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-01 04:52:50 +0900
committernsfisis <nsfisis@gmail.com>2026-08-01 04:52:50 +0900
commitb8d46b0495d00815a699932ced0b43955c949ab9 (patch)
tree17c340f51cbf259ea631ca7da7549714c91b916f /scripts/linters/src/Linters
parent8e8a3c147aa388c4b0fc021a08b30113eb590727 (diff)
downloadphp-shirabe-b8d46b0495d00815a699932ced0b43955c949ab9.tar.gz
php-shirabe-b8d46b0495d00815a699932ced0b43955c949ab9.tar.zst
php-shirabe-b8d46b0495d00815a699932ced0b43955c949ab9.zip
feat(php-src): add a BSD-licensed crate for php-src derived code
The audit in .ken/php-shim-copying.md judged 14 functions in shirabe-php-shim (plus php_wordwrap in shirabe-external-packages) to be line-by-line transcriptions or structural imitations of php-src. PHP's relicensing to 3-clause BSD makes keeping them legal, but the boundary between BSD-derived and MIT code was invisible in the source tree. Moving them into their own crate puts the license into the build metadata (so NOTICE generation follows the binary), makes a reverse dependency a compile error, and encodes the origin in the module path, which mirrors php-src's ext tree. Each function records its origin in a fixed-format doc comment, and a new php_src_derivation_boundary linter fails if `php-src` appears in any Rust source outside the crate. Public paths under shirabe_php_shim:: are unchanged: functions that are themselves derived are re-exported with `pub use`, and the wrappers that only validate arguments stay on the MIT side. This also resolves the duplicate wordwrap implementation. shirabe_php_shim::wordwrap was todo!(), so SymfonyStyle::block panicked, while shirabe-external-packages carried its own copy. Both now go through the single port, verified against real PHP on 13 cases covering multi-character breaks and cut. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'scripts/linters/src/Linters')
-rw-r--r--scripts/linters/src/Linters/PhpSrcDerivationBoundary.php54
1 files changed, 54 insertions, 0 deletions
diff --git a/scripts/linters/src/Linters/PhpSrcDerivationBoundary.php b/scripts/linters/src/Linters/PhpSrcDerivationBoundary.php
new file mode 100644
index 00000000..6885f171
--- /dev/null
+++ b/scripts/linters/src/Linters/PhpSrcDerivationBoundary.php
@@ -0,0 +1,54 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Shirabe\Lint\Linters;
+
+use Shirabe\Lint\Linter;
+use Shirabe\Lint\Support\FileFinder;
+use Shirabe\Lint\Support\Paths;
+
+final class PhpSrcDerivationBoundary implements Linter
+{
+ private const PHP_SRC_CRATE_PREFIX = 'crates/shirabe-php-src/';
+
+ // The origin marker every php-src derived item carries, plus the bare crate name.
+ private const MARKER_RE = '/php-src/i';
+
+ public function name(): string
+ {
+ return 'php_src_derivation_boundary';
+ }
+
+ public function failureIntro(): string
+ {
+ return "Found `php-src` mentioned outside the `shirabe-php-src` crate.\n"
+ . "Code written by reading php-src is licensed under php-src's terms, not Shirabe's MIT,\n"
+ . 'so it must live in `crates/shirabe-php-src/` and be reached through that crate:';
+ }
+
+ public function check(string $rootDir, array $excludes): array
+ {
+ $errors = [];
+
+ foreach (FileFinder::rustFiles($rootDir) as $path) {
+ $relative = Paths::relativeTo($rootDir, $path);
+ if (str_starts_with($relative, self::PHP_SRC_CRATE_PREFIX)) {
+ continue;
+ }
+ if (in_array($relative, $excludes, true)) {
+ continue;
+ }
+
+ foreach (file($path) as $idx => $raw) {
+ if (!preg_match(self::MARKER_RE, $raw)) {
+ continue;
+ }
+
+ $errors[] = "{$relative}:" . ($idx + 1) . ': ' . trim($raw);
+ }
+ }
+
+ return $errors;
+ }
+}