diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b7adc43..9ba5ec12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # CHANGELOG for PHP CS Fixer: custom fixers ## v3.25.0 +- Add NoUselessWriteVisibilityFixer - ReadonlyPromotedPropertiesFixer - support asymmetric visibility ## v3.24.0 diff --git a/README.md b/README.md index ef13ccad..399ada69 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Latest stable version](https://img.shields.io/packagist/v/kubawerlos/php-cs-fixer-custom-fixers.svg?label=current%20version)](https://packagist.org/packages/kubawerlos/php-cs-fixer-custom-fixers) [![PHP version](https://img.shields.io/packagist/php-v/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://php.net) [![License](https://img.shields.io/github/license/kubawerlos/php-cs-fixer-custom-fixers.svg)](LICENSE) -![Tests](https://img.shields.io/badge/tests-3607-brightgreen.svg) +![Tests](https://img.shields.io/badge/tests-3632-brightgreen.svg) [![Downloads](https://img.shields.io/packagist/dt/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://packagist.org/packages/kubawerlos/php-cs-fixer-custom-fixers) [![CI status](https://github.com/kubawerlos/php-cs-fixer-custom-fixers/actions/workflows/ci.yaml/badge.svg)](https://github.com/kubawerlos/php-cs-fixer-custom-fixers/actions/workflows/ci.yaml) @@ -399,6 +399,19 @@ Functions `strlen` and `mb_strlen` must not be compared to 0. +$isNotEmpty = $string !== ''; ``` +#### NoUselessWriteVisibilityFixer +There must be no useless write visibility. +```diff + > */ + private array $predecessorKindMap; + + public function __construct() + { + if (\defined('T_PUBLIC_SET')) { + $this->predecessorKindMap = [ + \T_PUBLIC_SET => [\T_PUBLIC, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC], + \T_PROTECTED_SET => [\T_PROTECTED, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED], + \T_PRIVATE_SET => [\T_PRIVATE, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE], + ]; + } + } + + public function getDefinition(): FixerDefinitionInterface + { + return new FixerDefinition( + 'There must be no useless write visibility.', + [new CodeSample( + <<<'PHP' + isAnyTokenKindsFound(\array_keys($this->predecessorKindMap)); + } + + public function isRisky(): bool + { + return false; + } + + public function fix(\SplFileInfo $file, Tokens $tokens): void + { + foreach ($tokens->findGivenKind(\array_keys($this->predecessorKindMap)) as $kind => $elements) { + foreach (\array_keys($elements) as $index) { + $this->fixVisibility($tokens, $index, $kind, $kind === \T_PUBLIC_SET); + } + } + } + + private function fixVisibility(Tokens $tokens, int $index, int $kind, bool $makePublicIfNone): void + { + $prevIndex = $tokens->getPrevMeaningfulToken($index); + \assert(\is_int($prevIndex)); + if ($tokens[$prevIndex]->isGivenKind(\T_ABSTRACT)) { + $prevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + \assert(\is_int($prevIndex)); + } + + if (!$tokens[$prevIndex]->isGivenKind($this->predecessorKindMap[$kind])) { + if ($makePublicIfNone) { + $prevDeciderIndex = $tokens->getPrevTokenOfKind($index, ['(', ';', '{']); + \assert(\is_int($prevDeciderIndex)); + $kind = $tokens[$prevDeciderIndex]->equals('(') ? CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC : \T_PUBLIC; + $tokens[$index] = new Token([$kind, 'public']); + } + + return; + } + + $tokens->clearAt($index); + + if ($tokens[$index + 1]->isWhitespace()) { + $tokens->clearAt($index + 1); + } + } +} diff --git a/tests/Fixer/NoUselessWriteVisibilityFixerTest.php b/tests/Fixer/NoUselessWriteVisibilityFixerTest.php new file mode 100644 index 00000000..4464ef31 --- /dev/null +++ b/tests/Fixer/NoUselessWriteVisibilityFixerTest.php @@ -0,0 +1,127 @@ += 8.4 + */ +final class NoUselessWriteVisibilityFixerTest extends AbstractFixerTestCase +{ + public function testIsRisky(): void + { + self::assertRiskiness(false); + } + + /** + * @dataProvider provideFixCases + */ + public function testFix(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + /** + * @return iterable + */ + public static function provideFixCases(): iterable + { + yield 'class properties' => [ + <<<'PHP' + [ + <<<'PHP' + [ + <<<'PHP' + [ + <<<'PHP' +