Skip to content

Commit 82d25d9

Browse files
committed
SlevomatCodingStandard.Functions.RequireTrailingCommaInClosureUse: New sniff
1 parent 9c16fd1 commit 82d25d9

File tree

6 files changed

+170
-2
lines changed

6 files changed

+170
-2
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,16 @@ This sniff provides the following setting:
821821

822822
This sniff disallows trailing commas in multi-line `use` of closure declaration.
823823

824+
#### SlevomatCodingStandard.Functions.RequireTrailingCommaInClosureUse 🔧
825+
826+
Commas after the last inherited variable in multi-line `use` of closure declaration make adding a new variable easier and result in a cleaner versioning diff.
827+
828+
This sniff enforces trailing commas in multi-line declarations.
829+
830+
This sniff provides the following setting:
831+
832+
* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 8.0 or higher.
833+
824834
#### SlevomatCodingStandard.Functions.DisallowTrailingCommaInDeclaration 🔧
825835

826836
This sniff disallows trailing commas in multi-line declarations.
@@ -835,8 +845,6 @@ This sniff provides the following setting:
835845

836846
* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 8.0 or higher.
837847

838-
#### SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses 🔧
839-
840848
Checks whether uses at the top of a file are alphabetically sorted. Follows natural sorting and takes edge cases with special symbols into consideration. The following code snippet is an example of correctly sorted uses:
841849

842850
```php
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace SlevomatCodingStandard\Sniffs\Functions;
4+
5+
use PHP_CodeSniffer\Files\File;
6+
use PHP_CodeSniffer\Sniffs\Sniff;
7+
use SlevomatCodingStandard\Helpers\SniffSettingsHelper;
8+
use SlevomatCodingStandard\Helpers\TokenHelper;
9+
use const T_CLOSURE;
10+
use const T_COMMA;
11+
use const T_USE;
12+
use const T_WHITESPACE;
13+
14+
class RequireTrailingCommaInClosureUseSniff implements Sniff
15+
{
16+
17+
public const CODE_MISSING_TRAILING_COMMA = 'MissingTrailingComma';
18+
19+
/** @var bool|null */
20+
public $enable = null;
21+
22+
/**
23+
* @return array<int, (int|string)>
24+
*/
25+
public function register(): array
26+
{
27+
return [T_CLOSURE];
28+
}
29+
30+
/**
31+
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
32+
* @param int $functionPointer
33+
*/
34+
public function process(File $phpcsFile, $functionPointer): void
35+
{
36+
$this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 80000);
37+
38+
if (!$this->enable) {
39+
return;
40+
}
41+
42+
$tokens = $phpcsFile->getTokens();
43+
44+
$parenthesisCloserPointer = $tokens[$functionPointer]['parenthesis_closer'];
45+
46+
$usePointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisCloserPointer + 1);
47+
48+
if ($tokens[$usePointer]['code'] !== T_USE) {
49+
return;
50+
}
51+
52+
$useParenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1);
53+
$useParenthesisCloserPointer = $tokens[$useParenthesisOpenerPointer]['parenthesis_closer'];
54+
55+
if ($tokens[$useParenthesisOpenerPointer]['line'] === $tokens[$useParenthesisCloserPointer]['line']) {
56+
return;
57+
}
58+
59+
$pointerBeforeUseParenthesisCloser = TokenHelper::findPreviousExcluding(
60+
$phpcsFile,
61+
T_WHITESPACE,
62+
$useParenthesisCloserPointer - 1,
63+
$useParenthesisOpenerPointer
64+
);
65+
66+
if ($tokens[$pointerBeforeUseParenthesisCloser]['code'] === T_COMMA) {
67+
return;
68+
}
69+
70+
$fix = $phpcsFile->addFixableError(
71+
'Multi-line "use" of closure declaration must have a trailing comma after the last inherited variable.',
72+
$pointerBeforeUseParenthesisCloser,
73+
self::CODE_MISSING_TRAILING_COMMA
74+
);
75+
76+
if (!$fix) {
77+
return;
78+
}
79+
80+
$phpcsFile->fixer->beginChangeset();
81+
$phpcsFile->fixer->addContent($pointerBeforeUseParenthesisCloser, ',');
82+
$phpcsFile->fixer->endChangeset();
83+
}
84+
85+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace SlevomatCodingStandard\Sniffs\Functions;
4+
5+
use SlevomatCodingStandard\Sniffs\TestCase;
6+
7+
class RequireTrailingCommaInClosureUseSniffTest extends TestCase
8+
{
9+
10+
public function testNoErrors(): void
11+
{
12+
$report = self::checkFile(__DIR__ . '/data/requireTrailingCommaInClosureUseNoErrors.php', [
13+
'enable' => true,
14+
]);
15+
self::assertNoSniffErrorInFile($report);
16+
}
17+
18+
public function testErrors(): void
19+
{
20+
$report = self::checkFile(__DIR__ . '/data/requireTrailingCommaInClosureUseErrors.php', [
21+
'enable' => true,
22+
]);
23+
24+
self::assertSame(1, $report->getErrorCount());
25+
26+
self::assertSniffError($report, 6, RequireTrailingCommaInClosureUseSniff::CODE_MISSING_TRAILING_COMMA);
27+
28+
self::assertAllFixedInFile($report);
29+
}
30+
31+
public function testShouldNotReportIfSniffIsDisabled(): void
32+
{
33+
$report = self::checkFile(__DIR__ . '/data/requireTrailingCommaInClosureUseErrors.php', [
34+
'enable' => false,
35+
]);
36+
37+
self::assertNoSniffErrorInFile($report);
38+
}
39+
40+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php // lint >= 8.0
2+
3+
function (
4+
) use (
5+
$a,
6+
$b,
7+
) {
8+
return $a + $b;
9+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php // lint >= 8.0
2+
3+
function (
4+
) use (
5+
$a,
6+
$b
7+
) {
8+
return $a + $b;
9+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php // lint >= 8.0
2+
3+
function () {
4+
5+
};
6+
7+
function () use ($a, $b) {
8+
9+
};
10+
11+
function (
12+
) use (
13+
$a,
14+
$b,
15+
) {
16+
return $a + $b;
17+
};

0 commit comments

Comments
 (0)