Skip to content

Commit 4698435

Browse files
committed
SlevomatCodingStandard.Classes.EnumCaseSpacing: New sniff
1 parent a5710b2 commit 4698435

File tree

10 files changed

+283
-6
lines changed

10 files changed

+283
-6
lines changed

SlevomatCodingStandard/Sniffs/Classes/AbstractPropertyAndConstantSpacing.php renamed to SlevomatCodingStandard/Sniffs/Classes/AbstractPropertyConstantAndEnumCaseSpacing.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use const T_COMMENT;
1616
use const T_CONST;
1717
use const T_DOC_COMMENT_OPEN_TAG;
18+
use const T_ENUM_CASE;
1819
use const T_FUNCTION;
1920
use const T_PRIVATE;
2021
use const T_PROTECTED;
@@ -29,7 +30,7 @@
2930
/**
3031
* @internal
3132
*/
32-
abstract class AbstractPropertyAndConstantSpacing implements Sniff
33+
abstract class AbstractPropertyConstantAndEnumCaseSpacing implements Sniff
3334
{
3435

3536
/** @var int */
@@ -69,7 +70,11 @@ public function process(File $phpcsFile, $pointer): int
6970
$firstOnLinePointer = TokenHelper::findFirstTokenOnNextLine($phpcsFile, $semicolonPointer);
7071
assert($firstOnLinePointer !== null);
7172

72-
$nextFunctionPointer = TokenHelper::findNext($phpcsFile, [T_FUNCTION, T_CONST, T_VARIABLE, T_USE], $firstOnLinePointer + 1);
73+
$nextFunctionPointer = TokenHelper::findNext(
74+
$phpcsFile,
75+
[T_FUNCTION, T_ENUM_CASE, T_CONST, T_VARIABLE, T_USE],
76+
$firstOnLinePointer + 1
77+
);
7378
if (
7479
$nextFunctionPointer === null
7580
|| $tokens[$nextFunctionPointer]['code'] === T_FUNCTION
@@ -78,7 +83,7 @@ public function process(File $phpcsFile, $pointer): int
7883
return $nextFunctionPointer ?? $firstOnLinePointer;
7984
}
8085

81-
$types = [T_COMMENT, T_DOC_COMMENT_OPEN_TAG, T_ATTRIBUTE, T_CONST, T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY, T_STATIC, T_USE];
86+
$types = [T_COMMENT, T_DOC_COMMENT_OPEN_TAG, T_ATTRIBUTE, T_ENUM_CASE, T_CONST, T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY, T_STATIC, T_USE];
8287
$nextPointer = TokenHelper::findNext($phpcsFile, $types, $firstOnLinePointer + 1, $tokens[$classPointer]['scope_closer']);
8388

8489
if (!$this->isNextMemberValid($phpcsFile, $nextPointer)) {

SlevomatCodingStandard/Sniffs/Classes/ConstantSpacingSniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use const T_USE;
1919
use const T_VARIABLE;
2020

21-
class ConstantSpacingSniff extends AbstractPropertyAndConstantSpacing
21+
class ConstantSpacingSniff extends AbstractPropertyConstantAndEnumCaseSpacing
2222
{
2323

2424
public const CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_CONSTANT = 'IncorrectCountOfBlankLinesAfterConstant';
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace SlevomatCodingStandard\Sniffs\Classes;
4+
5+
use PHP_CodeSniffer\Files\File;
6+
use SlevomatCodingStandard\Helpers\TokenHelper;
7+
use function sprintf;
8+
use const T_CONST;
9+
use const T_ENUM_CASE;
10+
use const T_FUNCTION;
11+
use const T_USE;
12+
use const T_VARIABLE;
13+
14+
class EnumCaseSpacingSniff extends AbstractPropertyConstantAndEnumCaseSpacing
15+
{
16+
17+
public const CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_ENUM_CASE = 'IncorrectCountOfBlankLinesAfterEnumCase';
18+
19+
/**
20+
* @return array<int, (int|string)>
21+
*/
22+
public function register(): array
23+
{
24+
return [T_ENUM_CASE];
25+
}
26+
27+
protected function isNextMemberValid(File $phpcsFile, int $pointer): bool
28+
{
29+
$tokens = $phpcsFile->getTokens();
30+
31+
if ($tokens[$pointer]['code'] === T_ENUM_CASE) {
32+
return true;
33+
}
34+
35+
$nextPointer = TokenHelper::findNext($phpcsFile, [T_FUNCTION, T_CONST, T_VARIABLE, T_USE, T_ENUM_CASE], $pointer + 1);
36+
37+
return $tokens[$nextPointer]['code'] === T_ENUM_CASE;
38+
}
39+
40+
protected function addError(File $phpcsFile, int $pointer, int $minExpectedLines, int $maxExpectedLines, int $found): bool
41+
{
42+
if ($minExpectedLines === $maxExpectedLines) {
43+
$errorMessage = $minExpectedLines === 1
44+
? 'Expected 1 blank line after enum case, found %3$d.'
45+
: 'Expected %2$d blank lines after enum case, found %3$d.';
46+
} else {
47+
$errorMessage = 'Expected %1$d to %2$d blank lines after enum case, found %3$d.';
48+
}
49+
$error = sprintf($errorMessage, $minExpectedLines, $maxExpectedLines, $found);
50+
51+
return $phpcsFile->addFixableError($error, $pointer, self::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_ENUM_CASE);
52+
}
53+
54+
}

SlevomatCodingStandard/Sniffs/Classes/PropertySpacingSniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
use const T_VAR;
2020
use const T_VARIABLE;
2121

22-
class PropertySpacingSniff extends AbstractPropertyAndConstantSpacing
22+
class PropertySpacingSniff extends AbstractPropertyConstantAndEnumCaseSpacing
2323
{
2424

2525
public const CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_PROPERTY = 'IncorrectCountOfBlankLinesAfterProperty';

build/phpcs.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@
239239
</properties>
240240
</rule>
241241
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming">
242-
<exclude-pattern>SlevomatCodingStandard/Sniffs/Classes/AbstractPropertyAndConstantSpacing.php</exclude-pattern>
242+
<exclude-pattern>SlevomatCodingStandard/Sniffs/Classes/AbstractPropertyConstantAndEnumCaseSpacing.php</exclude-pattern>
243243
<exclude-pattern>SlevomatCodingStandard/Sniffs/Classes/AbstractMethodSignature.php</exclude-pattern>
244244
<exclude-pattern>SlevomatCodingStandard/Sniffs/Commenting/AbstractRequireOneLineDocComment.php</exclude-pattern>
245245
<exclude-pattern>SlevomatCodingStandard/Sniffs/ControlStructures/AbstractControlStructureSpacing.php</exclude-pattern>

doc/classes.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,17 @@ Sniff provides the following settings:
122122
* `linesCountAfterOpeningBrace`: allows to configure the number of lines after opening brace.
123123
* `linesCountBeforeClosingBrace`: allows to configure the number of lines before closing brace.
124124

125+
#### SlevomatCodingStandard.Classes.EnumCaseSpacing 🔧
126+
127+
Checks that there is a certain number of blank lines between enum cases.
128+
129+
Sniff provides the following settings:
130+
131+
* `minLinesCountBeforeWithComment`: minimum number of lines before enum case with a documentation comment or attribute
132+
* `maxLinesCountBeforeWithComment`: maximum number of lines before enum case with a documentation comment or attribute
133+
* `minLinesCountBeforeWithoutComment`: minimum number of lines before enum case without a documentation comment or attribute
134+
* `maxLinesCountBeforeWithoutComment`: maximum number of lines before enum case without a documentation comment or attribute
135+
125136
#### SlevomatCodingStandard.Classes.ForbiddenPublicProperty
126137

127138
Disallows using public properties.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace SlevomatCodingStandard\Sniffs\Classes;
4+
5+
use SlevomatCodingStandard\Sniffs\TestCase;
6+
7+
class EnumCaseSpacingSniffTest extends TestCase
8+
{
9+
10+
public function testNoErrors(): void
11+
{
12+
$report = self::checkFile(__DIR__ . '/data/enumCaseSpacingNoErrors.php');
13+
self::assertNoSniffErrorInFile($report);
14+
}
15+
16+
public function testErrors(): void
17+
{
18+
$report = self::checkFile(__DIR__ . '/data/enumCaseSpacingErrors.php');
19+
20+
self::assertSame(4, $report->getErrorCount());
21+
22+
self::assertSniffError($report, 5, EnumCaseSpacingSniff::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_ENUM_CASE);
23+
self::assertSniffError($report, 24, EnumCaseSpacingSniff::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_ENUM_CASE);
24+
self::assertSniffError($report, 28, EnumCaseSpacingSniff::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_ENUM_CASE);
25+
self::assertSniffError($report, 55, EnumCaseSpacingSniff::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_ENUM_CASE);
26+
27+
self::assertAllFixedInFile($report);
28+
}
29+
30+
public function testErrorsWithModifiedLinesCount(): void
31+
{
32+
$report = self::checkFile(__DIR__ . '/data/enumCaseSpacingErrors.php', [
33+
'minLinesCountBeforeWithComment' => 2,
34+
'maxLinesCountBeforeWithComment' => 2,
35+
'maxLinesCountBeforeWithoutComment' => 2,
36+
]);
37+
38+
self::assertSame(2, $report->getErrorCount());
39+
40+
self::assertSniffError($report, 5, EnumCaseSpacingSniff::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_ENUM_CASE);
41+
self::assertSniffError($report, 28, EnumCaseSpacingSniff::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_ENUM_CASE);
42+
}
43+
44+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php // lint >= 8.2
2+
3+
enum Foo: string {
4+
/** @var string */
5+
case BAR = 'bar';
6+
7+
/** @var string */
8+
case FOO = 'foo';
9+
/**
10+
* whatever
11+
*/
12+
public static function wow()
13+
{
14+
}
15+
/**
16+
* who cares
17+
*/
18+
private function such()
19+
{
20+
}
21+
}
22+
23+
enum Bar: string {
24+
/** @var string */
25+
case BAR = 'bar';
26+
27+
/** @var string */
28+
case FOO = 'foo';
29+
30+
case WHATEVER = 'whatever';
31+
32+
33+
final const FINAL_CONSTANT = 'final';
34+
35+
36+
/**
37+
* whatever
38+
*/
39+
public static function wow()
40+
{
41+
}
42+
/**
43+
* who cares
44+
*/
45+
private function such()
46+
{
47+
}
48+
}
49+
50+
enum Boo
51+
{
52+
53+
case BOO;
54+
55+
case BOOO;
56+
57+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php // lint >= 8.2
2+
3+
enum Foo: string {
4+
/** @var string */
5+
case BAR = 'bar';
6+
/** @var string */
7+
case FOO = 'foo';
8+
/**
9+
* whatever
10+
*/
11+
public static function wow()
12+
{
13+
}
14+
/**
15+
* who cares
16+
*/
17+
private function such()
18+
{
19+
}
20+
}
21+
22+
enum Bar: string {
23+
/** @var string */
24+
case BAR = 'bar';
25+
26+
27+
/** @var string */
28+
case FOO = 'foo';
29+
30+
31+
32+
case WHATEVER = 'whatever';
33+
34+
35+
final const FINAL_CONSTANT = 'final';
36+
37+
38+
/**
39+
* whatever
40+
*/
41+
public static function wow()
42+
{
43+
}
44+
/**
45+
* who cares
46+
*/
47+
private function such()
48+
{
49+
}
50+
}
51+
52+
enum Boo
53+
{
54+
55+
case BOO;
56+
57+
58+
case BOOO;
59+
60+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php // lint >= 8.1
2+
3+
enum Foo: string {
4+
case BAR = 'bar';
5+
case FOO = 'foo';
6+
7+
public static function wow()
8+
{
9+
10+
}
11+
12+
private function such()
13+
{
14+
}
15+
}
16+
17+
enum Bar: string {
18+
/** @var string */
19+
case BAR = 'bar';
20+
21+
/** @var string */
22+
case FOO = 'foo';
23+
24+
/**
25+
* whatever
26+
*/
27+
public static function wow()
28+
{
29+
}
30+
31+
/**
32+
* who cares
33+
*/
34+
private function such()
35+
{
36+
}
37+
}
38+
39+
enum TestClass
40+
{
41+
case FOO;
42+
43+
use TestTrait;
44+
45+
case BAR;
46+
}

0 commit comments

Comments
 (0)