Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions bin/rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
$autoloadIncluder = new AutoloadIncluder();
$autoloadIncluder->includeDependencyOrRepositoryVendorAutoloadIfExists();

// rector-src on split packages: Turbo resolves php-parser classes through the project autoloader,
// as preload-split-package.php declares them only after Turbo is activated
$isSplitPackage = file_exists(__DIR__ . '/../preload-split-package.php') && is_dir(__DIR__ . '/../../../../vendor');
if ($isSplitPackage) {
$autoloadIncluder->autoloadProjectAutoloaderFile();
}

// PHPStan Turbo replaces php-parser classes, so it is activated before preload.php declares them.
// The main process only gets Turbo when php.ini loads it; the workers get it from WorkerCommandLineFactory.
$phpstanBootstrapFile = __DIR__ . '/../../../phpstan/phpstan/bootstrap.php';
Expand Down Expand Up @@ -140,6 +147,13 @@ public function loadIfExistsAndNotLoadedYet(string $filePath): void
require_once __DIR__ . '/../preload.php';
}

// require rector-src on split packages
if ($isSplitPackage) {
require_once __DIR__ . '/../preload-split-package.php';
}

unset($isSplitPackage);

$autoloadIncluder->loadIfExistsAndNotLoadedYet(__DIR__ . '/../vendor/scoper-autoload.php');
$autoloadIncluder->autoloadProjectAutoloaderFile();
$autoloadIncluder->autoloadRectorInstalledAsGlobalDependency();
Expand Down
54 changes: 47 additions & 7 deletions build/build-preload.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

$preloadBuilder = new PreloadBuilder();
$preloadBuilder->buildPreloadScript($buildDirectory, $buildDirectory . '/preload.php');
$preloadBuilder->buildPreloadScriptForSplitPackage($buildDirectory, $buildDirectory . '/preload-split-package.php');

final class PreloadBuilder
{
Expand Down Expand Up @@ -141,6 +142,44 @@ public function buildPreloadScript(string $buildDirectory, string $preloadFile):
$this->buildPreloadScriptPhpDocParser($buildDirectory, $preloadFile);
}

public function buildPreloadScriptForSplitPackage(string $buildDirectory, string $preloadFile): void
{
$this->buildPreloadScriptForSplitPhpParser($buildDirectory, $preloadFile);
$this->buildPreloadScriptForSplitPhpDocParser($buildDirectory, $preloadFile);
}

private function buildPreloadScriptForSplitPhpParser(string $buildDirectory, string $preloadFile): void
{
$vendorDir = $buildDirectory . '/vendor';
if (! is_dir($vendorDir . '/nikic/php-parser/lib/PhpParser')) {
return;
}

// 1. find php-parser file infos
$fileInfos = $this->findPhpParserFilesAndSortThem($vendorDir);

// 2. create preload-split-package.php from provided files
$preloadFileContent = $this->createPreloadFileContent($fileInfos, '/../../../vendor/');

file_put_contents($preloadFile, $preloadFileContent);
}

private function buildPreloadScriptForSplitPhpDocParser(string $buildDirectory, string $preloadFile): void
{
$vendorDir = $buildDirectory . '/vendor';
if (! is_dir($vendorDir . '/phpstan/phpdoc-parser')) {
return;
}

// 1. find phpdoc-parser file infos
$fileInfos = $this->findPhpDocParserFilesAndSortThem($vendorDir);

// 2. create preload-split-package.php from provided files
$preloadFileContent = $this->createPreloadFileContent($fileInfos, '/../../../vendor/', true);

file_put_contents($preloadFile, $preloadFileContent, FILE_APPEND);
}

private function buildPreloadScriptPhpDocParser(string $buildDirectory, string $preloadFile): void
{
$vendorDir = $buildDirectory . '/vendor';
Expand All @@ -152,7 +191,7 @@ private function buildPreloadScriptPhpDocParser(string $buildDirectory, string $
$fileInfos = $this->findPhpDocParserFilesAndSortThem($vendorDir);

// 2. create preload.php from provided files
$preloadFileContent = $this->createPreloadFileContent($fileInfos, true);
$preloadFileContent = $this->createPreloadFileContent($fileInfos, '/vendor/', true);

file_put_contents($preloadFile, $preloadFileContent, FILE_APPEND);
}
Expand All @@ -168,7 +207,7 @@ private function buildPreloadScriptPhpParser(string $buildDirectory, string $pre
$fileInfos = $this->findPhpParserFilesAndSortThem($vendorDir);

// 3. create preload.php from provided files
$preloadFileContent = $this->createPreloadFileContent($fileInfos);
$preloadFileContent = $this->createPreloadFileContent($fileInfos, '/vendor/');

file_put_contents($preloadFile, $preloadFileContent);
}
Expand Down Expand Up @@ -207,7 +246,7 @@ private function findPhpDocParserFiles(string $vendorDir): array
/**
* @param SplFileInfo[] $fileInfos
*/
private function createPreloadFileContent(array $fileInfos, bool $append = false): string
private function createPreloadFileContent(array $fileInfos, string $vendorPath, bool $append = false): string
{
$preloadFileContent = $append ? '' : self::PRELOAD_FILE_TEMPLATE . PHP_EOL . PHP_EOL;

Expand All @@ -217,23 +256,24 @@ private function createPreloadFileContent(array $fileInfos, bool $append = false
continue;
}

$preloadFileContent .= $this->createRequireOnceFilePathLine($realPath);
$preloadFileContent .= $this->createRequireOnceFilePathLine($realPath, $vendorPath);
}

return $preloadFileContent;
}

private function createRequireOnceFilePathLine(string $realPath): string
private function createRequireOnceFilePathLine(string $realPath, string $vendorPath): string
{
if (! str_contains($realPath, 'vendor')) {
$filePath = '/src/' . Strings::after($realPath, '/src/');
return "require_once __DIR__ . '" . $filePath . "';" . PHP_EOL;
}

$filePath = '/vendor/' . Strings::after($realPath, 'vendor/');
$vendorFilePath = Strings::after($realPath, 'vendor/');
$filePath = $vendorPath . $vendorFilePath;

// PHPStan Turbo declares its native NodeTraverser before this file runs
if ($filePath === '/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php') {
if ($vendorFilePath === 'nikic/php-parser/lib/PhpParser/NodeTraverser.php') {
return 'if (! class_exists(NodeTraverser::class, false)) {' . PHP_EOL
. " require_once __DIR__ . '" . $filePath . "';" . PHP_EOL
. '}' . PHP_EOL
Expand Down
1 change: 1 addition & 0 deletions ecs.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

// avoid re-running on build
__DIR__ . '/preload.php',
__DIR__ . '/preload-split-package.php',

PhpdocTypesFixer::class => [
// double to Double false positive
Expand Down
Loading
Loading