From 1514f45a45ada52b6fa369f16df98f947ea090ec Mon Sep 17 00:00:00 2001 From: Anastasiia Sherekina Date: Mon, 19 Jan 2026 18:24:47 +0200 Subject: [PATCH 1/2] Update white spaces around control statement sniff. Add check spaces around "break" and "continue" control statements. --- .../Sniffs/Commenting/InheritdocSniff.php | 3 ++ .../Commenting/ProhibitedDocCommentsSniff.php | 1 + .../WhiteSpaceAroundControlStatementSniff.php | 36 ++++++++++++------- .../WhiteSpaceBeforeChainCallSniff.php | 19 ++-------- .../success.php | 16 ++++++++- .../wrong.php | 10 ++++++ ...teSpaceAroundControlStatementSniffTest.php | 8 +++++ 7 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/PhpCs/FiveLab/Sniffs/Commenting/InheritdocSniff.php b/src/PhpCs/FiveLab/Sniffs/Commenting/InheritdocSniff.php index 42f3fd7..c4b951f 100644 --- a/src/PhpCs/FiveLab/Sniffs/Commenting/InheritdocSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Commenting/InheritdocSniff.php @@ -104,6 +104,7 @@ private function assertExistDocInParents(File $phpcsFile, int $line, string $met if ($implementRef->hasMethod($methodName)) { $exist = true; + break; } @@ -116,6 +117,7 @@ private function assertExistDocInParents(File $phpcsFile, int $line, string $met if (\preg_match('/^\*\s*@method (\S+) ([^\\\(]+)\s*\(/', \trim($docCommentLine), $parts)) { if ($methodName === $parts[2]) { $exist = true; + break; } } @@ -124,6 +126,7 @@ private function assertExistDocInParents(File $phpcsFile, int $line, string $met if (\preg_match('/^\*\s*@method ([^\\\(]+)\s*\(/', \trim($docCommentLine), $parts)) { if ($methodName === $parts[1]) { $exist = true; + break; } } diff --git a/src/PhpCs/FiveLab/Sniffs/Commenting/ProhibitedDocCommentsSniff.php b/src/PhpCs/FiveLab/Sniffs/Commenting/ProhibitedDocCommentsSniff.php index d139687..387f2ef 100644 --- a/src/PhpCs/FiveLab/Sniffs/Commenting/ProhibitedDocCommentsSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Commenting/ProhibitedDocCommentsSniff.php @@ -46,6 +46,7 @@ public function process(File $phpcsFile, mixed $stackPtr): void for ($i = $stackPtr + 1; $i < $closePtr; $i++) { if ($tokens[$i]['code'] === T_DOC_COMMENT_TAG) { $hasMetaTag = true; + break; } } diff --git a/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundControlStatementSniff.php b/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundControlStatementSniff.php index 6b7f73e..01add38 100644 --- a/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundControlStatementSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundControlStatementSniff.php @@ -36,12 +36,14 @@ class WhiteSpaceAroundControlStatementSniff implements Sniff * @var array> */ private static array $ignoredTokens = [ - T_IF => [T_ELSE, T_ELSEIF, T_COLON], - T_ELSE => [T_IF, T_CLOSE_CURLY_BRACKET], - T_ELSEIF => [T_ELSEIF, T_CLOSE_CURLY_BRACKET, T_ELSE], - T_DO => [T_WHILE], - T_WHILE => [T_DO], - T_MATCH => [T_OPEN_SHORT_ARRAY, T_CLOSE_SHORT_ARRAY, T_COMMA], + T_IF => [T_ELSE, T_ELSEIF, T_COLON], + T_ELSE => [T_IF, T_CLOSE_CURLY_BRACKET], + T_ELSEIF => [T_ELSEIF, T_CLOSE_CURLY_BRACKET, T_ELSE], + T_DO => [T_WHILE], + T_WHILE => [T_DO], + T_MATCH => [T_OPEN_SHORT_ARRAY, T_CLOSE_SHORT_ARRAY, T_COMMA], + T_BREAK => [T_CLOSE_CURLY_BRACKET], + T_CONTINUE => [T_CLOSE_CURLY_BRACKET], ]; public function register(): array @@ -56,6 +58,8 @@ public function register(): array T_DO, T_SWITCH, T_MATCH, + T_BREAK, + T_CONTINUE, ]; } @@ -63,7 +67,7 @@ public function process(File $phpcsFile, mixed $stackPtr): void { $stackToken = $phpcsFile->getTokens()[$stackPtr]; - if (!\array_key_exists('scope_closer', $stackToken)) { + if (!\array_key_exists('scope_closer', $stackToken) && !\in_array($stackToken['code'], [T_BREAK, T_CONTINUE], true)) { // Active token hasn't close scope. Maybe use "else if" (or similar) construction where scope undefined. return; } @@ -91,16 +95,22 @@ public function process(File $phpcsFile, mixed $stackPtr): void } // Check blank lines after - $scopeCloserPtr = $stackToken['scope_closer']; - $nextTokenPtr = $phpcsFile->findNext(Tokens::EMPTY_TOKENS, $scopeCloserPtr + 1, null, true); + if (\array_key_exists('scope_closer', $stackToken)) { + $scopeCloserPtr = $stackToken['scope_closer']; + $nextTokenPtr = $phpcsFile->findNext(Tokens::EMPTY_TOKENS, $scopeCloserPtr + 1, null, true); + } else { + $scopeCloserPtr = $stackPtr; + $nextTokenPtr = $stackPtr + 1; + } if ($nextTokenPtr) { $nextToken = $phpcsFile->getTokens()[$nextTokenPtr]; - if ($nextToken['code'] === T_SEMICOLON && $stackToken['code'] === T_MATCH) { - // Use "match" construction. - $nextTokenPtr = $phpcsFile->findNext(Tokens::EMPTY_TOKENS, $nextTokenPtr + 1, null, true); - $nextToken = $nextTokenPtr ? $phpcsFile->getTokens()[$nextTokenPtr] : null; + if ($nextToken['code'] === T_SEMICOLON) { + if (\in_array($stackToken['code'], [T_MATCH, T_BREAK, T_CONTINUE], true)) { + $nextTokenPtr = $phpcsFile->findNext(Tokens::EMPTY_TOKENS, $nextTokenPtr + 1, null, true); + $nextToken = $nextTokenPtr ? $phpcsFile->getTokens()[$nextTokenPtr] : null; + } } if ($nextToken) { diff --git a/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceBeforeChainCallSniff.php b/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceBeforeChainCallSniff.php index 3a6b361..e789fe8 100644 --- a/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceBeforeChainCallSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceBeforeChainCallSniff.php @@ -21,7 +21,7 @@ class WhiteSpaceBeforeChainCallSniff implements Sniff { - const GAP = 4; + const int GAP = 4; public function register(): array { @@ -96,14 +96,6 @@ public function process(File $phpcsFile, mixed $stackPtr): void ); } - /** - * Calculate whitespaces before first token on line - * - * @param File $phpcsFile - * @param int $line - * - * @return int - */ private function calculateWhitespacesBeforeFirstTokenOnLine(File $phpcsFile, int $line): int { $whitespaces = 0; @@ -111,6 +103,7 @@ private function calculateWhitespacesBeforeFirstTokenOnLine(File $phpcsFile, int foreach (PhpCsUtils::getTokensOnLine($phpcsFile, $line) as $token) { if (T_WHITESPACE === $token['code']) { $whitespaces += $token['length']; + continue; } @@ -120,14 +113,6 @@ private function calculateWhitespacesBeforeFirstTokenOnLine(File $phpcsFile, int return $whitespaces; } - /** - * Get non-empty tokens on line - * - * @param File $phpcsFile - * @param int $line - * - * @return array - */ private function getNonEmptyTokensOnLine(File $phpcsFile, int $line): array { $tokens = PhpCsUtils::getTokensOnLine($phpcsFile, $line); diff --git a/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/white-space-around-control-statement/success.php b/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/white-space-around-control-statement/success.php index b3edd43..1d4cc27 100644 --- a/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/white-space-around-control-statement/success.php +++ b/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/white-space-around-control-statement/success.php @@ -100,4 +100,18 @@ if (false) { $bar = 'bar'; } -} \ No newline at end of file + + break; +} + +if ($condition) { + $bar = 'bar'; + + break; +} + +for ($i = 0; $i < 10; $i++) { + $someArray[] = $i; + + continue; +} diff --git a/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/white-space-around-control-statement/wrong.php b/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/white-space-around-control-statement/wrong.php index c2a78c4..cca1dbc 100644 --- a/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/white-space-around-control-statement/wrong.php +++ b/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/white-space-around-control-statement/wrong.php @@ -15,3 +15,13 @@ $a .= $key; } $bar = 'foo'; + +if ($a) { + $a = 'bar'; + break; +} + +foreach ($array as $key => $item) { + $a .= $key; + continue; +} diff --git a/tests/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundControlStatementSniffTest.php b/tests/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundControlStatementSniffTest.php index 55616a4..2c58b10 100644 --- a/tests/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundControlStatementSniffTest.php +++ b/tests/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundControlStatementSniffTest.php @@ -44,6 +44,14 @@ public static function provideDataSet(): array 'message' => 'Must be one blank line after close "foreach" statement.', 'source' => 'FiveLab.Formatting.WhiteSpaceAroundControlStatement.MissedLineAfter', ], + [ + 'message' => 'Must be one blank line before "break" statement.', + 'source' => 'FiveLab.Formatting.WhiteSpaceAroundControlStatement.MissedLineBefore', + ], + [ + 'message' => 'Must be one blank line before "continue" statement.', + 'source' => 'FiveLab.Formatting.WhiteSpaceAroundControlStatement.MissedLineBefore', + ], ], ]; } From e99eb6140fe4a410371be0bbab5052ce50f16be6 Mon Sep 17 00:00:00 2001 From: Anastasiia Sherekina Date: Mon, 19 Jan 2026 18:29:22 +0200 Subject: [PATCH 2/2] Update white spaces around control statement sniff. Add check spaces around "break" and "continue" control statements. --- .../Sniffs/Formatting/WhiteSpaceBeforeChainCallSniff.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceBeforeChainCallSniff.php b/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceBeforeChainCallSniff.php index e789fe8..d593d4c 100644 --- a/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceBeforeChainCallSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceBeforeChainCallSniff.php @@ -113,6 +113,14 @@ private function calculateWhitespacesBeforeFirstTokenOnLine(File $phpcsFile, int return $whitespaces; } + /** + * Get non-empty tokens on line + * + * @param File $phpcsFile + * @param int $line + * + * @return array + */ private function getNonEmptyTokensOnLine(File $phpcsFile, int $line): array { $tokens = PhpCsUtils::getTokensOnLine($phpcsFile, $line);