mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-19 06:18:07 +01:00
f82e30a026
ae874efa14
Remove SourceLocatorProviderInterface as unused (#4126)
164 lines
7.3 KiB
PHP
164 lines
7.3 KiB
PHP
<?php
|
|
|
|
declare (strict_types=1);
|
|
namespace Rector\Parallel;
|
|
|
|
use RectorPrefix202306\Clue\React\NDJson\Decoder;
|
|
use RectorPrefix202306\Clue\React\NDJson\Encoder;
|
|
use RectorPrefix202306\Nette\Utils\FileSystem;
|
|
use Rector\Caching\Detector\ChangedFilesDetector;
|
|
use Rector\Core\Application\ApplicationFileProcessor;
|
|
use Rector\Core\Console\Style\RectorConsoleOutputStyle;
|
|
use Rector\Core\Contract\Processor\FileProcessorInterface;
|
|
use Rector\Core\Provider\CurrentFileProvider;
|
|
use Rector\Core\StaticReflection\DynamicSourceLocatorDecorator;
|
|
use Rector\Core\Util\ArrayParametersMerger;
|
|
use Rector\Core\ValueObject\Application\File;
|
|
use Rector\Core\ValueObject\Configuration;
|
|
use Rector\Core\ValueObject\Error\SystemError;
|
|
use Rector\Core\ValueObject\Reporting\FileDiff;
|
|
use Rector\Parallel\ValueObject\Bridge;
|
|
use RectorPrefix202306\Symplify\EasyParallel\Enum\Action;
|
|
use RectorPrefix202306\Symplify\EasyParallel\Enum\ReactCommand;
|
|
use RectorPrefix202306\Symplify\EasyParallel\Enum\ReactEvent;
|
|
use Throwable;
|
|
final class WorkerRunner
|
|
{
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\Core\Util\ArrayParametersMerger
|
|
*/
|
|
private $arrayParametersMerger;
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\Core\Provider\CurrentFileProvider
|
|
*/
|
|
private $currentFileProvider;
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\Core\StaticReflection\DynamicSourceLocatorDecorator
|
|
*/
|
|
private $dynamicSourceLocatorDecorator;
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\Core\Console\Style\RectorConsoleOutputStyle
|
|
*/
|
|
private $rectorConsoleOutputStyle;
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\Core\Application\ApplicationFileProcessor
|
|
*/
|
|
private $applicationFileProcessor;
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\Caching\Detector\ChangedFilesDetector
|
|
*/
|
|
private $changedFilesDetector;
|
|
/**
|
|
* @var FileProcessorInterface[]
|
|
* @readonly
|
|
*/
|
|
private $fileProcessors = [];
|
|
/**
|
|
* @var string
|
|
*/
|
|
private const RESULT = 'result';
|
|
/**
|
|
* @param FileProcessorInterface[] $fileProcessors
|
|
*/
|
|
public function __construct(ArrayParametersMerger $arrayParametersMerger, CurrentFileProvider $currentFileProvider, DynamicSourceLocatorDecorator $dynamicSourceLocatorDecorator, RectorConsoleOutputStyle $rectorConsoleOutputStyle, ApplicationFileProcessor $applicationFileProcessor, ChangedFilesDetector $changedFilesDetector, array $fileProcessors = [])
|
|
{
|
|
$this->arrayParametersMerger = $arrayParametersMerger;
|
|
$this->currentFileProvider = $currentFileProvider;
|
|
$this->dynamicSourceLocatorDecorator = $dynamicSourceLocatorDecorator;
|
|
$this->rectorConsoleOutputStyle = $rectorConsoleOutputStyle;
|
|
$this->applicationFileProcessor = $applicationFileProcessor;
|
|
$this->changedFilesDetector = $changedFilesDetector;
|
|
$this->fileProcessors = $fileProcessors;
|
|
}
|
|
public function run(Encoder $encoder, Decoder $decoder, Configuration $configuration) : void
|
|
{
|
|
$this->dynamicSourceLocatorDecorator->addPaths($configuration->getPaths());
|
|
// 1. handle system error
|
|
$handleErrorCallback = static function (Throwable $throwable) use($encoder) : void {
|
|
$systemErrors = new SystemError($throwable->getMessage(), $throwable->getFile(), $throwable->getLine());
|
|
$encoder->write([ReactCommand::ACTION => Action::RESULT, self::RESULT => [Bridge::SYSTEM_ERRORS => [$systemErrors], Bridge::FILES_COUNT => 0, Bridge::SYSTEM_ERRORS_COUNT => 1]]);
|
|
$encoder->end();
|
|
};
|
|
$encoder->on(ReactEvent::ERROR, $handleErrorCallback);
|
|
// 2. collect diffs + errors from file processor
|
|
$decoder->on(ReactEvent::DATA, function (array $json) use($encoder, $configuration) : void {
|
|
$action = $json[ReactCommand::ACTION];
|
|
if ($action !== Action::MAIN) {
|
|
return;
|
|
}
|
|
$systemErrorsCount = 0;
|
|
/** @var string[] $filePaths */
|
|
$filePaths = $json[Bridge::FILES] ?? [];
|
|
$errorAndFileDiffs = [];
|
|
$systemErrors = [];
|
|
// 1. allow PHPStan to work with static reflection on provided files
|
|
$this->applicationFileProcessor->configurePHPStanNodeScopeResolver($filePaths, $configuration);
|
|
foreach ($filePaths as $filePath) {
|
|
$file = null;
|
|
try {
|
|
$file = new File($filePath, FileSystem::read($filePath));
|
|
$this->currentFileProvider->setFile($file);
|
|
$errorAndFileDiffs = $this->processFile($file, $configuration, $errorAndFileDiffs);
|
|
if ($errorAndFileDiffs[Bridge::SYSTEM_ERRORS] !== []) {
|
|
$this->invalidateFile($file);
|
|
} elseif (!$configuration->isDryRun()) {
|
|
$this->changedFilesDetector->cacheFileWithDependencies($file->getFilePath());
|
|
}
|
|
} catch (Throwable $throwable) {
|
|
++$systemErrorsCount;
|
|
$systemErrors = $this->collectSystemErrors($systemErrors, $throwable, $filePath);
|
|
$this->invalidateFile($file);
|
|
}
|
|
}
|
|
/**
|
|
* this invokes all listeners listening $decoder->on(...) @see \Symplify\EasyParallel\Enum\ReactEvent::DATA
|
|
*/
|
|
$encoder->write([ReactCommand::ACTION => Action::RESULT, self::RESULT => [Bridge::FILE_DIFFS => $errorAndFileDiffs[Bridge::FILE_DIFFS] ?? [], Bridge::FILES_COUNT => \count($filePaths), Bridge::SYSTEM_ERRORS => $systemErrors, Bridge::SYSTEM_ERRORS_COUNT => $systemErrorsCount]]);
|
|
});
|
|
$decoder->on(ReactEvent::ERROR, $handleErrorCallback);
|
|
}
|
|
/**
|
|
* @param array{system_errors: SystemError[], file_diffs: FileDiff[]}|mixed[] $errorAndFileDiffs
|
|
* @return array{system_errors: SystemError[], file_diffs: FileDiff[]}
|
|
*/
|
|
private function processFile(File $file, Configuration $configuration, array $errorAndFileDiffs) : array
|
|
{
|
|
foreach ($this->fileProcessors as $fileProcessor) {
|
|
if (!$fileProcessor->supports($file, $configuration)) {
|
|
continue;
|
|
}
|
|
$currentErrorsAndFileDiffs = $fileProcessor->process($file, $configuration);
|
|
$errorAndFileDiffs = $this->arrayParametersMerger->merge($errorAndFileDiffs, $currentErrorsAndFileDiffs);
|
|
}
|
|
return $errorAndFileDiffs;
|
|
}
|
|
/**
|
|
* @param SystemError[] $systemErrors
|
|
* @return SystemError[]
|
|
*/
|
|
private function collectSystemErrors(array $systemErrors, Throwable $throwable, string $filePath) : array
|
|
{
|
|
$errorMessage = \sprintf('System error: "%s"', $throwable->getMessage()) . \PHP_EOL;
|
|
if ($this->rectorConsoleOutputStyle->isDebug()) {
|
|
$systemErrors[] = new SystemError($errorMessage . \PHP_EOL . 'Stack trace:' . \PHP_EOL . $throwable->getTraceAsString(), $filePath, $throwable->getLine());
|
|
return $systemErrors;
|
|
}
|
|
$errorMessage .= 'Run Rector with "--debug" option and post the report here: https://github.com/rectorphp/rector/issues/new';
|
|
$systemErrors[] = new SystemError($errorMessage, $filePath, $throwable->getLine());
|
|
return $systemErrors;
|
|
}
|
|
private function invalidateFile(?File $file) : void
|
|
{
|
|
if (!$file instanceof File) {
|
|
return;
|
|
}
|
|
$this->changedFilesDetector->invalidateFile($file->getFilePath());
|
|
}
|
|
}
|