Updated Rector to commit ebbada3fcdda79b5737d5a8986ceaf538a7159dd

ebbada3fcd Add "--only" option to process only a single rule (#6441)
This commit is contained in:
Tomas Votruba 2024-12-10 16:12:30 +00:00
parent ae97f5ffab
commit f6c514d60a
20 changed files with 228 additions and 22 deletions

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api * @api
* @var string * @var string
*/ */
public const PACKAGE_VERSION = '2fa586b0d66a1f5a38fd379ab5a14dadd2a6f274'; public const PACKAGE_VERSION = 'ebbada3fcdda79b5737d5a8986ceaf538a7159dd';
/** /**
* @api * @api
* @var string * @var string
*/ */
public const RELEASE_DATE = '2024-12-10 22:55:23'; public const RELEASE_DATE = '2024-12-10 17:08:16';
/** /**
* @var int * @var int
*/ */

View File

@ -17,9 +17,14 @@ final class ConfigurationFactory
* @readonly * @readonly
*/ */
private SymfonyStyle $symfonyStyle; private SymfonyStyle $symfonyStyle;
public function __construct(SymfonyStyle $symfonyStyle) /**
* @readonly
*/
private \Rector\Configuration\OnlyRuleResolver $onlyRuleResolver;
public function __construct(SymfonyStyle $symfonyStyle, \Rector\Configuration\OnlyRuleResolver $onlyRuleResolver)
{ {
$this->symfonyStyle = $symfonyStyle; $this->symfonyStyle = $symfonyStyle;
$this->onlyRuleResolver = $onlyRuleResolver;
} }
/** /**
* @api used in tests * @api used in tests
@ -28,7 +33,7 @@ final class ConfigurationFactory
public function createForTests(array $paths) : Configuration public function createForTests(array $paths) : Configuration
{ {
$fileExtensions = SimpleParameterProvider::provideArrayParameter(\Rector\Configuration\Option::FILE_EXTENSIONS); $fileExtensions = SimpleParameterProvider::provideArrayParameter(\Rector\Configuration\Option::FILE_EXTENSIONS);
return new Configuration(\false, \true, \false, ConsoleOutputFormatter::NAME, $fileExtensions, $paths, \true, null, null, \false, null, \false, \false); return new Configuration(\false, \true, \false, ConsoleOutputFormatter::NAME, $fileExtensions, $paths, \true, null, null, \false, null, \false, \false, null);
} }
/** /**
* Needs to run in the start of the life cycle, since the rest of workflow uses it. * Needs to run in the start of the life cycle, since the rest of workflow uses it.
@ -42,6 +47,10 @@ final class ConfigurationFactory
$showDiffs = $this->shouldShowDiffs($input); $showDiffs = $this->shouldShowDiffs($input);
$paths = $this->resolvePaths($input); $paths = $this->resolvePaths($input);
$fileExtensions = SimpleParameterProvider::provideArrayParameter(\Rector\Configuration\Option::FILE_EXTENSIONS); $fileExtensions = SimpleParameterProvider::provideArrayParameter(\Rector\Configuration\Option::FILE_EXTENSIONS);
$onlyRule = $input->getOption(\Rector\Configuration\Option::ONLY);
if ($onlyRule !== null) {
$onlyRule = $this->onlyRuleResolver->resolve($onlyRule);
}
$isParallel = SimpleParameterProvider::provideBoolParameter(\Rector\Configuration\Option::PARALLEL); $isParallel = SimpleParameterProvider::provideBoolParameter(\Rector\Configuration\Option::PARALLEL);
$parallelPort = (string) $input->getOption(\Rector\Configuration\Option::PARALLEL_PORT); $parallelPort = (string) $input->getOption(\Rector\Configuration\Option::PARALLEL_PORT);
$parallelIdentifier = (string) $input->getOption(\Rector\Configuration\Option::PARALLEL_IDENTIFIER); $parallelIdentifier = (string) $input->getOption(\Rector\Configuration\Option::PARALLEL_IDENTIFIER);
@ -52,7 +61,7 @@ final class ConfigurationFactory
} }
$memoryLimit = $this->resolveMemoryLimit($input); $memoryLimit = $this->resolveMemoryLimit($input);
$isReportingWithRealPath = SimpleParameterProvider::provideBoolParameter(\Rector\Configuration\Option::ABSOLUTE_FILE_PATH); $isReportingWithRealPath = SimpleParameterProvider::provideBoolParameter(\Rector\Configuration\Option::ABSOLUTE_FILE_PATH);
return new Configuration($isDryRun, $showProgressBar, $shouldClearCache, $outputFormat, $fileExtensions, $paths, $showDiffs, $parallelPort, $parallelIdentifier, $isParallel, $memoryLimit, $isDebug, $isReportingWithRealPath); return new Configuration($isDryRun, $showProgressBar, $shouldClearCache, $outputFormat, $fileExtensions, $paths, $showDiffs, $parallelPort, $parallelIdentifier, $isParallel, $memoryLimit, $isDebug, $isReportingWithRealPath, $onlyRule);
} }
private function shouldShowProgressBar(InputInterface $input, string $outputFormat) : bool private function shouldShowProgressBar(InputInterface $input, string $outputFormat) : bool
{ {

View File

@ -0,0 +1,48 @@
<?php
declare (strict_types=1);
namespace Rector\Configuration;
use Rector\Contract\Rector\RectorInterface;
use Rector\ValueObject\Configuration;
/**
* Modify available rector rules based on the configuration options
*/
final class ConfigurationRuleFilter
{
private ?Configuration $configuration = null;
public function setConfiguration(Configuration $configuration) : void
{
$this->configuration = $configuration;
}
/**
* @param array<RectorInterface> $rectors
* @return array<RectorInterface>
*/
public function filter(array $rectors) : array
{
if ($this->configuration === null) {
return $rectors;
}
$onlyRule = $this->configuration->getOnlyRule();
if ($onlyRule !== null) {
$rectors = $this->filterOnlyRule($rectors, $onlyRule);
return $rectors;
}
return $rectors;
}
/**
* @param array<RectorInterface> $rectors
* @return array<RectorInterface>
*/
public function filterOnlyRule(array $rectors, string $onlyRule) : array
{
$activeRectors = [];
foreach ($rectors as $rector) {
if (\is_a($rector, $onlyRule)) {
$activeRectors[] = $rector;
}
}
return $activeRectors;
}
}

View File

@ -0,0 +1,62 @@
<?php
declare (strict_types=1);
namespace Rector\Configuration;
use Rector\Contract\Rector\RectorInterface;
use Rector\Exception\Configuration\RectorRuleNotFoundException;
use Rector\Exception\Configuration\RectorRuleNameAmbigiousException;
/**
* @see \Rector\Tests\Configuration\OnlyRuleResolverTest
*/
final class OnlyRuleResolver
{
/**
* @var RectorInterface[]
* @readonly
*/
private array $rectors;
/**
* @param RectorInterface[] $rectors
*/
public function __construct(array $rectors)
{
$this->rectors = $rectors;
}
public function resolve(string $rule) : string
{
//fix wrongly double escaped backslashes
$rule = \str_replace('\\\\', '\\', $rule);
//remove single quotes appearing when single-quoting arguments on windows
if (\strncmp($rule, "'", \strlen("'")) === 0 && \substr_compare($rule, "'", -\strlen("'")) === 0) {
$rule = \substr($rule, 1, -1);
}
$rule = \ltrim($rule, '\\');
foreach ($this->rectors as $rector) {
if (\get_class($rector) === $rule) {
return $rule;
}
}
//allow short rule names if there are not duplicates
$matching = [];
foreach ($this->rectors as $rector) {
if (\substr_compare(\get_class($rector), '\\' . $rule, -\strlen('\\' . $rule)) === 0) {
$matching[] = \get_class($rector);
}
}
$matching = \array_unique($matching);
if (\count($matching) == 1) {
return $matching[0];
} elseif (\count($matching) > 1) {
\sort($matching);
$message = \sprintf('Short rule name "%s" is ambiguous. Specify the full rule name:' . \PHP_EOL . '- ' . \implode(\PHP_EOL . '- ', $matching), $rule);
throw new RectorRuleNameAmbigiousException($message);
}
if (\strpos($rule, '\\') === \false) {
$message = \sprintf('Rule "%s" was not found.%sThe rule has no namespace. Make sure to escape the backslashes, and add quotes around the rule name: --only="My\\Rector\\Rule"', $rule, \PHP_EOL);
} else {
$message = \sprintf('Rule "%s" was not found.%sMake sure it is registered in your config or in one of the sets', $rule, \PHP_EOL);
}
throw new RectorRuleNotFoundException($message);
}
}

View File

@ -80,6 +80,10 @@ final class Option
* @var string * @var string
*/ */
public const CLEAR_CACHE = 'clear-cache'; public const CLEAR_CACHE = 'clear-cache';
/**
* @var string
*/
public const ONLY = 'only';
/** /**
* @internal Use @see \Rector\Config\RectorConfig::parallel() instead * @internal Use @see \Rector\Config\RectorConfig::parallel() instead
* @var string * @var string

View File

@ -5,6 +5,8 @@ namespace Rector\Console\Command;
use RectorPrefix202412\Nette\Utils\Json; use RectorPrefix202412\Nette\Utils\Json;
use Rector\ChangesReporting\Output\ConsoleOutputFormatter; use Rector\ChangesReporting\Output\ConsoleOutputFormatter;
use Rector\Configuration\ConfigurationRuleFilter;
use Rector\Configuration\OnlyRuleResolver;
use Rector\Configuration\Option; use Rector\Configuration\Option;
use Rector\Contract\Rector\RectorInterface; use Rector\Contract\Rector\RectorInterface;
use Rector\PostRector\Contract\Rector\PostRectorInterface; use Rector\PostRector\Contract\Rector\PostRectorInterface;
@ -24,6 +26,14 @@ final class ListRulesCommand extends Command
* @readonly * @readonly
*/ */
private SkippedClassResolver $skippedClassResolver; private SkippedClassResolver $skippedClassResolver;
/**
* @readonly
*/
private OnlyRuleResolver $onlyRuleResolver;
/**
* @readonly
*/
private ConfigurationRuleFilter $configurationRuleFilter;
/** /**
* @var RectorInterface[] * @var RectorInterface[]
* @readonly * @readonly
@ -32,10 +42,12 @@ final class ListRulesCommand extends Command
/** /**
* @param RectorInterface[] $rectors * @param RectorInterface[] $rectors
*/ */
public function __construct(SymfonyStyle $symfonyStyle, SkippedClassResolver $skippedClassResolver, array $rectors) public function __construct(SymfonyStyle $symfonyStyle, SkippedClassResolver $skippedClassResolver, OnlyRuleResolver $onlyRuleResolver, ConfigurationRuleFilter $configurationRuleFilter, array $rectors)
{ {
$this->symfonyStyle = $symfonyStyle; $this->symfonyStyle = $symfonyStyle;
$this->skippedClassResolver = $skippedClassResolver; $this->skippedClassResolver = $skippedClassResolver;
$this->onlyRuleResolver = $onlyRuleResolver;
$this->configurationRuleFilter = $configurationRuleFilter;
$this->rectors = $rectors; $this->rectors = $rectors;
parent::__construct(); parent::__construct();
} }
@ -45,10 +57,15 @@ final class ListRulesCommand extends Command
$this->setDescription('Show loaded Rectors'); $this->setDescription('Show loaded Rectors');
$this->setAliases(['show-rules']); $this->setAliases(['show-rules']);
$this->addOption(Option::OUTPUT_FORMAT, null, InputOption::VALUE_REQUIRED, 'Select output format', ConsoleOutputFormatter::NAME); $this->addOption(Option::OUTPUT_FORMAT, null, InputOption::VALUE_REQUIRED, 'Select output format', ConsoleOutputFormatter::NAME);
$this->addOption(Option::ONLY, null, InputOption::VALUE_REQUIRED, 'Fully qualified rule class name');
} }
protected function execute(InputInterface $input, OutputInterface $output) : int protected function execute(InputInterface $input, OutputInterface $output) : int
{ {
$rectorClasses = $this->resolveRectorClasses(); $onlyRule = $input->getOption(Option::ONLY);
if ($onlyRule !== null) {
$onlyRule = $this->onlyRuleResolver->resolve($onlyRule);
}
$rectorClasses = $this->resolveRectorClasses($onlyRule);
$skippedClasses = $this->getSkippedCheckers(); $skippedClasses = $this->getSkippedCheckers();
$outputFormat = $input->getOption(Option::OUTPUT_FORMAT); $outputFormat = $input->getOption(Option::OUTPUT_FORMAT);
if ($outputFormat === 'json') { if ($outputFormat === 'json') {
@ -69,9 +86,12 @@ final class ListRulesCommand extends Command
/** /**
* @return array<class-string<RectorInterface>> * @return array<class-string<RectorInterface>>
*/ */
private function resolveRectorClasses() : array private function resolveRectorClasses(?string $onlyRule) : array
{ {
$customRectors = \array_filter($this->rectors, static fn(RectorInterface $rector): bool => !$rector instanceof PostRectorInterface); $customRectors = \array_filter($this->rectors, static fn(RectorInterface $rector): bool => !$rector instanceof PostRectorInterface);
if ($onlyRule !== null) {
$customRectors = $this->configurationRuleFilter->filterOnlyRule($customRectors, $onlyRule);
}
$rectorClasses = \array_map(static fn(RectorInterface $rector): string => \get_class($rector), $customRectors); $rectorClasses = \array_map(static fn(RectorInterface $rector): string => \get_class($rector), $customRectors);
\sort($rectorClasses); \sort($rectorClasses);
return \array_unique($rectorClasses); return \array_unique($rectorClasses);

View File

@ -9,6 +9,7 @@ use Rector\Caching\Detector\ChangedFilesDetector;
use Rector\ChangesReporting\Output\JsonOutputFormatter; use Rector\ChangesReporting\Output\JsonOutputFormatter;
use Rector\Configuration\ConfigInitializer; use Rector\Configuration\ConfigInitializer;
use Rector\Configuration\ConfigurationFactory; use Rector\Configuration\ConfigurationFactory;
use Rector\Configuration\ConfigurationRuleFilter;
use Rector\Configuration\Option; use Rector\Configuration\Option;
use Rector\Configuration\Parameter\SimpleParameterProvider; use Rector\Configuration\Parameter\SimpleParameterProvider;
use Rector\Console\ExitCode; use Rector\Console\ExitCode;
@ -72,7 +73,8 @@ final class ProcessCommand extends Command
* @readonly * @readonly
*/ */
private MissConfigurationReporter $missConfigurationReporter; private MissConfigurationReporter $missConfigurationReporter;
public function __construct(AdditionalAutoloader $additionalAutoloader, ChangedFilesDetector $changedFilesDetector, ConfigInitializer $configInitializer, ApplicationFileProcessor $applicationFileProcessor, DynamicSourceLocatorDecorator $dynamicSourceLocatorDecorator, OutputFormatterCollector $outputFormatterCollector, SymfonyStyle $symfonyStyle, MemoryLimiter $memoryLimiter, ConfigurationFactory $configurationFactory, DeprecatedRulesReporter $deprecatedRulesReporter, MissConfigurationReporter $missConfigurationReporter) private ConfigurationRuleFilter $configurationRuleFilter;
public function __construct(AdditionalAutoloader $additionalAutoloader, ChangedFilesDetector $changedFilesDetector, ConfigInitializer $configInitializer, ApplicationFileProcessor $applicationFileProcessor, DynamicSourceLocatorDecorator $dynamicSourceLocatorDecorator, OutputFormatterCollector $outputFormatterCollector, SymfonyStyle $symfonyStyle, MemoryLimiter $memoryLimiter, ConfigurationFactory $configurationFactory, DeprecatedRulesReporter $deprecatedRulesReporter, MissConfigurationReporter $missConfigurationReporter, ConfigurationRuleFilter $configurationRuleFilter)
{ {
$this->additionalAutoloader = $additionalAutoloader; $this->additionalAutoloader = $additionalAutoloader;
$this->changedFilesDetector = $changedFilesDetector; $this->changedFilesDetector = $changedFilesDetector;
@ -85,6 +87,7 @@ final class ProcessCommand extends Command
$this->configurationFactory = $configurationFactory; $this->configurationFactory = $configurationFactory;
$this->deprecatedRulesReporter = $deprecatedRulesReporter; $this->deprecatedRulesReporter = $deprecatedRulesReporter;
$this->missConfigurationReporter = $missConfigurationReporter; $this->missConfigurationReporter = $missConfigurationReporter;
$this->configurationRuleFilter = $configurationRuleFilter;
parent::__construct(); parent::__construct();
} }
protected function configure() : void protected function configure() : void
@ -121,6 +124,7 @@ EOF
} }
$configuration = $this->configurationFactory->createFromInput($input); $configuration = $this->configurationFactory->createFromInput($input);
$this->memoryLimiter->adjust($configuration); $this->memoryLimiter->adjust($configuration);
$this->configurationRuleFilter->setConfiguration($configuration);
// disable console output in case of json output formatter // disable console output in case of json output formatter
if ($configuration->getOutputFormat() === JsonOutputFormatter::NAME) { if ($configuration->getOutputFormat() === JsonOutputFormatter::NAME) {
$this->symfonyStyle->setVerbosity(OutputInterface::VERBOSITY_QUIET); $this->symfonyStyle->setVerbosity(OutputInterface::VERBOSITY_QUIET);

View File

@ -10,6 +10,7 @@ use RectorPrefix202412\React\Socket\ConnectionInterface;
use RectorPrefix202412\React\Socket\TcpConnector; use RectorPrefix202412\React\Socket\TcpConnector;
use Rector\Application\ApplicationFileProcessor; use Rector\Application\ApplicationFileProcessor;
use Rector\Configuration\ConfigurationFactory; use Rector\Configuration\ConfigurationFactory;
use Rector\Configuration\ConfigurationRuleFilter;
use Rector\Console\ProcessConfigureDecorator; use Rector\Console\ProcessConfigureDecorator;
use Rector\Parallel\ValueObject\Bridge; use Rector\Parallel\ValueObject\Bridge;
use Rector\StaticReflection\DynamicSourceLocatorDecorator; use Rector\StaticReflection\DynamicSourceLocatorDecorator;
@ -49,16 +50,21 @@ final class WorkerCommand extends Command
* @readonly * @readonly
*/ */
private ConfigurationFactory $configurationFactory; private ConfigurationFactory $configurationFactory;
/**
* @readonly
*/
private ConfigurationRuleFilter $configurationRuleFilter;
/** /**
* @var string * @var string
*/ */
private const RESULT = 'result'; private const RESULT = 'result';
public function __construct(DynamicSourceLocatorDecorator $dynamicSourceLocatorDecorator, ApplicationFileProcessor $applicationFileProcessor, MemoryLimiter $memoryLimiter, ConfigurationFactory $configurationFactory) public function __construct(DynamicSourceLocatorDecorator $dynamicSourceLocatorDecorator, ApplicationFileProcessor $applicationFileProcessor, MemoryLimiter $memoryLimiter, ConfigurationFactory $configurationFactory, ConfigurationRuleFilter $configurationRuleFilter)
{ {
$this->dynamicSourceLocatorDecorator = $dynamicSourceLocatorDecorator; $this->dynamicSourceLocatorDecorator = $dynamicSourceLocatorDecorator;
$this->applicationFileProcessor = $applicationFileProcessor; $this->applicationFileProcessor = $applicationFileProcessor;
$this->memoryLimiter = $memoryLimiter; $this->memoryLimiter = $memoryLimiter;
$this->configurationFactory = $configurationFactory; $this->configurationFactory = $configurationFactory;
$this->configurationRuleFilter = $configurationRuleFilter;
parent::__construct(); parent::__construct();
} }
protected function configure() : void protected function configure() : void
@ -72,6 +78,7 @@ final class WorkerCommand extends Command
{ {
$configuration = $this->configurationFactory->createFromInput($input); $configuration = $this->configurationFactory->createFromInput($input);
$this->memoryLimiter->adjust($configuration); $this->memoryLimiter->adjust($configuration);
$this->configurationRuleFilter->setConfiguration($configuration);
$streamSelectLoop = new StreamSelectLoop(); $streamSelectLoop = new StreamSelectLoop();
$parallelIdentifier = $configuration->getParallelIdentifier(); $parallelIdentifier = $configuration->getParallelIdentifier();
$tcpConnector = new TcpConnector($streamSelectLoop); $tcpConnector = new TcpConnector($streamSelectLoop);

View File

@ -18,6 +18,7 @@ final class ProcessConfigureDecorator
$command->addOption(Option::NO_PROGRESS_BAR, null, InputOption::VALUE_NONE, 'Hide progress bar. Useful e.g. for nicer CI output.'); $command->addOption(Option::NO_PROGRESS_BAR, null, InputOption::VALUE_NONE, 'Hide progress bar. Useful e.g. for nicer CI output.');
$command->addOption(Option::NO_DIFFS, null, InputOption::VALUE_NONE, 'Hide diffs of changed files. Useful e.g. for nicer CI output.'); $command->addOption(Option::NO_DIFFS, null, InputOption::VALUE_NONE, 'Hide diffs of changed files. Useful e.g. for nicer CI output.');
$command->addOption(Option::OUTPUT_FORMAT, null, InputOption::VALUE_REQUIRED, 'Select output format', ConsoleOutputFormatter::NAME); $command->addOption(Option::OUTPUT_FORMAT, null, InputOption::VALUE_REQUIRED, 'Select output format', ConsoleOutputFormatter::NAME);
$command->addOption(Option::ONLY, null, InputOption::VALUE_REQUIRED, 'Fully qualified rule class name');
$command->addOption(Option::DEBUG, null, InputOption::VALUE_NONE, 'Display debug output.'); $command->addOption(Option::DEBUG, null, InputOption::VALUE_NONE, 'Display debug output.');
$command->addOption(Option::MEMORY_LIMIT, null, InputOption::VALUE_REQUIRED, 'Memory limit for process'); $command->addOption(Option::MEMORY_LIMIT, null, InputOption::VALUE_REQUIRED, 'Memory limit for process');
$command->addOption(Option::CLEAR_CACHE, null, InputOption::VALUE_NONE, 'Clear unchanged files cache'); $command->addOption(Option::CLEAR_CACHE, null, InputOption::VALUE_NONE, 'Clear unchanged files cache');

View File

@ -46,6 +46,8 @@ use Rector\CodingStyle\ClassNameImport\ClassNameImportSkipVoter\UsesClassNameImp
use Rector\CodingStyle\Contract\ClassNameImport\ClassNameImportSkipVoterInterface; use Rector\CodingStyle\Contract\ClassNameImport\ClassNameImportSkipVoterInterface;
use Rector\Config\RectorConfig; use Rector\Config\RectorConfig;
use Rector\Configuration\ConfigInitializer; use Rector\Configuration\ConfigInitializer;
use Rector\Configuration\ConfigurationRuleFilter;
use Rector\Configuration\OnlyRuleResolver;
use Rector\Configuration\RenamedClassesDataCollector; use Rector\Configuration\RenamedClassesDataCollector;
use Rector\Console\Command\CustomRuleCommand; use Rector\Console\Command\CustomRuleCommand;
use Rector\Console\Command\ListRulesCommand; use Rector\Console\Command\ListRulesCommand;
@ -255,12 +257,14 @@ final class LazyContainerFactory
$inflectorFactory = new InflectorFactory(); $inflectorFactory = new InflectorFactory();
return $inflectorFactory->build(); return $inflectorFactory->build();
}); });
$rectorConfig->singleton(ConfigurationRuleFilter::class);
$rectorConfig->singleton(ProcessCommand::class); $rectorConfig->singleton(ProcessCommand::class);
$rectorConfig->singleton(WorkerCommand::class); $rectorConfig->singleton(WorkerCommand::class);
$rectorConfig->singleton(SetupCICommand::class); $rectorConfig->singleton(SetupCICommand::class);
$rectorConfig->singleton(ListRulesCommand::class); $rectorConfig->singleton(ListRulesCommand::class);
$rectorConfig->singleton(CustomRuleCommand::class); $rectorConfig->singleton(CustomRuleCommand::class);
$rectorConfig->when(ListRulesCommand::class)->needs('$rectors')->giveTagged(RectorInterface::class); $rectorConfig->when(ListRulesCommand::class)->needs('$rectors')->giveTagged(RectorInterface::class);
$rectorConfig->when(OnlyRuleResolver::class)->needs('$rectors')->giveTagged(RectorInterface::class);
$rectorConfig->singleton(FileProcessor::class); $rectorConfig->singleton(FileProcessor::class);
$rectorConfig->singleton(PostFileProcessor::class); $rectorConfig->singleton(PostFileProcessor::class);
// phpdoc-parser // phpdoc-parser

View File

@ -0,0 +1,9 @@
<?php
declare (strict_types=1);
namespace Rector\Exception\Configuration;
use Exception;
final class RectorRuleNameAmbigiousException extends Exception
{
}

View File

@ -0,0 +1,9 @@
<?php
declare (strict_types=1);
namespace Rector\Exception\Configuration;
use Exception;
final class RectorRuleNotFoundException extends Exception
{
}

View File

@ -97,6 +97,10 @@ final class WorkerCommandLineFactory
$config = (string) $input->getOption(Option::CONFIG); $config = (string) $input->getOption(Option::CONFIG);
$workerCommandArray[] = \escapeshellarg($this->filePathHelper->relativePath($config)); $workerCommandArray[] = \escapeshellarg($this->filePathHelper->relativePath($config));
} }
if ($input->getOption(Option::ONLY) !== null) {
$workerCommandArray[] = self::OPTION_DASHES . Option::ONLY;
$workerCommandArray[] = \escapeshellarg($input->getOption(Option::ONLY));
}
return \implode(' ', $workerCommandArray); return \implode(' ', $workerCommandArray);
} }
private function shouldSkipOption(InputInterface $input, string $optionName) : bool private function shouldSkipOption(InputInterface $input, string $optionName) : bool

View File

@ -7,6 +7,7 @@ use PhpParser\Node;
use PhpParser\Node\Stmt; use PhpParser\Node\Stmt;
use PhpParser\NodeTraverser; use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor; use PhpParser\NodeVisitor;
use Rector\Configuration\ConfigurationRuleFilter;
use Rector\Contract\Rector\RectorInterface; use Rector\Contract\Rector\RectorInterface;
use Rector\VersionBonding\PhpVersionedFilter; use Rector\VersionBonding\PhpVersionedFilter;
final class RectorNodeTraverser extends NodeTraverser final class RectorNodeTraverser extends NodeTraverser
@ -19,6 +20,10 @@ final class RectorNodeTraverser extends NodeTraverser
* @readonly * @readonly
*/ */
private PhpVersionedFilter $phpVersionedFilter; private PhpVersionedFilter $phpVersionedFilter;
/**
* @readonly
*/
private ConfigurationRuleFilter $configurationRuleFilter;
private bool $areNodeVisitorsPrepared = \false; private bool $areNodeVisitorsPrepared = \false;
/** /**
* @var array<class-string<Node>,RectorInterface[]> * @var array<class-string<Node>,RectorInterface[]>
@ -27,10 +32,11 @@ final class RectorNodeTraverser extends NodeTraverser
/** /**
* @param RectorInterface[] $rectors * @param RectorInterface[] $rectors
*/ */
public function __construct(array $rectors, PhpVersionedFilter $phpVersionedFilter) public function __construct(array $rectors, PhpVersionedFilter $phpVersionedFilter, ConfigurationRuleFilter $configurationRuleFilter)
{ {
$this->rectors = $rectors; $this->rectors = $rectors;
$this->phpVersionedFilter = $phpVersionedFilter; $this->phpVersionedFilter = $phpVersionedFilter;
$this->configurationRuleFilter = $configurationRuleFilter;
parent::__construct(); parent::__construct();
} }
/** /**
@ -89,6 +95,8 @@ final class RectorNodeTraverser extends NodeTraverser
} }
// filer out by version // filer out by version
$this->visitors = $this->phpVersionedFilter->filter($this->rectors); $this->visitors = $this->phpVersionedFilter->filter($this->rectors);
// filter by configuration
$this->visitors = $this->configurationRuleFilter->filter($this->visitors);
$this->areNodeVisitorsPrepared = \true; $this->areNodeVisitorsPrepared = \true;
} }
} }

View File

@ -64,11 +64,15 @@ final class Configuration
* @readonly * @readonly
*/ */
private bool $reportingWithRealPath = \false; private bool $reportingWithRealPath = \false;
/**
* @readonly
*/
private ?string $onlyRule = null;
/** /**
* @param string[] $fileExtensions * @param string[] $fileExtensions
* @param string[] $paths * @param string[] $paths
*/ */
public function __construct(bool $isDryRun = \false, bool $showProgressBar = \true, bool $shouldClearCache = \false, string $outputFormat = ConsoleOutputFormatter::NAME, array $fileExtensions = ['php'], array $paths = [], bool $showDiffs = \true, ?string $parallelPort = null, ?string $parallelIdentifier = null, bool $isParallel = \false, ?string $memoryLimit = null, bool $isDebug = \false, bool $reportingWithRealPath = \false) public function __construct(bool $isDryRun = \false, bool $showProgressBar = \true, bool $shouldClearCache = \false, string $outputFormat = ConsoleOutputFormatter::NAME, array $fileExtensions = ['php'], array $paths = [], bool $showDiffs = \true, ?string $parallelPort = null, ?string $parallelIdentifier = null, bool $isParallel = \false, ?string $memoryLimit = null, bool $isDebug = \false, bool $reportingWithRealPath = \false, ?string $onlyRule = null)
{ {
$this->isDryRun = $isDryRun; $this->isDryRun = $isDryRun;
$this->showProgressBar = $showProgressBar; $this->showProgressBar = $showProgressBar;
@ -83,6 +87,7 @@ final class Configuration
$this->memoryLimit = $memoryLimit; $this->memoryLimit = $memoryLimit;
$this->isDebug = $isDebug; $this->isDebug = $isDebug;
$this->reportingWithRealPath = $reportingWithRealPath; $this->reportingWithRealPath = $reportingWithRealPath;
$this->onlyRule = $onlyRule;
} }
public function isDryRun() : bool public function isDryRun() : bool
{ {
@ -104,6 +109,10 @@ final class Configuration
Assert::notEmpty($this->fileExtensions); Assert::notEmpty($this->fileExtensions);
return $this->fileExtensions; return $this->fileExtensions;
} }
public function getOnlyRule() : ?string
{
return $this->onlyRule;
}
/** /**
* @return string[] * @return string[]
*/ */

View File

@ -1234,8 +1234,10 @@ return array(
'Rector\\Config\\RegisteredService' => $baseDir . '/src/Config/RegisteredService.php', 'Rector\\Config\\RegisteredService' => $baseDir . '/src/Config/RegisteredService.php',
'Rector\\Configuration\\ConfigInitializer' => $baseDir . '/src/Configuration/ConfigInitializer.php', 'Rector\\Configuration\\ConfigInitializer' => $baseDir . '/src/Configuration/ConfigInitializer.php',
'Rector\\Configuration\\ConfigurationFactory' => $baseDir . '/src/Configuration/ConfigurationFactory.php', 'Rector\\Configuration\\ConfigurationFactory' => $baseDir . '/src/Configuration/ConfigurationFactory.php',
'Rector\\Configuration\\ConfigurationRuleFilter' => $baseDir . '/src/Configuration/ConfigurationRuleFilter.php',
'Rector\\Configuration\\Deprecation\\Contract\\DeprecatedInterface' => $baseDir . '/src/Configuration/Deprecation/Contract/DeprecatedInterface.php', 'Rector\\Configuration\\Deprecation\\Contract\\DeprecatedInterface' => $baseDir . '/src/Configuration/Deprecation/Contract/DeprecatedInterface.php',
'Rector\\Configuration\\Levels\\LevelRulesResolver' => $baseDir . '/src/Configuration/Levels/LevelRulesResolver.php', 'Rector\\Configuration\\Levels\\LevelRulesResolver' => $baseDir . '/src/Configuration/Levels/LevelRulesResolver.php',
'Rector\\Configuration\\OnlyRuleResolver' => $baseDir . '/src/Configuration/OnlyRuleResolver.php',
'Rector\\Configuration\\Option' => $baseDir . '/src/Configuration/Option.php', 'Rector\\Configuration\\Option' => $baseDir . '/src/Configuration/Option.php',
'Rector\\Configuration\\Parameter\\SimpleParameterProvider' => $baseDir . '/src/Configuration/Parameter/SimpleParameterProvider.php', 'Rector\\Configuration\\Parameter\\SimpleParameterProvider' => $baseDir . '/src/Configuration/Parameter/SimpleParameterProvider.php',
'Rector\\Configuration\\PhpLevelSetResolver' => $baseDir . '/src/Configuration/PhpLevelSetResolver.php', 'Rector\\Configuration\\PhpLevelSetResolver' => $baseDir . '/src/Configuration/PhpLevelSetResolver.php',
@ -1523,6 +1525,8 @@ return array(
'Rector\\Enum\\ObjectReference' => $baseDir . '/src/Enum/ObjectReference.php', 'Rector\\Enum\\ObjectReference' => $baseDir . '/src/Enum/ObjectReference.php',
'Rector\\Exception\\Cache\\CachingException' => $baseDir . '/src/Exception/Cache/CachingException.php', 'Rector\\Exception\\Cache\\CachingException' => $baseDir . '/src/Exception/Cache/CachingException.php',
'Rector\\Exception\\Configuration\\InvalidConfigurationException' => $baseDir . '/src/Exception/Configuration/InvalidConfigurationException.php', 'Rector\\Exception\\Configuration\\InvalidConfigurationException' => $baseDir . '/src/Exception/Configuration/InvalidConfigurationException.php',
'Rector\\Exception\\Configuration\\RectorRuleNameAmbigiousException' => $baseDir . '/src/Exception/Configuration/RectorRuleNameAmbigiousException.php',
'Rector\\Exception\\Configuration\\RectorRuleNotFoundException' => $baseDir . '/src/Exception/Configuration/RectorRuleNotFoundException.php',
'Rector\\Exception\\NotImplementedYetException' => $baseDir . '/src/Exception/NotImplementedYetException.php', 'Rector\\Exception\\NotImplementedYetException' => $baseDir . '/src/Exception/NotImplementedYetException.php',
'Rector\\Exception\\Reflection\\MissingPrivatePropertyException' => $baseDir . '/src/Exception/Reflection/MissingPrivatePropertyException.php', 'Rector\\Exception\\Reflection\\MissingPrivatePropertyException' => $baseDir . '/src/Exception/Reflection/MissingPrivatePropertyException.php',
'Rector\\Exception\\ShouldNotHappenException' => $baseDir . '/src/Exception/ShouldNotHappenException.php', 'Rector\\Exception\\ShouldNotHappenException' => $baseDir . '/src/Exception/ShouldNotHappenException.php',

View File

@ -1453,8 +1453,10 @@ class ComposerStaticInit9827c30fbb3017f238cd246d4e8886df
'Rector\\Config\\RegisteredService' => __DIR__ . '/../..' . '/src/Config/RegisteredService.php', 'Rector\\Config\\RegisteredService' => __DIR__ . '/../..' . '/src/Config/RegisteredService.php',
'Rector\\Configuration\\ConfigInitializer' => __DIR__ . '/../..' . '/src/Configuration/ConfigInitializer.php', 'Rector\\Configuration\\ConfigInitializer' => __DIR__ . '/../..' . '/src/Configuration/ConfigInitializer.php',
'Rector\\Configuration\\ConfigurationFactory' => __DIR__ . '/../..' . '/src/Configuration/ConfigurationFactory.php', 'Rector\\Configuration\\ConfigurationFactory' => __DIR__ . '/../..' . '/src/Configuration/ConfigurationFactory.php',
'Rector\\Configuration\\ConfigurationRuleFilter' => __DIR__ . '/../..' . '/src/Configuration/ConfigurationRuleFilter.php',
'Rector\\Configuration\\Deprecation\\Contract\\DeprecatedInterface' => __DIR__ . '/../..' . '/src/Configuration/Deprecation/Contract/DeprecatedInterface.php', 'Rector\\Configuration\\Deprecation\\Contract\\DeprecatedInterface' => __DIR__ . '/../..' . '/src/Configuration/Deprecation/Contract/DeprecatedInterface.php',
'Rector\\Configuration\\Levels\\LevelRulesResolver' => __DIR__ . '/../..' . '/src/Configuration/Levels/LevelRulesResolver.php', 'Rector\\Configuration\\Levels\\LevelRulesResolver' => __DIR__ . '/../..' . '/src/Configuration/Levels/LevelRulesResolver.php',
'Rector\\Configuration\\OnlyRuleResolver' => __DIR__ . '/../..' . '/src/Configuration/OnlyRuleResolver.php',
'Rector\\Configuration\\Option' => __DIR__ . '/../..' . '/src/Configuration/Option.php', 'Rector\\Configuration\\Option' => __DIR__ . '/../..' . '/src/Configuration/Option.php',
'Rector\\Configuration\\Parameter\\SimpleParameterProvider' => __DIR__ . '/../..' . '/src/Configuration/Parameter/SimpleParameterProvider.php', 'Rector\\Configuration\\Parameter\\SimpleParameterProvider' => __DIR__ . '/../..' . '/src/Configuration/Parameter/SimpleParameterProvider.php',
'Rector\\Configuration\\PhpLevelSetResolver' => __DIR__ . '/../..' . '/src/Configuration/PhpLevelSetResolver.php', 'Rector\\Configuration\\PhpLevelSetResolver' => __DIR__ . '/../..' . '/src/Configuration/PhpLevelSetResolver.php',
@ -1742,6 +1744,8 @@ class ComposerStaticInit9827c30fbb3017f238cd246d4e8886df
'Rector\\Enum\\ObjectReference' => __DIR__ . '/../..' . '/src/Enum/ObjectReference.php', 'Rector\\Enum\\ObjectReference' => __DIR__ . '/../..' . '/src/Enum/ObjectReference.php',
'Rector\\Exception\\Cache\\CachingException' => __DIR__ . '/../..' . '/src/Exception/Cache/CachingException.php', 'Rector\\Exception\\Cache\\CachingException' => __DIR__ . '/../..' . '/src/Exception/Cache/CachingException.php',
'Rector\\Exception\\Configuration\\InvalidConfigurationException' => __DIR__ . '/../..' . '/src/Exception/Configuration/InvalidConfigurationException.php', 'Rector\\Exception\\Configuration\\InvalidConfigurationException' => __DIR__ . '/../..' . '/src/Exception/Configuration/InvalidConfigurationException.php',
'Rector\\Exception\\Configuration\\RectorRuleNameAmbigiousException' => __DIR__ . '/../..' . '/src/Exception/Configuration/RectorRuleNameAmbigiousException.php',
'Rector\\Exception\\Configuration\\RectorRuleNotFoundException' => __DIR__ . '/../..' . '/src/Exception/Configuration/RectorRuleNotFoundException.php',
'Rector\\Exception\\NotImplementedYetException' => __DIR__ . '/../..' . '/src/Exception/NotImplementedYetException.php', 'Rector\\Exception\\NotImplementedYetException' => __DIR__ . '/../..' . '/src/Exception/NotImplementedYetException.php',
'Rector\\Exception\\Reflection\\MissingPrivatePropertyException' => __DIR__ . '/../..' . '/src/Exception/Reflection/MissingPrivatePropertyException.php', 'Rector\\Exception\\Reflection\\MissingPrivatePropertyException' => __DIR__ . '/../..' . '/src/Exception/Reflection/MissingPrivatePropertyException.php',
'Rector\\Exception\\ShouldNotHappenException' => __DIR__ . '/../..' . '/src/Exception/ShouldNotHappenException.php', 'Rector\\Exception\\ShouldNotHappenException' => __DIR__ . '/../..' . '/src/Exception/ShouldNotHappenException.php',

View File

@ -512,17 +512,17 @@
}, },
{ {
"name": "illuminate\/container", "name": "illuminate\/container",
"version": "v11.34.2", "version": "v11.35.0",
"version_normalized": "11.34.2.0", "version_normalized": "11.35.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https:\/\/github.com\/illuminate\/container.git", "url": "https:\/\/github.com\/illuminate\/container.git",
"reference": "b057b0bbb38d7c7524df1ca5c38e7318f4c64d26" "reference": "4a777578ce2388384565bf5c8e76881f0da68e54"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https:\/\/api.github.com\/repos\/illuminate\/container\/zipball\/b057b0bbb38d7c7524df1ca5c38e7318f4c64d26", "url": "https:\/\/api.github.com\/repos\/illuminate\/container\/zipball\/4a777578ce2388384565bf5c8e76881f0da68e54",
"reference": "b057b0bbb38d7c7524df1ca5c38e7318f4c64d26", "reference": "4a777578ce2388384565bf5c8e76881f0da68e54",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -533,7 +533,7 @@
"provide": { "provide": {
"psr\/container-implementation": "1.1|2.0" "psr\/container-implementation": "1.1|2.0"
}, },
"time": "2024-11-21T20:07:31+00:00", "time": "2024-12-08T15:40:56+00:00",
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
@ -569,8 +569,8 @@
}, },
{ {
"name": "illuminate\/contracts", "name": "illuminate\/contracts",
"version": "v11.34.2", "version": "v11.35.0",
"version_normalized": "11.34.2.0", "version_normalized": "11.35.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https:\/\/github.com\/illuminate\/contracts.git", "url": "https:\/\/github.com\/illuminate\/contracts.git",

File diff suppressed because one or more lines are too long

View File

@ -255,7 +255,7 @@ class Container implements ArrayAccess, ContainerContract
} }
$concrete = $this->getClosure($abstract, $concrete); $concrete = $this->getClosure($abstract, $concrete);
} }
$this->bindings[$abstract] = \compact('concrete', 'shared'); $this->bindings[$abstract] = ['concrete' => $concrete, 'shared' => $shared];
// If the abstract type was already resolved in this container we'll fire the // If the abstract type was already resolved in this container we'll fire the
// rebound listener so that any objects which have already gotten resolved // rebound listener so that any objects which have already gotten resolved
// can have their copy of the object updated via the listener callbacks. // can have their copy of the object updated via the listener callbacks.