Skip to content

Commit 3d0a56a

Browse files
committed
Add NoUselessWriteVisibilityFixer
1 parent 79b9d56 commit 3d0a56a

File tree

4 files changed

+194
-1
lines changed

4 files changed

+194
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# CHANGELOG for PHP CS Fixer: custom fixers
22

33
## v3.25.0
4+
- Add NoUselessWriteVisibilityFixer
45
- ReadonlyPromotedPropertiesFixer - support asymmetric visibility
56

67
## v3.24.0

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![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)
66
[![PHP version](https://img.shields.io/packagist/php-v/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://php.net)
77
[![License](https://img.shields.io/github/license/kubawerlos/php-cs-fixer-custom-fixers.svg)](LICENSE)
8-
![Tests](https://img.shields.io/badge/tests-3613-brightgreen.svg)
8+
![Tests](https://img.shields.io/badge/tests-3635-brightgreen.svg)
99
[![Downloads](https://img.shields.io/packagist/dt/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://packagist.org/packages/kubawerlos/php-cs-fixer-custom-fixers)
1010

1111
[![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.
399399
+$isNotEmpty = $string !== '';
400400
```
401401

402+
#### NoUselessWriteVisibilityFixer
403+
There must be no useless write visibility.
404+
```diff
405+
<?php class Foo {
406+
- public public(set) $x;
407+
- public(set) $y;
408+
- protected protected(set) $z;
409+
+ public $x;
410+
+ public(set)$y;
411+
+ protected $z;
412+
}
413+
```
414+
402415
#### NumericLiteralSeparatorFixer
403416
Numeric literals must have configured separators.
404417
DEPRECATED: use `numeric_literal_separator` instead.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of PHP CS Fixer: custom fixers.
5+
*
6+
* (c) 2018 Kuba Werłos
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace PhpCsFixerCustomFixers\Fixer;
13+
14+
use PhpCsFixer\FixerDefinition\CodeSample;
15+
use PhpCsFixer\FixerDefinition\FixerDefinition;
16+
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
17+
use PhpCsFixer\Tokenizer\CT;
18+
use PhpCsFixer\Tokenizer\Token;
19+
use PhpCsFixer\Tokenizer\Tokens;
20+
21+
final class NoUselessWriteVisibilityFixer extends AbstractFixer
22+
{
23+
private const PREDECESSOR_KIND_MAP = [
24+
\T_PUBLIC_SET => [\T_PUBLIC, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC],
25+
\T_PROTECTED_SET => [\T_PROTECTED, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED],
26+
\T_PRIVATE_SET => [\T_PRIVATE, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE],
27+
];
28+
29+
public function getDefinition(): FixerDefinitionInterface
30+
{
31+
return new FixerDefinition(
32+
'There must be no useless write visibility.',
33+
[new CodeSample(
34+
<<<'PHP'
35+
<?php class Foo {
36+
public public(set) $x;
37+
public(set) $y;
38+
protected protected(set) $z;
39+
}
40+
41+
PHP,
42+
)],
43+
);
44+
}
45+
46+
public function getPriority(): int
47+
{
48+
return 0;
49+
}
50+
51+
public function isCandidate(Tokens $tokens): bool
52+
{
53+
return \defined('T_PUBLIC_SET') && $tokens->isAnyTokenKindsFound(\array_keys(self::PREDECESSOR_KIND_MAP));
54+
}
55+
56+
public function isRisky(): bool
57+
{
58+
return false;
59+
}
60+
61+
public function fix(\SplFileInfo $file, Tokens $tokens): void
62+
{
63+
foreach ($tokens->findGivenKind(\array_keys(self::PREDECESSOR_KIND_MAP)) as $kind => $elements) {
64+
foreach (\array_keys($elements) as $index) {
65+
$this->fixVisibility($tokens, $index, $kind, $kind === T_PUBLIC_SET);
66+
}
67+
}
68+
}
69+
70+
private static function fixVisibility(Tokens $tokens, int $index, int $kind, bool $makePublicIfNone): void
71+
{
72+
$prevIndex = $tokens->getPrevMeaningfulToken($index);
73+
74+
if (!$tokens[$prevIndex]->isGivenKind(self::PREDECESSOR_KIND_MAP[$kind])) {
75+
if ($makePublicIfNone) {
76+
$tokens[$index] = new Token([T_PUBLIC, 'public']);
77+
}
78+
return;
79+
}
80+
81+
$tokens->clearAt($index);
82+
83+
if ($tokens[$index + 1]->isWhitespace()) {
84+
$tokens->clearAt($index + 1);
85+
}
86+
}
87+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of PHP CS Fixer: custom fixers.
5+
*
6+
* (c) 2018 Kuba Werłos
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace Tests\Fixer;
13+
14+
/**
15+
* @internal
16+
*
17+
* @covers \PhpCsFixerCustomFixers\Fixer\NoUselessWriteVisibilityFixer
18+
*/
19+
final class NoUselessWriteVisibilityFixerTest extends AbstractFixerTestCase
20+
{
21+
public function testIsRisky(): void
22+
{
23+
self::assertRiskiness(false);
24+
}
25+
26+
/**
27+
* @requires PHP >= 8.4
28+
*
29+
* @dataProvider provideFixCases
30+
*/
31+
public function testFix(string $expected, ?string $input = null): void
32+
{
33+
$this->doTest($expected, $input);
34+
}
35+
36+
/**
37+
* @return iterable<array{0: string, 1?: string}>
38+
*/
39+
public static function provideFixCases(): iterable
40+
{
41+
yield [
42+
<<<'PHP'
43+
<?php class Foo {
44+
public $x;
45+
protected $z;
46+
private $z;
47+
}
48+
PHP,
49+
<<<'PHP'
50+
<?php class Foo {
51+
public public(set) $x;
52+
protected protected(set) $z;
53+
private private(set) $z;
54+
}
55+
PHP,
56+
];
57+
58+
yield [
59+
<<<'PHP'
60+
<?php class Foo {
61+
public $x;
62+
}
63+
PHP,
64+
<<<'PHP'
65+
<?php class Foo {
66+
public(set) $x;
67+
}
68+
PHP,
69+
];
70+
71+
yield [
72+
<<<'PHP'
73+
<?php class Foo {
74+
public function __construct(
75+
public $x,
76+
protected $z,
77+
private $z,
78+
) {}
79+
}
80+
PHP,
81+
<<<'PHP'
82+
<?php class Foo {
83+
public function __construct(
84+
public public(set) $x,
85+
protected protected(set) $z,
86+
private private(set) $z,
87+
) {}
88+
}
89+
PHP,
90+
];
91+
}
92+
}

0 commit comments

Comments
 (0)