From 709a9bdf437c72367687f49a51cdc8ffabe451d8 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 3 Mar 2025 17:58:26 +0000 Subject: [PATCH] Updated Rector to commit 2bd14ca20d293a22114301f8bcf4b8bcb2a20d77 https://github.com/rectorphp/rector-src/commit/2bd14ca20d293a22114301f8bcf4b8bcb2a20d77 [dx] log rules registered in both withRules() and sets, keep them once to avoid duplications or invalid use (#6761) --- config/set/php-polyfills.php | 5 ++++- src/Application/VersionResolver.php | 4 ++-- src/Configuration/Option.php | 9 ++++++++ src/Configuration/RectorConfigBuilder.php | 25 ++++++++++++----------- src/Console/Command/ProcessCommand.php | 14 +++++++++++-- src/ValueObject/Configuration.php | 12 +++++++++++ 6 files changed, 52 insertions(+), 17 deletions(-) diff --git a/config/set/php-polyfills.php b/config/set/php-polyfills.php index 374eaac079b..28e3cbd0abb 100644 --- a/config/set/php-polyfills.php +++ b/config/set/php-polyfills.php @@ -10,6 +10,9 @@ use Rector\Php80\Rector\Identical\StrEndsWithRector; use Rector\Php80\Rector\Identical\StrStartsWithRector; use Rector\Php80\Rector\NotIdentical\StrContainsRector; use Rector\Php80\Rector\Ternary\GetDebugTypeRector; +// @note longer rule registration must be used here, to separate from withRules() from root rector.php // these rules can be used ahead of PHP version, // as long composer.json includes particular symfony/php-polyfill package -return RectorConfig::configure()->withRules([ArrayKeyFirstLastRector::class, IsCountableRector::class, GetDebugTypeRector::class, StrStartsWithRector::class, StrEndsWithRector::class, StrContainsRector::class]); +return static function (RectorConfig $rectorConfig) : void { + $rectorConfig->rules([ArrayKeyFirstLastRector::class, IsCountableRector::class, GetDebugTypeRector::class, StrStartsWithRector::class, StrEndsWithRector::class, StrContainsRector::class]); +}; diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index f9e77b99d5d..8ef6e0447b9 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '2.0.10'; + public const PACKAGE_VERSION = '2bd14ca20d293a22114301f8bcf4b8bcb2a20d77'; /** * @api * @var string */ - public const RELEASE_DATE = '2025-03-02 22:31:22'; + public const RELEASE_DATE = '2025-03-03 18:54:33'; /** * @var int */ diff --git a/src/Configuration/Option.php b/src/Configuration/Option.php index 5bcf1e964e1..5fd7bccfa5c 100644 --- a/src/Configuration/Option.php +++ b/src/Configuration/Option.php @@ -240,4 +240,13 @@ final class Option * @internal To report overflow levels in ->with*Level() methods */ public const LEVEL_OVERFLOWS = 'level_overflows'; + /** + * @internal To avoid registering rules via ->withRules(), that are already loaded in sets, + * and keep rector.php clean + */ + public const ROOT_STANDALONE_REGISTERED_RULES = 'root_standalone_registered_rules'; + /** + * @internal The other half of ROOT_STANDALONE_REGISTERED_RULES to compare + */ + public const SET_REGISTERED_RULES = 'set_registered_rules'; } diff --git a/src/Configuration/RectorConfigBuilder.php b/src/Configuration/RectorConfigBuilder.php index f773a583ddf..7c77de9cba8 100644 --- a/src/Configuration/RectorConfigBuilder.php +++ b/src/Configuration/RectorConfigBuilder.php @@ -170,6 +170,9 @@ final class RectorConfigBuilder if ($uniqueSets !== []) { $rectorConfig->sets($uniqueSets); } + // log rules from sets and compare them with explicit rules + $setRegisteredRectorClasses = $rectorConfig->getRectorClasses(); + SimpleParameterProvider::addParameter(\Rector\Configuration\Option::SET_REGISTERED_RULES, $setRegisteredRectorClasses); if ($this->paths !== []) { $rectorConfig->paths($this->paths); } @@ -514,6 +517,10 @@ final class RectorConfigBuilder public function withRules(array $rules) : self { $this->rules = \array_merge($this->rules, $rules); + // log all explicitly registered rules + // we only check the non-configurable rules, as the configurable ones might override them + $nonConfigurableRules = \array_filter($rules, fn(string $rule): bool => !\is_a($rule, ConfigurableRectorInterface::class, \true)); + SimpleParameterProvider::addParameter(\Rector\Configuration\Option::ROOT_STANDALONE_REGISTERED_RULES, $nonConfigurableRules); return $this; } /** @@ -753,23 +760,17 @@ final class RectorConfigBuilder } if ($php82) { $this->sets[] = DowngradeLevelSetList::DOWN_TO_PHP_82; - } - if ($php81) { + } elseif ($php81) { $this->sets[] = DowngradeLevelSetList::DOWN_TO_PHP_81; - } - if ($php80) { + } elseif ($php80) { $this->sets[] = DowngradeLevelSetList::DOWN_TO_PHP_80; - } - if ($php74) { + } elseif ($php74) { $this->sets[] = DowngradeLevelSetList::DOWN_TO_PHP_74; - } - if ($php73) { + } elseif ($php73) { $this->sets[] = DowngradeLevelSetList::DOWN_TO_PHP_73; - } - if ($php72) { + } elseif ($php72) { $this->sets[] = DowngradeLevelSetList::DOWN_TO_PHP_72; - } - if ($php71) { + } elseif ($php71) { $this->sets[] = DowngradeLevelSetList::DOWN_TO_PHP_71; } return $this; diff --git a/src/Console/Command/ProcessCommand.php b/src/Console/Command/ProcessCommand.php index 443f85e8d50..3da40fd4c83 100644 --- a/src/Console/Command/ProcessCommand.php +++ b/src/Console/Command/ProcessCommand.php @@ -21,6 +21,7 @@ use Rector\Reporting\MissConfigurationReporter; use Rector\StaticReflection\DynamicSourceLocatorDecorator; use Rector\Util\MemoryLimiter; use Rector\ValueObject\Configuration; +use Rector\ValueObject\Configuration\LevelOverflow; use Rector\ValueObject\ProcessResult; use RectorPrefix202503\Symfony\Component\Console\Application; use RectorPrefix202503\Symfony\Component\Console\Command\Command; @@ -137,8 +138,12 @@ EOF $paths = $configuration->getPaths(); // 0. warn about too high levels foreach ($configuration->getLevelOverflows() as $levelOverflow) { - $suggestedSetMethod = \PHP_VERSION_ID >= 80000 ? \sprintf('->withPreparedSets(%s: true)', $levelOverflow->getSuggestedRuleset()) : \sprintf('->withSets(SetList::%s)', $levelOverflow->getSuggestedSetListConstant()); - $this->symfonyStyle->warning(\sprintf('The "->%s()" level contains only %d rules, but you set level to %d.%sYou are using the full set now! Time to switch to more efficient "%s".', $levelOverflow->getConfigurationName(), $levelOverflow->getRuleCount(), $levelOverflow->getLevel(), \PHP_EOL, $suggestedSetMethod)); + $this->reportLevelOverflow($levelOverflow); + } + // 0. warn about rules registered in both withRules() and sets to avoid bloated rector.php configs + $setAndRulesDuplicatedRegistrations = $configuration->getBothSetAndRulesDuplicatedRegistrations(); + if ($setAndRulesDuplicatedRegistrations !== []) { + $this->symfonyStyle->warning(\sprintf('These rules are registered in both sets and "withRules()". Remove them from "withRules()" to avoid duplications: %s* %s', \PHP_EOL . \PHP_EOL, \implode(' * ', $setAndRulesDuplicatedRegistrations) . \PHP_EOL)); } // 1. add files and directories to static locator $this->dynamicSourceLocatorDecorator->addPaths($paths); @@ -217,4 +222,9 @@ EOF $this->symfonyStyle->writeln('[info] Sets loaded based on installed packages:'); $this->symfonyStyle->listing($composerBasedSets); } + private function reportLevelOverflow(LevelOverflow $levelOverflow) : void + { + $suggestedSetMethod = \PHP_VERSION_ID >= 80000 ? \sprintf('->withPreparedSets(%s: true)', $levelOverflow->getSuggestedRuleset()) : \sprintf('->withSets(SetList::%s)', $levelOverflow->getSuggestedSetListConstant()); + $this->symfonyStyle->warning(\sprintf('The "->%s()" level contains only %d rules, but you set level to %d.%sYou are using the full set now! Time to switch to more efficient "%s".', $levelOverflow->getConfigurationName(), $levelOverflow->getRuleCount(), $levelOverflow->getLevel(), \PHP_EOL, $suggestedSetMethod)); + } } diff --git a/src/ValueObject/Configuration.php b/src/ValueObject/Configuration.php index c25f21eae6c..131defbd3e4 100644 --- a/src/ValueObject/Configuration.php +++ b/src/ValueObject/Configuration.php @@ -4,6 +4,8 @@ declare (strict_types=1); namespace Rector\ValueObject; use Rector\ChangesReporting\Output\ConsoleOutputFormatter; +use Rector\Configuration\Option; +use Rector\Configuration\Parameter\SimpleParameterProvider; use Rector\ValueObject\Configuration\LevelOverflow; use RectorPrefix202503\Webmozart\Assert\Assert; final class Configuration @@ -176,4 +178,14 @@ final class Configuration { return $this->levelOverflows; } + /** + * @return string[] + */ + public function getBothSetAndRulesDuplicatedRegistrations() : array + { + $rootStandaloneRegisteredRules = SimpleParameterProvider::provideArrayParameter(Option::ROOT_STANDALONE_REGISTERED_RULES); + $setRegisteredRules = SimpleParameterProvider::provideArrayParameter(Option::SET_REGISTERED_RULES); + $ruleDuplicatedRegistrations = \array_intersect($rootStandaloneRegisteredRules, $setRegisteredRules); + return \array_unique($ruleDuplicatedRegistrations); + } }