Skip to content

Commit 8a2b6b1

Browse files
authored
Merge pull request #427 from PHPCSStandards/feature/squiz-operatorspacing-prevent-fixer-conflict
Squiz/OperatorSpacing: bug fix - prevent fixer conflict
2 parents 37af382 + 195e941 commit 8a2b6b1

File tree

5 files changed

+83
-17
lines changed

5 files changed

+83
-17
lines changed

src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ public function process(File $phpcsFile, $stackPtr)
238238
) {
239239
// Throw an error for assignments only if enabled using the sniff property
240240
// because other standards allow multiple spaces to align assignments.
241-
if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) {
241+
$prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
242+
if ($tokens[$prevNonWhitespace]['line'] !== $tokens[$stackPtr]['line']) {
242243
$found = 'newline';
243244
} else {
244245
$found = $tokens[($stackPtr - 1)]['length'];
@@ -253,20 +254,29 @@ public function process(File $phpcsFile, $stackPtr)
253254
$operator,
254255
$found,
255256
];
256-
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBefore', $data);
257-
if ($fix === true) {
258-
$phpcsFile->fixer->beginChangeset();
259-
if ($found === 'newline') {
260-
$i = ($stackPtr - 2);
261-
while ($tokens[$i]['code'] === T_WHITESPACE) {
262-
$phpcsFile->fixer->replaceToken($i, '');
263-
$i--;
257+
258+
if (isset(Tokens::$commentTokens[$tokens[$prevNonWhitespace]['code']]) === true) {
259+
// Throw a non-fixable error if the token on the previous line is a comment token,
260+
// as in that case it's not for the sniff to decide where the comment should be moved to
261+
// and it would get us into unfixable situations as the new line char is included
262+
// in the contents of the comment token.
263+
$phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data);
264+
} else {
265+
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBefore', $data);
266+
if ($fix === true) {
267+
$phpcsFile->fixer->beginChangeset();
268+
if ($found === 'newline') {
269+
$i = ($stackPtr - 2);
270+
while ($tokens[$i]['code'] === T_WHITESPACE) {
271+
$phpcsFile->fixer->replaceToken($i, '');
272+
$i--;
273+
}
264274
}
265-
}
266275

267-
$phpcsFile->fixer->replaceToken(($stackPtr - 1), ' ');
268-
$phpcsFile->fixer->endChangeset();
269-
}
276+
$phpcsFile->fixer->replaceToken(($stackPtr - 1), ' ');
277+
$phpcsFile->fixer->endChangeset();
278+
}
279+
}//end if
270280
}//end if
271281
}//end if
272282

src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,5 +483,28 @@ match ($a) {
483483
default => -3,
484484
};
485485

486-
/* Intentional parse error. This has to be the last test in the file. */
487-
$a = 10 +
486+
$foo = $var
487+
? 10
488+
: true;
489+
490+
// Safeguard that a non-fixable error is thrown when there is a new line before the operator,
491+
// but the last non-whitespace token before the operator is a comment token.
492+
$foo = $var // Comment
493+
? false /* Comment */
494+
: true;
495+
496+
$foo = $var // phpcs: ignore Stnd.Cat.Sniff -- for reasons.
497+
498+
499+
? $something /**
500+
* Don't ask, but someone might have a docblock between the lines. It's valid PHP after all.
501+
*/
502+
503+
504+
: true;
505+
506+
// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true
507+
$foo = $var // Comment
508+
? false // Comment
509+
: true;
510+
// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false

src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc.fixed

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,5 +477,26 @@ match ($a) {
477477
default => -3,
478478
};
479479

480-
/* Intentional parse error. This has to be the last test in the file. */
481-
$a = 10 +
480+
$foo = $var ? 10 : true;
481+
482+
// Safeguard that a non-fixable error is thrown when there is a new line before the operator,
483+
// but the last non-whitespace token before the operator is a comment token.
484+
$foo = $var // Comment
485+
? false /* Comment */
486+
: true;
487+
488+
$foo = $var // phpcs: ignore Stnd.Cat.Sniff -- for reasons.
489+
490+
491+
? $something /**
492+
* Don't ask, but someone might have a docblock between the lines. It's valid PHP after all.
493+
*/
494+
495+
496+
: true;
497+
498+
// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true
499+
$foo = $var // Comment
500+
? false // Comment
501+
: true;
502+
// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
// Intentional parse error (unfinished statement).
4+
// This has to be the only test in the file.
5+
6+
$a = 10 +

src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ public function getErrorList($testFile='')
104104
265 => 2,
105105
266 => 2,
106106
271 => 2,
107+
487 => 1,
108+
488 => 1,
109+
493 => 1,
110+
494 => 1,
111+
499 => 1,
112+
504 => 1,
107113
];
108114

109115
case 'OperatorSpacingUnitTest.js':

0 commit comments

Comments
 (0)