Skip to content

Commit 3f8ec82

Browse files
committed
Squiz/ForLoopDeclaration: fix fixer conflict
Fix a fixer conflict within the sniff. If `$requiredSpacingAfterOpen/BeforeClose` would be set to anything but `0` and the first or the last clause of the `for()` would be empty, the sniff had a fixer conflict with itself, as the `SpacingAfterOpen/BeforeClose` error would demand whitespace, while the `SpacingBeforeFirst/AfterSecondNoThird` would try to remove it. Fixed by skipping the semicolon spacing checks when an empty first/last expression is detected and leaving the handling of those situations up to the `SpaceAfterOpen/BeforeClose` logic. This fix effectively removes the `SpacingAfterSecondNoThird` error code.
1 parent 8c59d2b commit 3f8ec82

File tree

1 file changed

+29
-26
lines changed

1 file changed

+29
-26
lines changed

src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -195,38 +195,41 @@ public function process(File $phpcsFile, $stackPtr)
195195
$humanReadableCode = ucfirst($humanReadableCount);
196196
$data = [$humanReadableCount];
197197

198-
if ($tokens[($semicolon - 1)]['code'] === T_WHITESPACE) {
199-
$error = 'Space found before %s semicolon of FOR loop';
200-
$errorCode = 'SpacingBefore'.$humanReadableCode;
201-
$fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data);
202-
if ($fix === true) {
203-
$phpcsFile->fixer->replaceToken(($semicolon - 1), '');
198+
// Only examine the space before the first semicolon if the first expression is not empty.
199+
// If it *is* empty, leave it up to the `SpacingAfterOpen` logic.
200+
$prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($semicolon - 1), $openingBracket, true);
201+
if ($semicolonCount !== 1 || $prevNonWhiteSpace !== $openingBracket) {
202+
if ($tokens[($semicolon - 1)]['code'] === T_WHITESPACE) {
203+
$error = 'Space found before %s semicolon of FOR loop';
204+
$errorCode = 'SpacingBefore'.$humanReadableCode;
205+
$fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data);
206+
if ($fix === true) {
207+
$phpcsFile->fixer->replaceToken(($semicolon - 1), '');
208+
}
204209
}
205210
}
206211

207-
if ($tokens[($semicolon + 1)]['code'] !== T_WHITESPACE
208-
&& $tokens[($semicolon + 1)]['code'] !== T_SEMICOLON
209-
&& ($semicolon + 1) !== $closingBracket
210-
) {
211-
$error = 'Expected 1 space after %s semicolon of FOR loop; 0 found';
212-
$errorCode = 'NoSpaceAfter'.$humanReadableCode;
213-
$fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data);
214-
if ($fix === true) {
215-
$phpcsFile->fixer->addContent($semicolon, ' ');
216-
}
217-
} else {
218-
if (strlen($tokens[($semicolon + 1)]['content']) !== 1) {
212+
// Only examine the space after the second semicolon if the last expression is not empty.
213+
// If it *is* empty, leave it up to the `SpacingBeforeClose` logic.
214+
$nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($semicolon + 1), ($closingBracket + 1), true);
215+
if ($semicolonCount !== 2 || $nextNonWhiteSpace !== $closingBracket) {
216+
if ($tokens[($semicolon + 1)]['code'] !== T_WHITESPACE
217+
&& $tokens[($semicolon + 1)]['code'] !== T_SEMICOLON
218+
) {
219+
$error = 'Expected 1 space after %s semicolon of FOR loop; 0 found';
220+
$errorCode = 'NoSpaceAfter'.$humanReadableCode;
221+
$fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data);
222+
if ($fix === true) {
223+
$phpcsFile->fixer->addContent($semicolon, ' ');
224+
}
225+
} else if ($tokens[($semicolon + 1)]['code'] === T_WHITESPACE
226+
&& $tokens[$nextNonWhiteSpace]['code'] !== T_SEMICOLON
227+
) {
219228
$spaces = strlen($tokens[($semicolon + 1)]['content']);
220-
$data[] = $spaces;
221-
if ($semicolonCount === 2 && ($semicolon + 2) === $closingBracket) {
222-
$error = 'Expected no space after second semicolon of FOR loop; %s found';
223-
$fix = $phpcsFile->addFixableError($error, $semicolon, 'SpacingAfterSecondNoThird', $data);
224-
if ($fix === true) {
225-
$phpcsFile->fixer->replaceToken(($semicolon + 1), '');
226-
}
227-
} else {
229+
if ($spaces !== 1) {
228230
$error = 'Expected 1 space after %s semicolon of FOR loop; %s found';
229231
$errorCode = 'SpacingAfter'.$humanReadableCode;
232+
$data[] = $spaces;
230233
$fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data);
231234
if ($fix === true) {
232235
$phpcsFile->fixer->replaceToken(($semicolon + 1), ' ');

0 commit comments

Comments
 (0)