From c76e0060b15779aade9f0621b295f8c0ef40025a Mon Sep 17 00:00:00 2001 From: Carlos Granados Date: Sat, 25 Jan 2025 15:16:35 +0100 Subject: [PATCH] feat: add coding style levels --- config/set/coding-style.php | 65 ++-------------- src/Config/Level/CodingStyleLevel.php | 91 +++++++++++++++++++++++ src/Configuration/RectorConfigBuilder.php | 31 ++++++++ 3 files changed, 129 insertions(+), 58 deletions(-) create mode 100644 src/Config/Level/CodingStyleLevel.php diff --git a/config/set/coding-style.php b/config/set/coding-style.php index 5abadc796e0..f3e5b87c833 100644 --- a/config/set/coding-style.php +++ b/config/set/coding-style.php @@ -2,66 +2,15 @@ declare(strict_types=1); -use Rector\CodingStyle\Rector\Assign\SplitDoubleAssignRector; -use Rector\CodingStyle\Rector\Catch_\CatchExceptionNameMatchingTypeRector; -use Rector\CodingStyle\Rector\ClassConst\RemoveFinalFromConstRector; -use Rector\CodingStyle\Rector\ClassConst\SplitGroupedClassConstantsRector; -use Rector\CodingStyle\Rector\ClassMethod\FuncGetArgsToVariadicParamRector; -use Rector\CodingStyle\Rector\ClassMethod\MakeInheritedMethodVisibilitySameAsParentRector; -use Rector\CodingStyle\Rector\ClassMethod\NewlineBeforeNewAssignSetRector; -use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector; -use Rector\CodingStyle\Rector\Encapsed\WrapEncapsedVariableInCurlyBracesRector; -use Rector\CodingStyle\Rector\FuncCall\CallUserFuncArrayToVariadicRector; -use Rector\CodingStyle\Rector\FuncCall\CallUserFuncToMethodCallRector; -use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector; -use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector; -use Rector\CodingStyle\Rector\FuncCall\StrictArraySearchRector; -use Rector\CodingStyle\Rector\FuncCall\VersionCompareFuncCallToConstantRector; -use Rector\CodingStyle\Rector\If_\NullableCompareToNullRector; -use Rector\CodingStyle\Rector\Property\SplitGroupedPropertiesRector; -use Rector\CodingStyle\Rector\Stmt\NewlineAfterStatementRector; -use Rector\CodingStyle\Rector\Stmt\RemoveUselessAliasInUseStatementRector; -use Rector\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector; -use Rector\CodingStyle\Rector\String_\UseClassKeywordForClassNameResolutionRector; -use Rector\CodingStyle\Rector\Ternary\TernaryConditionVariableAssignmentRector; -use Rector\CodingStyle\Rector\Use_\SeparateMultiUseImportsRector; +use Rector\Config\Level\CodingStyleLevel; use Rector\Config\RectorConfig; -use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; -use Rector\Transform\Rector\FuncCall\FuncCallToConstFetchRector; -use Rector\Visibility\Rector\ClassMethod\ExplicitPublicClassMethodRector; return static function (RectorConfig $rectorConfig): void { - $rectorConfig - ->ruleWithConfiguration(FuncCallToConstFetchRector::class, [ - 'php_sapi_name' => 'PHP_SAPI', - 'pi' => 'M_PI', - ]); + foreach (CodingStyleLevel::RULES_WITH_CONFIGURATION as $rectorClass => $configuration) { + $rectorConfig->ruleWithConfiguration($rectorClass, $configuration); + } - $rectorConfig->rules([ - SeparateMultiUseImportsRector::class, - NewlineAfterStatementRector::class, - RemoveFinalFromConstRector::class, - NullableCompareToNullRector::class, - ConsistentImplodeRector::class, - TernaryConditionVariableAssignmentRector::class, - SymplifyQuoteEscapeRector::class, - StringClassNameToClassConstantRector::class, - CatchExceptionNameMatchingTypeRector::class, - SplitDoubleAssignRector::class, - EncapsedStringsToSprintfRector::class, - WrapEncapsedVariableInCurlyBracesRector::class, - NewlineBeforeNewAssignSetRector::class, - MakeInheritedMethodVisibilitySameAsParentRector::class, - CallUserFuncArrayToVariadicRector::class, - VersionCompareFuncCallToConstantRector::class, - CountArrayToEmptyArrayComparisonRector::class, - CallUserFuncToMethodCallRector::class, - FuncGetArgsToVariadicParamRector::class, - StrictArraySearchRector::class, - UseClassKeywordForClassNameResolutionRector::class, - SplitGroupedPropertiesRector::class, - SplitGroupedClassConstantsRector::class, - ExplicitPublicClassMethodRector::class, - RemoveUselessAliasInUseStatementRector::class, - ]); + // the rule order matters, as its used in withCodingStyleLevel() method + // place the safest rules first, follow by more complex ones + $rectorConfig->rules(CodingStyleLevel::RULES); }; diff --git a/src/Config/Level/CodingStyleLevel.php b/src/Config/Level/CodingStyleLevel.php new file mode 100644 index 00000000000..70310ea85b5 --- /dev/null +++ b/src/Config/Level/CodingStyleLevel.php @@ -0,0 +1,91 @@ +> + */ + public const RULES = [ + SeparateMultiUseImportsRector::class, + NewlineAfterStatementRector::class, + RemoveFinalFromConstRector::class, + NullableCompareToNullRector::class, + ConsistentImplodeRector::class, + TernaryConditionVariableAssignmentRector::class, + SymplifyQuoteEscapeRector::class, + StringClassNameToClassConstantRector::class, + CatchExceptionNameMatchingTypeRector::class, + SplitDoubleAssignRector::class, + EncapsedStringsToSprintfRector::class, + WrapEncapsedVariableInCurlyBracesRector::class, + NewlineBeforeNewAssignSetRector::class, + MakeInheritedMethodVisibilitySameAsParentRector::class, + CallUserFuncArrayToVariadicRector::class, + VersionCompareFuncCallToConstantRector::class, + CountArrayToEmptyArrayComparisonRector::class, + CallUserFuncToMethodCallRector::class, + FuncGetArgsToVariadicParamRector::class, + StrictArraySearchRector::class, + UseClassKeywordForClassNameResolutionRector::class, + SplitGroupedPropertiesRector::class, + SplitGroupedClassConstantsRector::class, + ExplicitPublicClassMethodRector::class, + RemoveUselessAliasInUseStatementRector::class, + ]; + + /** + * @var array, mixed[]> + */ + public const RULES_WITH_CONFIGURATION = [ + FuncCallToConstFetchRector::class => [ + 'php_sapi_name' => 'PHP_SAPI', + 'pi' => 'M_PI', + ], + ]; +} diff --git a/src/Configuration/RectorConfigBuilder.php b/src/Configuration/RectorConfigBuilder.php index 493fc5ff757..fa777e37091 100644 --- a/src/Configuration/RectorConfigBuilder.php +++ b/src/Configuration/RectorConfigBuilder.php @@ -9,6 +9,7 @@ use Rector\Caching\Contract\ValueObject\Storage\CacheStorageInterface; use Rector\Composer\InstalledPackageResolver; use Rector\Config\Level\CodeQualityLevel; +use Rector\Config\Level\CodingStyleLevel; use Rector\Config\Level\DeadCodeLevel; use Rector\Config\Level\TypeDeclarationLevel; use Rector\Config\RectorConfig; @@ -137,6 +138,8 @@ final class RectorConfigBuilder private ?bool $isCodeQualityLevelUsed = null; + private ?bool $isCodingStyleLevelUsed = null; + private ?bool $isFluentNewLine = null; /** @@ -221,6 +224,13 @@ public function __invoke(RectorConfig $rectorConfig): void )); } + if (in_array(SetList::CODING_STYLE, $uniqueSets, true) && $this->isCodingStyleLevelUsed === true) { + throw new InvalidConfigurationException(sprintf( + 'Your config already enables coding style set.%sRemove "->withCodingStyleLevel()" as it only duplicates it, or remove coding style set.', + PHP_EOL + )); + } + if ($uniqueSets !== []) { $rectorConfig->sets($uniqueSets); } @@ -1010,6 +1020,27 @@ public function withCodeQualityLevel(int $level): self return $this; } + /** + * @experimental Raise your coding style from the safest rules + * to more affecting ones, one level at a time + */ + public function withCodingStyleLevel(int $level): self + { + Assert::natural($level); + + $this->isCodingStyleLevelUsed = true; + + $levelRules = LevelRulesResolver::resolve($level, CodingStyleLevel::RULES, __METHOD__); + + $this->rules = array_merge($this->rules, $levelRules); + + foreach (CodingStyleLevel::RULES_WITH_CONFIGURATION as $rectorClass => $configuration) { + $this->rulesWithConfigurations[$rectorClass][] = $configuration; + } + + return $this; + } + public function withFluentCallNewLine(bool $isFluentNewLine = true): self { $this->isFluentNewLine = $isFluentNewLine;