Skip to content

Commit f5abbe6

Browse files
authored
Merge branch 'main' into fix_PhpdocNoSuperfluousParamFixer
2 parents ac0f849 + c3a815a commit f5abbe6

13 files changed

+702
-58
lines changed

.dev-tools/composer.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
"require": {
44
"php": "^8.4",
55
"ergebnis/composer-normalize": "^2.47",
6-
"infection/infection": "^0.30.1",
6+
"infection/infection": "^0.31.0",
77
"kubawerlos/composer-smaller-lock": "^1.1.0",
88
"kubawerlos/php-cs-fixer-config": "^5.3",
99
"mi-schi/phpmd-extension": "^4.3",
1010
"phpmd/phpmd": "^2.15",
1111
"phpstan/extension-installer": "^1.4.3",
12-
"phpstan/phpstan": "^2.1.17",
13-
"phpstan/phpstan-phpunit": "^2.0.6",
14-
"phpstan/phpstan-strict-rules": "^2.0.4",
12+
"phpstan/phpstan": "^2.1.20",
13+
"phpstan/phpstan-phpunit": "^2.0.7",
14+
"phpstan/phpstan-strict-rules": "^2.0.6",
1515
"shipmonk/composer-dependency-analyser": "^1.8.3",
16-
"shipmonk/phpstan-rules": "^4.1.4",
16+
"shipmonk/dead-code-detector": "^0.13.0",
17+
"shipmonk/phpstan-rules": "^4.1.5",
1718
"squizlabs/php_codesniffer": "^3.13.2",
1819
"tomasvotruba/type-coverage": "^2.0.2",
1920
"vimeo/psalm": "^6.13.0"

.dev-tools/composer.lock

Lines changed: 174 additions & 44 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.dev-tools/src/InfectionConfigBuilder.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ final class InfectionConfigBuilder
3131
'NotIdenticalNotEqual',
3232
'OneZeroInteger',
3333
'Plus',
34+
'ReturnRemoval',
3435
'SyntaxError',
3536
];
3637

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG for PHP CS Fixer: custom fixers
22

3+
## v3.32.0
4+
- Add FunctionParameterSeparationFixer
5+
- Update minimum PHP CS Fixer version to 3.85.0
6+
37
## v3.31.0
48
- Update minimum PHP CS Fixer version to 3.84.0
59

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,24 @@ Value from `foreach` must not be used if possible.
172172
}
173173
```
174174

175+
#### FunctionParameterSeparationFixer
176+
Function parameters, if any is having attribute or hook, must be separated by a blank line.
177+
```diff
178+
<?php
179+
class Foo {
180+
public function __construct(
181+
#[Attibute1]
182+
private string $x,
183+
+
184+
#[Attibute2]
185+
private string $y,
186+
+
187+
#[Attibute3]
188+
private string $z,
189+
) {}
190+
}
191+
```
192+
175193
#### InternalClassCasingFixer
176194
When referencing an internal class it must be written using the correct casing.
177195
DEPRECATED: use `class_reference_name_casing` instead.
@@ -641,7 +659,7 @@ PHPDoc `list` type must be used instead of `array` without a key.
641659
```
642660

643661
#### PhpdocTypesCommaSpacesFixer
644-
PHPDoc types commas must not be preceded by a whitespace, and must be succeeded by a single whitespace.
662+
PHPDoc types commas must not be preceded by a whitespace, and must be succeeded by a single whitespace or newline.
645663
```diff
646664
-<?php /** @var array<int,string> */
647665
+<?php /** @var array<int, string> */

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"php": "^7.4 || ^8.0",
1414
"ext-filter": "*",
1515
"ext-tokenizer": "*",
16-
"friendsofphp/php-cs-fixer": "^3.84"
16+
"friendsofphp/php-cs-fixer": "^3.85"
1717
},
1818
"require-dev": {
1919
"phpunit/phpunit": "^9.6.22 || 10.5.45 || ^11.5.7"

src/Fixer/AbstractTypesFixer.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ final public function fix(\SplFileInfo $file, Tokens $tokens): void
4444
continue;
4545
}
4646

47-
$typeExpression = $annotation->getTypeExpression();
48-
if ($typeExpression === null) {
47+
$types = $annotation->getTypes();
48+
if ($types === []) {
4949
continue;
5050
}
5151

52-
$type = $typeExpression->toString();
53-
$type = $this->fixType($type);
54-
$annotation->setTypes([$type]);
52+
$types = \array_map(fn (string $x): string => $this->fixType($x), $types);
53+
54+
$annotation->setTypes($types);
5555
}
5656

5757
$newContent = $docBlock->getContent();
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
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\FixerDefinition;
15+
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
16+
use PhpCsFixer\FixerDefinition\VersionSpecification;
17+
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
18+
use PhpCsFixer\Preg;
19+
use PhpCsFixer\Tokenizer\CT;
20+
use PhpCsFixer\Tokenizer\FCT;
21+
use PhpCsFixer\Tokenizer\Token;
22+
use PhpCsFixer\Tokenizer\Tokens;
23+
24+
/**
25+
* @no-named-arguments
26+
*/
27+
final class FunctionParameterSeparationFixer extends AbstractFixer
28+
{
29+
public function getDefinition(): FixerDefinitionInterface
30+
{
31+
return new FixerDefinition(
32+
'Function parameters, if any is having attribute or hook, must be separated by a blank line.',
33+
[
34+
new VersionSpecificCodeSample(
35+
<<<'PHP'
36+
<?php
37+
class Foo {
38+
public function __construct(
39+
#[Attibute1]
40+
private string $x,
41+
#[Attibute2]
42+
private string $y,
43+
#[Attibute3]
44+
private string $z,
45+
) {}
46+
}
47+
48+
PHP,
49+
new VersionSpecification(80000),
50+
),
51+
],
52+
'',
53+
);
54+
}
55+
56+
/**
57+
* Must run after MethodArgumentSpaceFixer.
58+
*/
59+
public function getPriority(): int
60+
{
61+
return 0;
62+
}
63+
64+
public function isCandidate(Tokens $tokens): bool
65+
{
66+
return $tokens->isTokenKindFound(\T_FUNCTION);
67+
}
68+
69+
public function isRisky(): bool
70+
{
71+
return false;
72+
}
73+
74+
public function fix(\SplFileInfo $file, Tokens $tokens): void
75+
{
76+
for ($index = $tokens->count() - 1; $index > 0; $index--) {
77+
if (!$tokens[$index]->isGivenKind([\T_FUNCTION])) {
78+
continue;
79+
}
80+
81+
$openParenthesisIndex = $tokens->getNextTokenOfKind($index, ['(']);
82+
\assert(\is_int($openParenthesisIndex));
83+
84+
$closeParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesisIndex);
85+
86+
if (!self::shouldBeFixed($tokens, $openParenthesisIndex, $closeParenthesisIndex)) {
87+
continue;
88+
}
89+
90+
self::fixFunction($tokens, $openParenthesisIndex, $closeParenthesisIndex);
91+
}
92+
}
93+
94+
private static function shouldBeFixed(Tokens $tokens, int $openParenthesisIndex, int $closeParenthesisIndex): bool
95+
{
96+
for ($index = $openParenthesisIndex; $index < $closeParenthesisIndex; $index++) {
97+
if ($tokens[$index]->isGivenKind([FCT::T_ATTRIBUTE, CT::T_PROPERTY_HOOK_BRACE_OPEN])) {
98+
return true;
99+
}
100+
}
101+
102+
return false;
103+
}
104+
105+
private static function fixFunction(Tokens $tokens, int $openParenthesisIndex, int $closeParenthesisIndex): void
106+
{
107+
$prevCloseParenthesisIndex = $tokens->getPrevMeaningfulToken($closeParenthesisIndex);
108+
\assert(\is_int($prevCloseParenthesisIndex));
109+
110+
for ($index = $openParenthesisIndex; $index < $prevCloseParenthesisIndex; $index++) {
111+
if ($tokens[$index]->isGivenKind(FCT::T_ATTRIBUTE)) {
112+
$index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ATTRIBUTE, $index);
113+
continue;
114+
}
115+
116+
if ($tokens[$index]->isGivenKind(CT::T_PROPERTY_HOOK_BRACE_OPEN)) {
117+
$index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PROPERTY_HOOK, $index);
118+
continue;
119+
}
120+
121+
if (!$tokens[$index]->equals(',')) {
122+
continue;
123+
}
124+
125+
if (!$tokens[$index + 1]->isGivenKind(\T_WHITESPACE) || \substr_count($tokens[$index + 1]->getContent(), "\n") !== 1) {
126+
continue;
127+
}
128+
129+
$tokens[$index + 1] = new Token([
130+
\T_WHITESPACE,
131+
Preg::replace('/(\\r\\n|\\n)(\\h+)$/', '$1$1$2', $tokens[$index + 1]->getContent(), 1),
132+
]);
133+
}
134+
}
135+
}

src/Fixer/PhpdocTypesCommaSpacesFixer.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ final class PhpdocTypesCommaSpacesFixer extends AbstractTypesFixer
2424
public function getDefinition(): FixerDefinitionInterface
2525
{
2626
return new FixerDefinition(
27-
'PHPDoc types commas must not be preceded by a whitespace, and must be succeeded by a single whitespace.',
27+
'PHPDoc types commas must not be preceded by a whitespace, and must be succeeded by a single whitespace or newline.',
2828
[new CodeSample("<?php /** @var array<int,string> */\n")],
2929
'',
3030
);
@@ -37,6 +37,6 @@ public function getPriority(): int
3737

3838
protected function fixType(string $type): string
3939
{
40-
return Preg::replace('/\\h*,\\s*/', ', ', $type);
40+
return Preg::replace('/,(?!\\R)\\s*/', ', ', Preg::replace('/\\h*,/', ',', $type));
4141
}
4242
}

0 commit comments

Comments
 (0)