From 4b13b4fb9d3dca4c9f99718e220936dcfd9c9c95 Mon Sep 17 00:00:00 2001 From: Sander Muller Date: Sat, 17 Oct 2026 17:16:37 +0200 Subject: [PATCH] Skip PhpParser\NodeTraverser in preload.php when it is already declared PHPStan Turbo declares a native PhpParser\NodeTraverser when it is activated. preload.php then fails with "Cannot redeclare class". Without Turbo, the class is not declared yet and preload.php loads it as before. --- build/build-preload.php | 10 ++++++++++ preload.php | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/build/build-preload.php b/build/build-preload.php index 47630502cdf..a2216797532 100755 --- a/build/build-preload.php +++ b/build/build-preload.php @@ -48,6 +48,7 @@ final class PreloadBuilder declare(strict_types=1); use PhpParser\Node; +use PhpParser\NodeTraverser; use PHPStan\Testing\PHPStanTestCase; if (defined('__PHPSTAN_RUNNING__')) { @@ -230,6 +231,15 @@ private function createRequireOnceFilePathLine(string $realPath): string } $filePath = '/vendor/' . Strings::after($realPath, 'vendor/'); + + // PHPStan Turbo declares its native NodeTraverser before this file runs + if ($filePath === '/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php') { + return 'if (! class_exists(NodeTraverser::class, false)) {' . PHP_EOL + . " require_once __DIR__ . '" . $filePath . "';" . PHP_EOL + . '}' . PHP_EOL + . PHP_EOL; + } + return "require_once __DIR__ . '" . $filePath . "';" . PHP_EOL; } diff --git a/preload.php b/preload.php index b0e5eeaa067..7a108f6bd79 100644 --- a/preload.php +++ b/preload.php @@ -3,6 +3,7 @@ declare(strict_types=1); use PhpParser\Node; +use PhpParser\NodeTraverser; use PHPStan\Testing\PHPStanTestCase; if (defined('__PHPSTAN_RUNNING__')) { @@ -274,7 +275,10 @@ function isPHPStanTestPreloaded(): bool require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php'; require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php'; require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php'; -require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php'; +if (! class_exists(NodeTraverser::class, false)) { + require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php'; +} + require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php'; require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CommentAnnotatingVisitor.php'; require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php';