diff --git a/.circleci/config.yml b/.circleci/config.yml index f85604b..6e46a7b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -106,19 +106,29 @@ workflows: - documentation: matrix: parameters: - php-version: ["8.2"] + php-version: + - "8.3" - tests: matrix: parameters: - php-version: ["8.0", "8.1", "8.2"] + php-version: + - "8.1" + - "8.2" + - "8.3" - tests-with-future-mode: matrix: parameters: - php-version: ["8.0", "8.1", "8.2"] + php-version: + - "8.1" + - "8.2" + - "8.3" - tests-with-lowest-dependencies: matrix: parameters: - php-version: ["8.0", "8.1", "8.2"] + php-version: + - "8.1" + - "8.2" + - "8.3" - release-test - release: requires: diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 001dda6..c1ab6a4 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -4,13 +4,16 @@ use PedroTroller\CS\Fixer\Fixers; use PedroTroller\CS\Fixer\RuleSetFactory; +use PhpCsFixer\Config; +use PhpCsFixer\Finder; -return (new PhpCsFixer\Config()) +return (new Config()) ->setRiskyAllowed(true) ->setRules( RuleSetFactory::create() + ->per(2, true) ->phpCsFixer(true) - ->php(8.0, true) + ->php(8.1, true) ->pedrotroller(true) ->enable('align_multiline_comment') ->enable('array_indentation') @@ -33,7 +36,7 @@ ->setUsingCache(false) ->registerCustomFixers(new Fixers()) ->setFinder( - PhpCsFixer\Finder::create() + Finder::create() ->in(__DIR__) ->append([__FILE__, __DIR__.'/bin/doc']) ) diff --git a/README.md b/README.md index 6d36aee..08d29ed 100644 --- a/README.md +++ b/README.md @@ -384,12 +384,12 @@ Prohibited functions MUST BE commented on as prohibited ### Available options - - `functions` (*optional*): The function names to be marked how prohibited - - default: `var_dump`, `dump`, `die` - - `comment` (*optional*): The prohibition message to put in the comment - default: `@TODO remove this line` + - `functions` (*optional*): The function names to be marked how prohibited + - default: `var_dump`, `dump`, `die` + ### Configuration examples ```php @@ -511,18 +511,18 @@ If the declaration of a method is too long, the arguments of this method MUST BE ### Available options - - `max-args` (*optional*): The maximum number of arguments allowed with splitting the arguments into several lines (use `false` to disable this feature) - - default: `3` - - - `max-length` (*optional*): The maximum number of characters allowed with splitting the arguments into several lines - - default: `120` - - `automatic-argument-merge` (*optional*): If both conditions are met (the line is not too long and there are not too many arguments), then the arguments are put back inline - default: `true` - `inline-attributes` (*optional*): In the case of a split, the declaration of the attributes of the arguments of the method will be on the same line as the arguments themselves - default: `false` + - `max-args` (*optional*): The maximum number of arguments allowed with splitting the arguments into several lines (use `false` to disable this feature) + - default: `3` + + - `max-length` (*optional*): The maximum number of characters allowed with splitting the arguments into several lines + - default: `120` + ### Configuration examples ```php diff --git a/bin/Utils.php b/bin/Utils.php index 871d946..b21abba 100644 --- a/bin/Utils.php +++ b/bin/Utils.php @@ -4,7 +4,7 @@ final class Utils { - public static function arrayToString(array $array = null) + public static function arrayToString(?array $array = null) { if (null === $array) { return; @@ -15,7 +15,7 @@ public static function arrayToString(array $array = null) if (array_values($array) === $array) { $string .= implode(', ', array_map([self::class, 'valueToString'], $array)); } else { - $string .= implode(', ', array_map(fn ($value, $key) => '\''.$key.'\' => '.self::valueToString($value), $array, array_keys($array))); + $string .= implode(', ', array_map(static fn ($value, $key) => '\''.$key.'\' => '.self::valueToString($value), $array, array_keys($array))); } $string .= ' ]'; diff --git a/bin/doc b/bin/doc index 2a9eb34..08fa01f 100755 --- a/bin/doc +++ b/bin/doc @@ -1,7 +1,10 @@ #!/usr/bin/env php getDefinition()->getCodeSamples(); return [ @@ -25,7 +28,7 @@ $fixers = array_map(function (AbstractFixer $fixer) { 'deprecated' => $fixer->isDeprecated(), 'replacement' => $fixer->getDeprecationReplacement(), 'options' => array_map( - function (FixerOptionInterface $option) { + static function (FixerOptionInterface $option) { return [ 'name' => $option->getName(), 'description' => $option->getDescription(), @@ -39,7 +42,7 @@ $fixers = array_map(function (AbstractFixer $fixer) { ? $fixer->getConfigurationDefinition()->getOptions() : [] ), - 'samples' => array_map(function (CodeSample $sample) use ($fixer) { + 'samples' => array_map(static function (CodeSample $sample) use ($fixer) { if ($fixer instanceof ConfigurableFixerInterface) { $fixer->configure($sample->getConfiguration()); } @@ -57,13 +60,13 @@ $fixers = array_map(function (AbstractFixer $fixer) { } while (strlen($line) < 80 + 1) { - $line = $line.' '; + $line .= ' '; } if (0 === $num) { - $line = $line.'// 80 chars'; + $line .= '// 80 chars'; } else { - $line = $line.'//'; + $line .= '//'; } $diff[$num] = $line; @@ -80,7 +83,7 @@ $fixers = array_map(function (AbstractFixer $fixer) { ]; }, $samples), ]; -}, iterator_to_array(new PedroTroller\CS\Fixer\Fixers())); +}, [...(new Fixers())]); $loader = new FilesystemLoader([__DIR__]); $twig = new Environment($loader); diff --git a/composer.json b/composer.json index af442f9..87d66a1 100644 --- a/composer.json +++ b/composer.json @@ -3,15 +3,18 @@ "description": "PHP-CS-FIXER : my custom fixers", "license": "MIT", "require": { - "php": "^8.0" + "php": "^8.1", + "friendsofphp/php-cs-fixer": ">=3.59.3" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.17", + "friendsofphp/php-cs-fixer": "^3.60", "phpspec/phpspec": "^7.0", "sebastian/diff": "^4.0", "twig/twig": "^3.3", "webmozart/assert": "^1.10" }, + "minimum-stability": "dev", + "prefer-stable": true, "autoload": { "psr-4": { "PedroTroller\\CS\\Fixer\\": "src/PedroTroller/CS/Fixer" @@ -31,19 +34,17 @@ "dev-master": "3.x-dev" } }, - "minimum-stability": "dev", - "prefer-stable": true, "scripts": { - "tests": [ - "tests\\Runner::run", - "tests\\Orchestra::run", - "phpspec run -fpretty" + "lint": [ + "@php-cs-fixer" ], "php-cs-fixer": [ "php-cs-fixer fix --dry-run -vvv --diff" ], - "lint": [ - "@php-cs-fixer" + "tests": [ + "tests\\Runner::run", + "tests\\Orchestra::run", + "phpspec run -fpretty" ] } } diff --git a/doc/rule-set-factory.md b/doc/rule-set-factory.md index a132bc0..a8787b2 100644 --- a/doc/rule-set-factory.md +++ b/doc/rule-set-factory.md @@ -11,7 +11,7 @@ return PhpCsFixer\Config::create() ->setRules(RuleSetFactory::create() ->symfony() // Activate the @Symfony ruleset ->phpCsFixer() // Activate the @PhpCsFixer ruleset - ->php(5.6, true) // Activate php 5.6 risky rules + ->php(8.2, true) // Activate php 8.2 risky rules ->pedrotroller(true) // Activate my own ruleset (with risky rules) ->enable('ordered_imports') // Add an other rule ->disable('yoda_style') // Disable a rule @@ -26,6 +26,10 @@ return PhpCsFixer\Config::create() ## Methods +### `->per([int|float $version = null, [bool $risky = false]])` + +Activate the `@PER` (`@PER-CS1.0`, `@PER-CS1.0:risky`, `@PER-CS2.0`, `@PER-CS2.0:risky`, ...) rule. + ### `->psr0()` Activate the `@psr0` rule. diff --git a/spec/PedroTroller/CS/Fixer/RuleSetFactorySpec.php b/spec/PedroTroller/CS/Fixer/RuleSetFactorySpec.php index 7dfedb2..5d1c0bc 100644 --- a/spec/PedroTroller/CS/Fixer/RuleSetFactorySpec.php +++ b/spec/PedroTroller/CS/Fixer/RuleSetFactorySpec.php @@ -10,11 +10,46 @@ final class RuleSetFactorySpec extends ObjectBehavior { + function let() + { + $this->beConstructedThrough('create'); + } + function it_is_initializable() { $this->shouldHaveType(RuleSetFactory::class); } + function it_adds_a_per_set() + { + $this->per()->getRules()->shouldReturn(['@PER' => true]); + } + + function it_adds_a_per_risky_set() + { + $this->per(risky: true)->getRules()->shouldReturn(['@PER:risky' => true]); + } + + function it_adds_a_per1_0_set() + { + $this->per(1)->getRules()->shouldReturn(['@PER-CS1.0' => true]); + } + + function it_adds_a_per1_0_risky_set() + { + $this->per(1, true)->getRules()->shouldReturn(['@PER-CS1.0:risky' => true]); + } + + function it_adds_a_per2_0_set() + { + $this->per(2)->getRules()->shouldReturn(['@PER-CS2.0' => true]); + } + + function it_adds_a_per2_0_risky_set() + { + $this->per(2, true)->getRules()->shouldReturn(['@PER-CS2.0:risky' => true]); + } + function it_adds_a_psr0_set() { $this->psr0()->getRules()->shouldReturn(['@psr0' => true]); @@ -144,15 +179,6 @@ function it_adds_a_php_version_support() ]); } - function it_can_also_parse_versions_as_string() - { - $this->php('5.6.2')->getRules()->shouldReturn([ - '@PHP54Migration' => true, - 'array_syntax' => ['syntax' => 'short'], - 'list_syntax' => ['syntax' => 'long'], - ]); - } - function it_adds_a_phpunit_version_support() { $this->phpUnit(2.0, false)->getRules()->shouldReturn([]); @@ -310,8 +336,6 @@ function it_adds_my_own_fixer_set() $rules[$fixer->getName()] = true; } - ksort($rules); - $this->pedrotroller(true)->getRules()->shouldReturn($rules); } @@ -327,8 +351,6 @@ function it_adds_my_own_fixer_set_except_privates() $rules[$fixer->getName()] = true; } - ksort($rules); - $this->pedrotroller(false)->getRules()->shouldReturn($rules); } diff --git a/src/PedroTroller/CS/Fixer/AbstractFixer.php b/src/PedroTroller/CS/Fixer/AbstractFixer.php index 549e599..eecec51 100644 --- a/src/PedroTroller/CS/Fixer/AbstractFixer.php +++ b/src/PedroTroller/CS/Fixer/AbstractFixer.php @@ -23,7 +23,7 @@ public function isCandidate(Tokens $tokens): bool public function getName(): string { - return sprintf('PedroTroller/%s', parent::getName()); + return \sprintf('PedroTroller/%s', parent::getName()); } /** @@ -45,7 +45,7 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( $this->getDocumentation(), array_map( - fn (array $configutation = null) => new CodeSample($this->getSampleCode(), $configutation), + fn (?array $configutation = null) => new CodeSample($this->getSampleCode(), $configutation), $this->getSampleConfigurations() ) ); diff --git a/src/PedroTroller/CS/Fixer/Behat/OrderBehatStepsFixer.php b/src/PedroTroller/CS/Fixer/Behat/OrderBehatStepsFixer.php index ea44517..70f5fed 100644 --- a/src/PedroTroller/CS/Fixer/Behat/OrderBehatStepsFixer.php +++ b/src/PedroTroller/CS/Fixer/Behat/OrderBehatStepsFixer.php @@ -8,6 +8,7 @@ use PedroTroller\CS\Fixer\Priority; use PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer; use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ConfigurableFixerTrait; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; @@ -15,6 +16,8 @@ final class OrderBehatStepsFixer extends AbstractOrderedClassElementsFixer implements ConfigurableFixerInterface { + use ConfigurableFixerTrait; + public const ANNOTATION_PRIORITIES = [ '@BeforeSuite', '@AfterSuite', @@ -126,7 +129,7 @@ public function getDocumentation(): string return 'Step definition methods in Behat contexts MUST BE ordered by annotation and method name.'; } - public function getConfigurationDefinition(): FixerConfigurationResolverInterface + public function createConfigurationDefinition(): FixerConfigurationResolverInterface { return new FixerConfigurationResolver([ (new FixerOptionBuilder('instanceof', 'Parent class or interface of your behat context classes.')) diff --git a/src/PedroTroller/CS/Fixer/ClassNotation/OrderedWithGetterAndSetterFirstFixer.php b/src/PedroTroller/CS/Fixer/ClassNotation/OrderedWithGetterAndSetterFirstFixer.php index 487f44e..dca0e9a 100644 --- a/src/PedroTroller/CS/Fixer/ClassNotation/OrderedWithGetterAndSetterFirstFixer.php +++ b/src/PedroTroller/CS/Fixer/ClassNotation/OrderedWithGetterAndSetterFirstFixer.php @@ -152,11 +152,11 @@ private function getMethodsNames(array $elements): array $methods = []; foreach ($this->getPropertiesNames($elements) as $name) { - $methods[] = sprintf('get%s', ucfirst($name)); - $methods[] = sprintf('is%s', ucfirst($name)); - $methods[] = sprintf('has%s', ucfirst($name)); + $methods[] = \sprintf('get%s', ucfirst($name)); + $methods[] = \sprintf('is%s', ucfirst($name)); + $methods[] = \sprintf('has%s', ucfirst($name)); $methods[] = lcfirst($name); - $methods[] = sprintf('set%s', ucfirst($name)); + $methods[] = \sprintf('set%s', ucfirst($name)); } return $methods; @@ -164,8 +164,8 @@ private function getMethodsNames(array $elements): array private function getPropertiesNames(array $elements): array { - $properties = array_filter($elements, fn ($element) => 'property' === $element['type']); + $properties = array_filter($elements, static fn ($element) => 'property' === $element['type']); - return array_map(fn ($element) => ltrim($element['propertyName'], '$'), $properties); + return array_map(static fn ($element) => ltrim($element['propertyName'], '$'), $properties); } } diff --git a/src/PedroTroller/CS/Fixer/CodingStyle/ExceptionsPunctuationFixer.php b/src/PedroTroller/CS/Fixer/CodingStyle/ExceptionsPunctuationFixer.php index c2a0add..a8c447e 100644 --- a/src/PedroTroller/CS/Fixer/CodingStyle/ExceptionsPunctuationFixer.php +++ b/src/PedroTroller/CS/Fixer/CodingStyle/ExceptionsPunctuationFixer.php @@ -152,6 +152,6 @@ private function cleanupMessage(Token $token): Token return $token; } - return new Token([T_CONSTANT_ENCAPSED_STRING, sprintf('%s%s.%s', $quotes, implode('', $chars), $quotes)]); + return new Token([T_CONSTANT_ENCAPSED_STRING, \sprintf('%s%s.%s', $quotes, implode('', $chars), $quotes)]); } } diff --git a/src/PedroTroller/CS/Fixer/CodingStyle/ForbiddenFunctionsFixer.php b/src/PedroTroller/CS/Fixer/CodingStyle/ForbiddenFunctionsFixer.php index a75f975..868b89e 100644 --- a/src/PedroTroller/CS/Fixer/CodingStyle/ForbiddenFunctionsFixer.php +++ b/src/PedroTroller/CS/Fixer/CodingStyle/ForbiddenFunctionsFixer.php @@ -6,6 +6,7 @@ use PedroTroller\CS\Fixer\AbstractFixer; use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ConfigurableFixerTrait; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; @@ -15,6 +16,8 @@ final class ForbiddenFunctionsFixer extends AbstractFixer implements ConfigurableFixerInterface { + use ConfigurableFixerTrait; + public function getSampleCode(): string { return <<<'PHP' @@ -53,7 +56,7 @@ public function getDocumentation(): string return 'Prohibited functions MUST BE commented on as prohibited'; } - public function getConfigurationDefinition(): FixerConfigurationResolverInterface + public function createConfigurationDefinition(): FixerConfigurationResolverInterface { return new FixerConfigurationResolver([ (new FixerOptionBuilder('functions', 'The function names to be marked how prohibited')) @@ -86,7 +89,7 @@ protected function applyFix(SplFileInfo $file, Tokens $tokens): void if (\in_array($token->getContent(), $this->configuration['functions'], true)) { $end = $this->analyze($tokens)->getEndOfTheLine($index); - $tokens[$end] = new Token([T_WHITESPACE, sprintf(' // %s%s', $this->configuration['comment'], $tokens[$end]->getContent())]); + $tokens[$end] = new Token([T_WHITESPACE, \sprintf(' // %s%s', $this->configuration['comment'], $tokens[$end]->getContent())]); } } } diff --git a/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenMethodArgumentsFixer.php b/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenMethodArgumentsFixer.php index 3c7115a..988f750 100644 --- a/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenMethodArgumentsFixer.php +++ b/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenMethodArgumentsFixer.php @@ -8,6 +8,8 @@ use PedroTroller\CS\Fixer\Priority; use PhpCsFixer\Fixer\Basic\BracesFixer; use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ConfigurableFixerTrait; +use PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer; use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; @@ -18,11 +20,16 @@ final class LineBreakBetweenMethodArgumentsFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface { + use ConfigurableFixerTrait; + public const T_TYPEHINT_SEMI_COLON = 10025; public function getPriority(): int { - return Priority::after(BracesFixer::class); + return min( + Priority::after(BracesFixer::class), + Priority::after(MethodArgumentSpaceFixer::class), + ); } public function getSampleConfigurations(): array @@ -77,7 +84,7 @@ public function fun3( SPEC; } - public function getConfigurationDefinition(): FixerConfigurationResolverInterface + public function createConfigurationDefinition(): FixerConfigurationResolverInterface { return new FixerConfigurationResolver([ (new FixerOptionBuilder('max-args', 'The maximum number of arguments allowed with splitting the arguments into several lines (use `false` to disable this feature)')) diff --git a/src/PedroTroller/CS/Fixer/Comment/CommentLineToPhpdocBlockFixer.php b/src/PedroTroller/CS/Fixer/Comment/CommentLineToPhpdocBlockFixer.php index 8407552..cedd462 100644 --- a/src/PedroTroller/CS/Fixer/Comment/CommentLineToPhpdocBlockFixer.php +++ b/src/PedroTroller/CS/Fixer/Comment/CommentLineToPhpdocBlockFixer.php @@ -148,11 +148,11 @@ private function formatComments(array $comments, string $indentation): string array_pop($comments); } - $comments = array_map(fn ($comment) => rtrim($indentation.' * '.ltrim($comment, ' /')), $comments); + $comments = array_map(static fn ($comment) => rtrim($indentation.' * '.ltrim($comment, ' /')), $comments); $comments = implode("\n", $comments); $comments = trim($comments, " \n"); - return sprintf("/**\n%s %s\n%s */", $indentation, $comments, $indentation); + return \sprintf("/**\n%s %s\n%s */", $indentation, $comments, $indentation); } } diff --git a/src/PedroTroller/CS/Fixer/DeadCode/UselessCodeAfterReturnFixer.php b/src/PedroTroller/CS/Fixer/DeadCode/UselessCodeAfterReturnFixer.php index d68461f..4b6d20a 100644 --- a/src/PedroTroller/CS/Fixer/DeadCode/UselessCodeAfterReturnFixer.php +++ b/src/PedroTroller/CS/Fixer/DeadCode/UselessCodeAfterReturnFixer.php @@ -83,7 +83,7 @@ protected function applyFix(SplFileInfo $file, Tokens $tokens): void $possible = array_merge($possible, array_keys($ends)); } - $possible = array_filter($possible, fn ($value) => null !== $value); + $possible = array_filter($possible, static fn ($value) => null !== $value); if (empty($possible)) { continue; diff --git a/src/PedroTroller/CS/Fixer/DoctrineMigrationsFixer.php b/src/PedroTroller/CS/Fixer/DoctrineMigrationsFixer.php index 94bc5e2..92b9545 100644 --- a/src/PedroTroller/CS/Fixer/DoctrineMigrationsFixer.php +++ b/src/PedroTroller/CS/Fixer/DoctrineMigrationsFixer.php @@ -6,6 +6,7 @@ use PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer; use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ConfigurableFixerTrait; use PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer; use PhpCsFixer\Fixer\Whitespace\NoExtraBlankLinesFixer; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; @@ -17,6 +18,8 @@ final class DoctrineMigrationsFixer extends AbstractFixer implements ConfigurableFixerInterface { + use ConfigurableFixerTrait; + /** * @var string[] */ @@ -100,7 +103,7 @@ public function getPriority(): int return Priority::before(ClassAttributesSeparationFixer::class, NoEmptyPhpdocFixer::class, NoExtraBlankLinesFixer::class); } - public function getConfigurationDefinition(): FixerConfigurationResolverInterface + public function createConfigurationDefinition(): FixerConfigurationResolverInterface { return new FixerConfigurationResolver([ (new FixerOptionBuilder('instanceof', 'The parent class of which Doctrine migrations extend')) diff --git a/src/PedroTroller/CS/Fixer/Fixers.php b/src/PedroTroller/CS/Fixer/Fixers.php index 3f16380..aeac81f 100644 --- a/src/PedroTroller/CS/Fixer/Fixers.php +++ b/src/PedroTroller/CS/Fixer/Fixers.php @@ -23,7 +23,7 @@ public function getIterator(): Generator ; $files = array_map( - fn ($file) => $file->getPathname(), + static fn ($file) => $file->getPathname(), iterator_to_array($finder) ); diff --git a/src/PedroTroller/CS/Fixer/PhpspecFixer.php b/src/PedroTroller/CS/Fixer/PhpspecFixer.php index e92f0e6..07ad383 100644 --- a/src/PedroTroller/CS/Fixer/PhpspecFixer.php +++ b/src/PedroTroller/CS/Fixer/PhpspecFixer.php @@ -6,6 +6,7 @@ use PhpCsFixer\Fixer\ClassNotation\VisibilityRequiredFixer; use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ConfigurableFixerTrait; use PhpCsFixer\Fixer\FunctionNotation\StaticLambdaFixer; use PhpCsFixer\Fixer\FunctionNotation\VoidReturnFixer; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; @@ -17,6 +18,8 @@ final class PhpspecFixer extends AbstractOrderedClassElementsFixer implements ConfigurableFixerInterface { + use ConfigurableFixerTrait; + public function getSampleConfigurations(): array { return [ @@ -101,7 +104,7 @@ public function getPriority(): int ); } - public function getConfigurationDefinition(): FixerConfigurationResolverInterface + public function createConfigurationDefinition(): FixerConfigurationResolverInterface { return new FixerConfigurationResolver([ (new FixerOptionBuilder('instanceof', 'Parent classes of your spec classes.')) @@ -262,7 +265,7 @@ private function filterElementsByMethodName(string $regex, array $elements): arr $filter = []; foreach ($this->filterElementsByType('method', $elements) as $index => $method) { - if (0 !== preg_match(sprintf('/^%s$/', $regex), $method['methodName'])) { + if (0 !== preg_match(\sprintf('/^%s$/', $regex), $method['methodName'])) { $filter[$index] = $method; } } diff --git a/src/PedroTroller/CS/Fixer/Priority.php b/src/PedroTroller/CS/Fixer/Priority.php index 6d6d5ae..005fe98 100644 --- a/src/PedroTroller/CS/Fixer/Priority.php +++ b/src/PedroTroller/CS/Fixer/Priority.php @@ -6,9 +6,7 @@ final class Priority { - private function __construct() - { - } + private function __construct() {} /** * @param array $classes @@ -18,7 +16,7 @@ private function __construct() public static function before(...$classes) { $priorities = array_map( - fn ($class) => (new $class())->getPriority(), + static fn ($class) => (new $class())->getPriority(), $classes ); @@ -33,7 +31,7 @@ public static function before(...$classes) public static function after(...$classes) { $priorities = array_map( - fn ($class) => (new $class())->getPriority(), + static fn ($class) => (new $class())->getPriority(), $classes ); diff --git a/src/PedroTroller/CS/Fixer/RuleSetFactory.php b/src/PedroTroller/CS/Fixer/RuleSetFactory.php index 66b5f52..dc2d0d9 100644 --- a/src/PedroTroller/CS/Fixer/RuleSetFactory.php +++ b/src/PedroTroller/CS/Fixer/RuleSetFactory.php @@ -4,44 +4,85 @@ namespace PedroTroller\CS\Fixer; +use Exception; +use IteratorAggregate; use PhpCsFixer\RuleSet\RuleSets; +use Traversable; -final class RuleSetFactory +/** + * @IteratorAggregate> + */ +final class RuleSetFactory implements IteratorAggregate { /** - * @var array[] + * @var array|bool> */ private $rules; - public function __construct(array $rules = []) + /** + * @var array + */ + private array $cache; + + /** + * @param array|bool> $rules + * @param array $cache + */ + private function __construct(array $rules, array $cache) { $this->rules = $rules; + $this->cache = $cache; } /** - * @return array + * @return array|bool> */ - public function getRules() + public function getRules(): array { - $rules = $this->rules; + return $this->rules; + } - ksort($rules); + public function getIterator(): Traversable + { + yield from $this->rules; + } - return $rules; + public static function create(array $rules = []): self + { + return new self( + $rules, + (new RuleSets())->getSetDefinitionNames(), + ); } - /** - * @return RuleSetFactory - */ - public static function create(array $rules = []) + public function per(null|float|int $version = null, bool $risky = false): self { - return new self($rules); + $candidates = null !== $version + ? ['@PER-CS'.number_format($version, 1, '.', '')] + : ['@PER']; + + if (true === $risky) { + $candidates = [ + $candidates[0].':risky', + ...$candidates, + ]; + } + + foreach ($candidates as $candidate) { + if (false === \in_array($candidate, $this->cache, true)) { + continue; + } + + return self::create(array_merge( + $this->rules, + [$candidate => true], + )); + } + + throw new Exception('RuleSet not found: '.implode(', ', $candidates)); } - /** - * @return RuleSetFactory - */ - public function psr0() + public function psr0(): self { return self::create(array_merge( $this->rules, @@ -49,10 +90,7 @@ public function psr0() )); } - /** - * @return RuleSetFactory - */ - public function psr1() + public function psr1(): self { return self::create(array_merge( $this->rules, @@ -60,10 +98,7 @@ public function psr1() )); } - /** - * @return RuleSetFactory - */ - public function psr2() + public function psr2(): self { return self::create(array_merge( $this->rules, @@ -71,10 +106,7 @@ public function psr2() )); } - /** - * @return RuleSetFactory - */ - public function psr4() + public function psr4(): self { return self::create(array_merge( $this->rules, @@ -82,12 +114,7 @@ public function psr4() )); } - /** - * @param bool $risky - * - * @return RuleSetFactory - */ - public function symfony($risky = false) + public function symfony(bool $risky = false): self { $rules = ['@Symfony' => true]; @@ -101,12 +128,7 @@ public function symfony($risky = false) )); } - /** - * @param bool $risky - * - * @return RuleSetFactory - */ - public function phpCsFixer($risky = false) + public function phpCsFixer(bool $risky = false): self { $rules = ['@PhpCsFixer' => true]; @@ -120,10 +142,7 @@ public function phpCsFixer($risky = false) )); } - /** - * @return RuleSetFactory - */ - public function doctrineAnnotation() + public function doctrineAnnotation(): self { return self::create(array_merge( $this->rules, @@ -131,27 +150,20 @@ public function doctrineAnnotation() )); } - /** - * @param float|string $version - * @param bool $risky - * - * @return RuleSetFactory - */ - public function php($version, $risky = false) + public function php(float $version, bool $risky = false): self { $config = $this->migration('php', $version, $risky)->getRules(); - switch (true) { - case $version >= 7.1: - $config = array_merge(['list_syntax' => ['syntax' => 'short']], $config); + $config['array_syntax'] = ['syntax' => 'long']; + $config['list_syntax'] = ['syntax' => 'long']; - // no break - case $version >= 5.4: - $config = array_merge(['array_syntax' => ['syntax' => 'short']], $config); + if ($version >= 7.1) { + $config['list_syntax'] = ['syntax' => 'short']; } - $config = array_merge(['list_syntax' => ['syntax' => 'long']], $config); - $config = array_merge(['array_syntax' => ['syntax' => 'long']], $config); + if ($version >= 5.4) { + $config['array_syntax'] = ['syntax' => 'short']; + } return self::create(array_merge( $this->rules, @@ -159,23 +171,12 @@ public function php($version, $risky = false) )); } - /** - * @param float $version - * @param bool $risky - * - * @return RuleSetFactory - */ - public function phpUnit($version, $risky = false) + public function phpUnit(float $version, bool $risky = false): self { return $this->migration('phpunit', $version, $risky); } - /** - * @param bool $risky - * - * @return RuleSetFactory - */ - public function pedrotroller($risky = false) + public function pedrotroller(bool $risky = false): self { $rules = []; @@ -191,20 +192,13 @@ public function pedrotroller($risky = false) $rules[$fixer->getName()] = true; } - ksort($rules); - return self::create(array_merge( $this->rules, $rules )); } - /** - * @param string $name - * - * @return RuleSetFactory - */ - public function enable($name, array $config = null) + public function enable(string $name, ?array $config = null): self { return self::create(array_merge( $this->rules, @@ -212,12 +206,7 @@ public function enable($name, array $config = null) )); } - /** - * @param string $name - * - * @return RuleSetFactory - */ - public function disable($name) + public function disable(string $name): self { return self::create(array_merge( $this->rules, @@ -225,39 +214,33 @@ public function disable($name) )); } - /** - * @param string $package - * @param float $version - * @param bool $risky - * - * @return RuleSetFactory - */ - private function migration($package, $version, $risky) + private function migration(string $package, float $version, bool $risky): self { - $rules = (new RuleSets())->getSetDefinitionNames(); - $rules = array_combine($rules, $rules); - - $rules = array_map(function ($name) { - preg_match('/^@([A-Za-z]+)(\d+)Migration(:risky|)$/', $name, $matches); + $rules = array_combine($this->cache, $this->cache); + $rules = array_map( + static function ($name) { + preg_match('/^@([A-Za-z]+)(\d+)Migration(:risky|)$/', $name, $matches); - return $matches; - }, $rules); + return $matches; + }, + $rules + ); $rules = array_filter($rules); - $rules = array_filter($rules, function ($versionAndRisky) use ($package) { + $rules = array_filter($rules, static function ($versionAndRisky) use ($package) { [$rule, $rulePackage, $ruleVersion, $ruleRisky] = $versionAndRisky; return strtoupper($package) === strtoupper($rulePackage); }); - $rules = array_filter($rules, function ($versionAndRisky) use ($version) { + $rules = array_filter($rules, static function ($versionAndRisky) use ($version) { [$rule, $rulePackage, $ruleVersion, $ruleRisky] = $versionAndRisky; return ((float) $ruleVersion / 10) <= $version; }); - $rules = array_filter($rules, function ($versionAndRisky) use ($risky) { + $rules = array_filter($rules, static function ($versionAndRisky) use ($risky) { [$rule, $rulePackage, $ruleVersion, $ruleRisky] = $versionAndRisky; if ($risky) { @@ -269,7 +252,7 @@ private function migration($package, $version, $risky) return self::create(array_merge( $this->rules, - array_map(fn () => true, $rules) + array_map(static fn () => true, $rules) )); } } diff --git a/src/PedroTroller/CS/Fixer/TokenSignatures.php b/src/PedroTroller/CS/Fixer/TokenSignatures.php index 06ad2b6..3e535d2 100644 --- a/src/PedroTroller/CS/Fixer/TokenSignatures.php +++ b/src/PedroTroller/CS/Fixer/TokenSignatures.php @@ -9,7 +9,5 @@ final class TokenSignatures public const TYPINT_OPTIONAL = 10022; public const TYPINT_DOUBLE_DOTS = 10025; - public function __construct() - { - } + public function __construct() {} } diff --git a/src/PedroTroller/CS/Fixer/TokensAnalyzer.php b/src/PedroTroller/CS/Fixer/TokensAnalyzer.php index f356f96..d80b50b 100644 --- a/src/PedroTroller/CS/Fixer/TokensAnalyzer.php +++ b/src/PedroTroller/CS/Fixer/TokensAnalyzer.php @@ -186,7 +186,7 @@ public function getNextSemiColon($index) public function getReturnedType($index) { if (false === $this->tokens[$index]->isGivenKind(T_FUNCTION)) { - throw new Exception(sprintf('Expected token: T_FUNCTION Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); + throw new Exception(\sprintf('Expected token: T_FUNCTION Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); } $methodName = $this->tokens->getNextMeaningfulToken($index); @@ -317,7 +317,7 @@ public function endOfTheStatement(int $index): ?int public function getClosingParenthesis($index) { if ('(' !== $this->tokens[$index]->getContent()) { - throw new Exception(sprintf('Expected token: (. Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); + throw new Exception(\sprintf('Expected token: (. Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); } for ($i = $index + 1; $i < $this->tokens->count(); ++$i) { @@ -345,7 +345,7 @@ public function getClosingParenthesis($index) public function getClosingBracket($index) { if ('[' !== $this->tokens[$index]->getContent()) { - throw new Exception(sprintf('Expected token: [. Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); + throw new Exception(\sprintf('Expected token: [. Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); } for ($i = $index + 1; $i < $this->tokens->count(); ++$i) { @@ -373,7 +373,7 @@ public function getClosingBracket($index) public function getClosingCurlyBracket($index) { if ('{' !== $this->tokens[$index]->getContent()) { - throw new Exception(sprintf('Expected token: {. Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); + throw new Exception(\sprintf('Expected token: {. Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); } for ($i = $index + 1; $i < $this->tokens->count(); ++$i) { @@ -401,7 +401,7 @@ public function getClosingCurlyBracket($index) public function getClosingAttribute($index) { if (false === $this->tokens[$index]->isGivenKind(T_ATTRIBUTE)) { - throw new Exception(sprintf('Expected token: T_ATTRIBUTE Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); + throw new Exception(\sprintf('Expected token: T_ATTRIBUTE Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); } for ($i = $index + 1; $i < $this->tokens->count(); ++$i) { diff --git a/tests/Orchestra.php b/tests/Orchestra.php index 0501f4a..154ee38 100644 --- a/tests/Orchestra.php +++ b/tests/Orchestra.php @@ -5,10 +5,13 @@ namespace tests; use PedroTroller\CS\Fixer\ClassNotation\OrderedWithGetterAndSetterFirstFixer; +use PedroTroller\CS\Fixer\CodingStyle\LineBreakBetweenMethodArgumentsFixer; use PedroTroller\CS\Fixer\DoctrineMigrationsFixer; +use PhpCsFixer\Fixer\Basic\BracesFixer; use PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer; use PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer; use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer; use PhpCsFixer\Fixer\Import\SingleLineAfterImportsFixer; use PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer; use PhpCsFixer\Fixer\Whitespace\NoExtraBlankLinesFixer; @@ -41,6 +44,11 @@ public static function run(): void ->before(new NoWhitespaceInBlankLineFixer()) ; + self::assert(new LineBreakBetweenMethodArgumentsFixer()) + ->after(new BracesFixer()) + ->after(new MethodArgumentSpaceFixer()) + ; + echo "\n"; } @@ -57,7 +65,7 @@ public static function assert(FixerInterface $fixer) */ public function before(FixerInterface $other) { - echo sprintf("\nRun %s before %s\n", $this->fixer->getName(), $other->getName()); + echo \sprintf("\nRun %s before %s\n", $this->fixer->getName(), $other->getName()); Assert::greaterThan( $this->fixer->getPriority(), @@ -72,7 +80,7 @@ public function before(FixerInterface $other) */ public function after(FixerInterface $other) { - echo sprintf("\nRun %s after %s\n", $this->fixer->getName(), $other->getName()); + echo \sprintf("\nRun %s after %s\n", $this->fixer->getName(), $other->getName()); Assert::lessThan( $this->fixer->getPriority(), diff --git a/tests/Runner.php b/tests/Runner.php index 66f70ff..39b5e26 100644 --- a/tests/Runner.php +++ b/tests/Runner.php @@ -18,8 +18,8 @@ public static function run(): void $deprecations = []; set_error_handler( - function ($type, $message, $file, $line) use (&$deprecations): void { - $deprecations[$message][] = sprintf('%s at line %d', $file, $line); + static function ($type, $message, $file, $line) use (&$deprecations): void { + $deprecations[$message][] = \sprintf('%s at line %d', $file, $line); $deprecations[$message] = array_unique($deprecations[$message]); sort($deprecations[$message]); @@ -35,12 +35,12 @@ function ($type, $message, $file, $line) use (&$deprecations): void { if (false === empty($deprecations)) { ksort($deprecations); - $message = sprintf( + $message = \sprintf( "Deprecations : \n\n%s", implode( "\n\n", array_map( - fn ($message, array $files) => sprintf("%s\n%s", $message, implode("\n", $files)), + static fn ($message, array $files) => \sprintf("%s\n%s", $message, implode("\n", $files)), array_keys($deprecations), $deprecations ) @@ -53,7 +53,7 @@ function ($type, $message, $file, $line) use (&$deprecations): void { private static function runUseCases(): void { - $directory = sprintf('%s/UseCase', __DIR__); + $directory = \sprintf('%s/UseCase', __DIR__); $finder = new Finder(); $finder @@ -100,7 +100,7 @@ private static function runUseCases(): void private static function runAnalyzerIntegrations(): void { - $directory = sprintf('%s/TokensAnalyzerIntegration', __DIR__); + $directory = \sprintf('%s/TokensAnalyzerIntegration', __DIR__); $finder = new Finder(); $finder diff --git a/tests/TokensAnalyzerIntegration.php b/tests/TokensAnalyzerIntegration.php index 0423e15..f36c8ba 100644 --- a/tests/TokensAnalyzerIntegration.php +++ b/tests/TokensAnalyzerIntegration.php @@ -53,7 +53,7 @@ protected function tokensContaining(Tokens $tokens, $content) } if (empty($indexes)) { - throw new Exception(sprintf('There is no token containing %s.', $content)); + throw new Exception(\sprintf('There is no token containing %s.', $content)); } return $indexes; diff --git a/tests/TokensAnalyzerIntegration/MethodArguments.php b/tests/TokensAnalyzerIntegration/MethodArguments.php index d379637..872a4a4 100644 --- a/tests/TokensAnalyzerIntegration/MethodArguments.php +++ b/tests/TokensAnalyzerIntegration/MethodArguments.php @@ -49,7 +49,7 @@ public function assertions(TokensAnalyzer $analyzer, Tokens $tokens): void { $methods = array_filter( $analyzer->getClassyElements(), - fn ($element) => 'method' === $element['type'] + static fn ($element) => 'method' === $element['type'] ); Assert::count($methods, 3); @@ -67,7 +67,7 @@ public function assertions(TokensAnalyzer $analyzer, Tokens $tokens): void $arguments, [ ($theFunction + 5) => [ - 'type' => 'Domain\\Model\\User', + 'type' => 'Domain\Model\User', 'name' => '$user', 'nullable' => false, 'asDefault' => false, diff --git a/tests/UseCase/LineBreakBetweenMethods/Regression/Case1.php b/tests/UseCase/LineBreakBetweenMethods/Regression/Case1.php index 33d64fd..ec4f5fd 100644 --- a/tests/UseCase/LineBreakBetweenMethods/Regression/Case1.php +++ b/tests/UseCase/LineBreakBetweenMethods/Regression/Case1.php @@ -23,12 +23,12 @@ public function getFixers(): iterable public function getRawScript(): string { - return file_get_contents(sprintf('%s/Case1/CamelizeNamingStrategy.php.text', __DIR__)); + return file_get_contents(\sprintf('%s/Case1/CamelizeNamingStrategy.php.text', __DIR__)); } public function getExpectation(): string { - return file_get_contents(sprintf('%s/Case1/CamelizeNamingStrategy.php.text', __DIR__)); + return file_get_contents(\sprintf('%s/Case1/CamelizeNamingStrategy.php.text', __DIR__)); } public function getMinSupportedPhpVersion(): int diff --git a/tests/UseCase/Phpspec/Regression/Case1.php b/tests/UseCase/Phpspec/Regression/Case1.php index 946586a..bfeb45d 100644 --- a/tests/UseCase/Phpspec/Regression/Case1.php +++ b/tests/UseCase/Phpspec/Regression/Case1.php @@ -22,12 +22,12 @@ public function getFixers(): iterable public function getRawScript(): string { - return file_get_contents(sprintf('%s/Case1/file.php.txt', __DIR__)); + return file_get_contents(\sprintf('%s/Case1/file.php.txt', __DIR__)); } public function getExpectation(): string { - return file_get_contents(sprintf('%s/Case1/file.php.txt', __DIR__)); + return file_get_contents(\sprintf('%s/Case1/file.php.txt', __DIR__)); } public function getMinSupportedPhpVersion(): int diff --git a/tests/UseCase/Phpspec/Regression/Case2.php b/tests/UseCase/Phpspec/Regression/Case2.php index 782c697..5a03634 100644 --- a/tests/UseCase/Phpspec/Regression/Case2.php +++ b/tests/UseCase/Phpspec/Regression/Case2.php @@ -16,12 +16,12 @@ public function getFixers(): iterable public function getRawScript(): string { - return file_get_contents(sprintf('%s/Case2/file.php.txt', __DIR__)); + return file_get_contents(\sprintf('%s/Case2/file.php.txt', __DIR__)); } public function getExpectation(): string { - return file_get_contents(sprintf('%s/Case2/file.php.txt', __DIR__)); + return file_get_contents(\sprintf('%s/Case2/file.php.txt', __DIR__)); } public function getMinSupportedPhpVersion(): int