From daa1940b80f6de71d3233f17c59e7d47bfb25960 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 25 Apr 2024 16:52:58 -0300 Subject: [PATCH 1/8] Generic/InlineControlStructure: fix error when handling `else if` This commit fixes a bug in this sniff where it would not handle correctly `elseif` statements when there is a comment between the `else` and `if` tokens. The affected code was added in https://github.com/squizlabs/PHP_CodeSniffer/commit/18f98cc9a48bacf026c1a61208d03f6b88c2f69e to fix a similar bug when there is more than one whitespace between `else` and `if`, but it failed to consider that there might be comment tokens between `else` and `if`. --- .../Sniffs/ControlStructures/InlineControlStructureSniff.php | 2 +- .../ControlStructures/InlineControlStructureUnitTest.1.inc | 4 ++++ .../InlineControlStructureUnitTest.1.inc.fixed | 5 +++++ .../ControlStructures/InlineControlStructureUnitTest.js | 4 ++++ .../InlineControlStructureUnitTest.js.fixed | 5 +++++ .../ControlStructures/InlineControlStructureUnitTest.php | 2 ++ 6 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php index 41efffa4df..bc4a916d20 100644 --- a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php +++ b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php @@ -75,7 +75,7 @@ public function process(File $phpcsFile, $stackPtr) // Ignore the ELSE in ELSE IF. We'll process the IF part later. if ($tokens[$stackPtr]['code'] === T_ELSE) { - $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); if ($tokens[$next]['code'] === T_IF) { return; } diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc index fb4a7380fb..739ba40a6d 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc @@ -272,3 +272,7 @@ function testFinally() } finally { } } + +if ($something) { + echo 'hello'; +} else /* comment */ if ($somethingElse) echo 'hi'; diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed index d80a32652a..9a89b0e387 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed @@ -307,3 +307,8 @@ function testFinally() } } } + +if ($something) { + echo 'hello'; +} else /* comment */ if ($somethingElse) { echo 'hi'; +} diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js index 4d3b1e8aa2..ca6dae13a0 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js @@ -29,3 +29,7 @@ if ($("#myid").rotationDegrees()=='90') if ($("#myid").rotationDegrees()=='90') $foo = {'transform': 'rotate(90deg)'}; + +if (something) { + alert('hello'); +} else /* comment */ if (somethingElse) alert('hi'); diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js.fixed index 8f0c413e75..d410cfb122 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js.fixed +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js.fixed @@ -37,3 +37,8 @@ if ($("#myid").rotationDegrees()=='90') { if ($("#myid").rotationDegrees()=='90') { $foo = {'transform': 'rotate(90deg)'}; } + +if (something) { + alert('hello'); +} else /* comment */ if (somethingElse) { alert('hi'); +} diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php index 44f1d74716..5d42d1122a 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php @@ -78,6 +78,7 @@ public function getErrorList($testFile='') 242 => 1, 260 => 1, 269 => 1, + 278 => 1, ]; case 'InlineControlStructureUnitTest.js': @@ -90,6 +91,7 @@ public function getErrorList($testFile='') 21 => 1, 27 => 1, 30 => 1, + 35 => 1, ]; default: From 3db1049adc9aaf3b5d4f13064e3311e89362f029 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 26 Apr 2024 12:50:18 -0300 Subject: [PATCH 2/8] Generic/InlineControlStructure: stop listening for T_SWITCH tokens There is no inline version of a `switch` in PHP so there is no reason for this sniff to listen to `T_SWITCH` tokens. Before this change, the sniff would bail early on the line below as a switch always has a scope opener, so this change should not impact in any way the behavior of the sniff. https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/9a0c2546ea2fa7aac19881da7b655cc5f022bc10/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php#L71 The InlineControlStructure sniff started listening for T_SWITCH tokens since the commit that added this sniff to PHPCS: https://github.com/PHPCSStandards/PHP_CodeSniffer/commit/ad96ebb#diff-e1ea4eabd79d6324057bbf726a27074250478f87d92c11a3725a97f0afbd5513R50 --- .../Sniffs/ControlStructures/InlineControlStructureSniff.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php index bc4a916d20..15c3cf3cfc 100644 --- a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php +++ b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php @@ -48,7 +48,6 @@ public function register() T_FOREACH, T_WHILE, T_DO, - T_SWITCH, T_FOR, ]; From 86c5693f682073d192253bc8c2fbb0dd4c3cf7eb Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 3 May 2024 11:35:05 -0300 Subject: [PATCH 3/8] Generic/InlineControlStructure: remove unreachable condition The removed condition was added in a5d3f147190dbb2fd103f1163eca69835edafb44. The tests added in this commit still pass without the removed condition. The condition is unreachable because `$end` can never be equal to `$phpcsFile->numTokens`. It will always be less than `$phpcsFile->numTokens`. `$end` represents the index of a token in the tokens array. The indexes of the tokens array are zero-based, and the `$phpcsFile->numTokens` property is one-based. So even if `$end` is pointing to the index of the last token, it will be less than `$phpcsFile->numTokens`. `$end` is first set as `$end = ($closer + 1)`. In theory, if `$closer` is the index of the last token, `$end` could be equal to `$phpcsFile->numTokens`. But that is a situation that will never occur as it will represent a syntax error, and the sniff would have bailed already. --- .../Sniffs/ControlStructures/InlineControlStructureSniff.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php index 15c3cf3cfc..bb11ffd733 100644 --- a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php +++ b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php @@ -269,10 +269,6 @@ public function process(File $phpcsFile, $stackPtr) } }//end for - if ($end === $phpcsFile->numTokens) { - $end = $lastNonEmpty; - } - $nextContent = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { // Looks for completely empty statements. From 6469d1ad09e09d431fa94352abd39e16b95621a3 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 3 May 2024 15:05:35 -0300 Subject: [PATCH 4/8] Generic/InlineControlStructure: rename JS test case file Doing this to be able to create tests with syntax errors on separate files. --- ...StructureUnitTest.js => InlineControlStructureUnitTest.1.js} | 0 ...tTest.js.fixed => InlineControlStructureUnitTest.1.js.fixed} | 0 .../Tests/ControlStructures/InlineControlStructureUnitTest.php | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename src/Standards/Generic/Tests/ControlStructures/{InlineControlStructureUnitTest.js => InlineControlStructureUnitTest.1.js} (100%) rename src/Standards/Generic/Tests/ControlStructures/{InlineControlStructureUnitTest.js.fixed => InlineControlStructureUnitTest.1.js.fixed} (100%) diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js similarity index 100% rename from src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js rename to src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js.fixed similarity index 100% rename from src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js.fixed rename to src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js.fixed diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php index 5d42d1122a..afcaa3a335 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php @@ -81,7 +81,7 @@ public function getErrorList($testFile='') 278 => 1, ]; - case 'InlineControlStructureUnitTest.js': + case 'InlineControlStructureUnitTest.1.js': return [ 3 => 1, 7 => 1, From 0d32a27718a8aa7af457491458b730cfb1b62650 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 3 May 2024 15:15:52 -0300 Subject: [PATCH 5/8] Generic/InlineControlStructure: remove redundant condition This commit removes a redundant condition that was added in fbea319 to support JS braceless do-while loops. A subsequent commit added similar code to support braceless do-while loops (plus for/while loops without body) for PHP, but it also works for JS (13c803b). There are a few syntax error cases that were handled by the code that is removed by this commit and are not handled by the code introduced in 13c803b. Without the removed code, they are now handled in a if condition right below. I added two tests with those cases to ensure the sniff continues working as expected. --- .../InlineControlStructureSniff.php | 15 --------------- .../InlineControlStructureUnitTest.2.js | 5 +++++ .../InlineControlStructureUnitTest.3.js | 5 +++++ 3 files changed, 10 insertions(+), 15 deletions(-) create mode 100644 src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.2.js create mode 100644 src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.3.js diff --git a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php index bb11ffd733..0c9837963d 100644 --- a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php +++ b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php @@ -94,21 +94,6 @@ public function process(File $phpcsFile, $stackPtr) return; } } - - // In Javascript DO WHILE loops without curly braces are legal. This - // is only valid if a single statement is present between the DO and - // the WHILE. We can detect this by checking only a single semicolon - // is present between them. - if ($tokens[$stackPtr]['code'] === T_WHILE && $phpcsFile->tokenizerType === 'JS') { - $lastDo = $phpcsFile->findPrevious(T_DO, ($stackPtr - 1)); - $lastSemicolon = $phpcsFile->findPrevious(T_SEMICOLON, ($stackPtr - 1)); - if ($lastDo !== false && $lastSemicolon !== false && $lastDo < $lastSemicolon) { - $precedingSemicolon = $phpcsFile->findPrevious(T_SEMICOLON, ($lastSemicolon - 1)); - if ($precedingSemicolon === false || $precedingSemicolon < $lastDo) { - return; - } - } - } }//end if if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.2.js b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.2.js new file mode 100644 index 0000000000..e26c331270 --- /dev/null +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.2.js @@ -0,0 +1,5 @@ +// Intentional parse error (missing closing parenthesis). +// This should be the only test in this file. +// Testing that the sniff is *not* triggered. + +do i++; while (i < 5 diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.3.js b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.3.js new file mode 100644 index 0000000000..9ccedcda33 --- /dev/null +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.3.js @@ -0,0 +1,5 @@ +// Intentional parse error (missing opening parenthesis). +// This should be the only test in this file. +// Testing that the sniff is *not* triggered. + +do i++; while From cf9459c6190afec8ad6c9ba6f85b86ffed58f27a Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 3 May 2024 15:59:42 -0300 Subject: [PATCH 6/8] Generic/InlineControlStructure: fix bug when handling elseif/if/foreach without body In PHP, `elseif`, `if` and `foreach` can be declared without a body. The sniff was improperly flagging those as inline control structures. This commit changes that, and now the sniff does not trigger an error anymore for elseif/if/foreach without a body. This is consistent with the behavior of the sniff for `while` and `for` statements without a body. It is likely that this problem was not found before because it is hard to imagine a case in which an `elseif`, `if` or `foreach` without a body would be useful. --- .../InlineControlStructureSniff.php | 4 ++-- .../InlineControlStructureUnitTest.1.inc | 13 +++++++++++++ .../InlineControlStructureUnitTest.1.inc.fixed | 14 ++++++++++++++ .../InlineControlStructureUnitTest.php | 1 + 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php index 0c9837963d..0d35d565df 100644 --- a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php +++ b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php @@ -80,8 +80,8 @@ public function process(File $phpcsFile, $stackPtr) } } - if ($tokens[$stackPtr]['code'] === T_WHILE || $tokens[$stackPtr]['code'] === T_FOR) { - // This could be from a DO WHILE, which doesn't have an opening brace or a while/for without body. + if (in_array($tokens[$stackPtr]['code'], [T_ELSEIF, T_IF, T_FOR, T_FOREACH, T_WHILE], true) === true) { + // This could be from a DO WHILE, which doesn't have an opening brace, or an elseif/if/for/foreach/while without body. if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { $afterParensCloser = $phpcsFile->findNext(Tokens::$emptyTokens, ($tokens[$stackPtr]['parenthesis_closer'] + 1), null, true); if ($afterParensCloser === false) { diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc index 739ba40a6d..a9d8ce7884 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc @@ -276,3 +276,16 @@ function testFinally() if ($something) { echo 'hello'; } else /* comment */ if ($somethingElse) echo 'hi'; + +if ($shouldNotTriggerSniff); + +if (false) { +} elseif ($shouldNotTriggerSniff); + +if (false) { +} else if ($shouldNotTriggerSniff); + +if (false) { +} else ($shouldTriggerSniff); + +foreach ($array as $shouldNotTriggerSniff); diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed index 9a89b0e387..d965fe644d 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed @@ -312,3 +312,17 @@ if ($something) { echo 'hello'; } else /* comment */ if ($somethingElse) { echo 'hi'; } + +if ($shouldNotTriggerSniff); + +if (false) { +} elseif ($shouldNotTriggerSniff); + +if (false) { +} else if ($shouldNotTriggerSniff); + +if (false) { +} else { ($shouldTriggerSniff); +} + +foreach ($array as $shouldNotTriggerSniff); diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php index afcaa3a335..93a485fa40 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php @@ -79,6 +79,7 @@ public function getErrorList($testFile='') 260 => 1, 269 => 1, 278 => 1, + 289 => 1, ]; case 'InlineControlStructureUnitTest.1.js': From b1ae5ae974dada4db8839553183887af6635f5da Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Mon, 6 May 2024 16:03:56 -0300 Subject: [PATCH 7/8] Generic/InlineControlStructure: remove unreachable condition This commit removes an unreachable condition in the fixer part of the sniff. The original version of this condition was added in the early days by the commit that enabled this sniff to fix errors: https://github.com/squizlabs/PHP_CodeSniffer/commit/a54c6193472f7c98d64c481a9e7d1203de300889#diff-4b3945c2100b0a92a56509de1b797bf58ad804cf36233c95c492479b665655dcL108-L110 The only two tests that were added with the commit mentioned above that trigger the removed condition are tests using `while` loops without body: https://github.com/squizlabs/PHP_CodeSniffer/commit/a54c6193472f7c98d64c481a9e7d1203de300889#diff-4b3945c2100b0a92a56509de1b797bf58ad804cf36233c95c492479b665655dcL108-L110 I believe control structures without a body are the only cases where `$next` would be equal to `$end`. Thus, these are the only cases where the removed condition would be executed. But subsequent commits changed the sniff to bail early and not get to the fixer part when handling control structures without a body: - 13c803b changed the sniff to ignore while/for without a body and updated the existing tests: https://github.com/squizlabs/PHP_CodeSniffer/commit/13c803bb14d01641ca089d515eab4287c71e8156#diff-2f069f3fe33bacdfc80485b97303aec66c98c451d07e6d86e41982b81ab1a294L49-R51 - f4afa10 expanded the same approach to also include elseif/if/foreach control structures Those changes rendered the condition that is removed by this commit unreachable. --- .../InlineControlStructureSniff.php | 120 +++++++----------- 1 file changed, 46 insertions(+), 74 deletions(-) diff --git a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php index 0d35d565df..37cab1528e 100644 --- a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php +++ b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php @@ -263,94 +263,66 @@ public function process(File $phpcsFile, $stackPtr) $endLine = $end; } - if ($next !== $end) { - if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { - // Account for a comment on the end of the line. - for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) { - if (isset($tokens[($endLine + 1)]) === false - || $tokens[$endLine]['line'] !== $tokens[($endLine + 1)]['line'] - ) { - break; - } - } - - if (isset(Tokens::$commentTokens[$tokens[$endLine]['code']]) === false - && ($tokens[$endLine]['code'] !== T_WHITESPACE - || isset(Tokens::$commentTokens[$tokens[($endLine - 1)]['code']]) === false) - ) { - $endLine = $end; - } - } - - if ($endLine !== $end) { - $endToken = $endLine; - $addedContent = ''; - } else { - $endToken = $end; - $addedContent = $phpcsFile->eolChar; - - if ($tokens[$end]['code'] !== T_SEMICOLON - && $tokens[$end]['code'] !== T_CLOSE_CURLY_BRACKET + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Account for a comment on the end of the line. + for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) { + if (isset($tokens[($endLine + 1)]) === false + || $tokens[$endLine]['line'] !== $tokens[($endLine + 1)]['line'] ) { - $phpcsFile->fixer->addContent($end, '; '); + break; } } - $next = $phpcsFile->findNext(T_WHITESPACE, ($endToken + 1), null, true); - if ($next !== false - && ($tokens[$next]['code'] === T_ELSE - || $tokens[$next]['code'] === T_ELSEIF) + if (isset(Tokens::$commentTokens[$tokens[$endLine]['code']]) === false + && ($tokens[$endLine]['code'] !== T_WHITESPACE + || isset(Tokens::$commentTokens[$tokens[($endLine - 1)]['code']]) === false) ) { - $phpcsFile->fixer->addContentBefore($next, '} '); - } else { - $indent = ''; - for ($first = $stackPtr; $first > 0; $first--) { - if ($tokens[$first]['column'] === 1) { - break; - } - } + $endLine = $end; + } + } - if ($tokens[$first]['code'] === T_WHITESPACE) { - $indent = $tokens[$first]['content']; - } else if ($tokens[$first]['code'] === T_INLINE_HTML - || $tokens[$first]['code'] === T_OPEN_TAG - ) { - $addedContent = ''; - } + if ($endLine !== $end) { + $endToken = $endLine; + $addedContent = ''; + } else { + $endToken = $end; + $addedContent = $phpcsFile->eolChar; - $addedContent .= $indent.'}'; - if ($next !== false && $tokens[$endToken]['code'] === T_COMMENT) { - $addedContent .= $phpcsFile->eolChar; - } + if ($tokens[$end]['code'] !== T_SEMICOLON + && $tokens[$end]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + $phpcsFile->fixer->addContent($end, '; '); + } + } - $phpcsFile->fixer->addContent($endToken, $addedContent); - }//end if + $next = $phpcsFile->findNext(T_WHITESPACE, ($endToken + 1), null, true); + if ($next !== false + && ($tokens[$next]['code'] === T_ELSE + || $tokens[$next]['code'] === T_ELSEIF) + ) { + $phpcsFile->fixer->addContentBefore($next, '} '); } else { - if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { - // Account for a comment on the end of the line. - for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) { - if (isset($tokens[($endLine + 1)]) === false - || $tokens[$endLine]['line'] !== $tokens[($endLine + 1)]['line'] - ) { - break; - } + $indent = ''; + for ($first = $stackPtr; $first > 0; $first--) { + if ($tokens[$first]['column'] === 1) { + break; } + } - if ($tokens[$endLine]['code'] !== T_COMMENT - && ($tokens[$endLine]['code'] !== T_WHITESPACE - || $tokens[($endLine - 1)]['code'] !== T_COMMENT) - ) { - $endLine = $end; - } + if ($tokens[$first]['code'] === T_WHITESPACE) { + $indent = $tokens[$first]['content']; + } else if ($tokens[$first]['code'] === T_INLINE_HTML + || $tokens[$first]['code'] === T_OPEN_TAG + ) { + $addedContent = ''; } - if ($endLine !== $end) { - $phpcsFile->fixer->replaceToken($end, ''); - $phpcsFile->fixer->addNewlineBefore($endLine); - $phpcsFile->fixer->addContent($endLine, '}'); - } else { - $phpcsFile->fixer->replaceToken($end, '}'); + $addedContent .= $indent.'}'; + if ($next !== false && $tokens[$endToken]['code'] === T_COMMENT) { + $addedContent .= $phpcsFile->eolChar; } + + $phpcsFile->fixer->addContent($endToken, $addedContent); }//end if $phpcsFile->fixer->endChangeset(); From 89f4fc62cba2a81dcd3dbcf4ae3f53590122fa7d Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 26 Apr 2024 11:21:20 -0300 Subject: [PATCH 8/8] Generic/InlineControlStructure: improve code coverage --- .../InlineControlStructureUnitTest.1.inc | 10 +++++++++ ...InlineControlStructureUnitTest.1.inc.fixed | 14 ++++++++++++ .../InlineControlStructureUnitTest.10.inc | 9 ++++++++ ...nlineControlStructureUnitTest.10.inc.fixed | 10 +++++++++ .../InlineControlStructureUnitTest.8.inc | 7 ++++++ .../InlineControlStructureUnitTest.9.inc | 7 ++++++ .../InlineControlStructureUnitTest.php | 22 +++++++++++++++++-- 7 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.10.inc create mode 100644 src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.10.inc.fixed create mode 100644 src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.8.inc create mode 100644 src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.9.inc diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc index a9d8ce7884..d0a3c5f7ec 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc @@ -289,3 +289,13 @@ if (false) { } else ($shouldTriggerSniff); foreach ($array as $shouldNotTriggerSniff); + +do echo $i++; while ($i < 5); + +// phpcs:set Generic.ControlStructures.InlineControlStructure error false +if ($something) echo 'hello'; +// phpcs:set Generic.ControlStructures.InlineControlStructure error true + +if ($noSpaceAfterClosingParenthesis)echo 'hello'; + +do ; while ($i > 5); diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed index d965fe644d..631fa55fc1 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed @@ -326,3 +326,17 @@ if (false) { } foreach ($array as $shouldNotTriggerSniff); + +do { echo $i++; +} while ($i < 5); + +// phpcs:set Generic.ControlStructures.InlineControlStructure error false +if ($something) { echo 'hello'; +} +// phpcs:set Generic.ControlStructures.InlineControlStructure error true + +if ($noSpaceAfterClosingParenthesis) { echo 'hello'; +} + +do { ; +} while ($i > 5); diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.10.inc b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.10.inc new file mode 100644 index 0000000000..6de22da665 --- /dev/null +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.10.inc @@ -0,0 +1,9 @@ + 1, 278 => 1, 289 => 1, + 293 => 1, + 299 => 1, + 301 => 1, + ]; + + case 'InlineControlStructureUnitTest.10.inc': + return [ + 6 => 1, ]; case 'InlineControlStructureUnitTest.1.js': @@ -108,11 +116,21 @@ public function getErrorList($testFile='') * The key of the array should represent the line number and the value * should represent the number of warnings that should occur on that line. * + * @param string $testFile The name of the file being tested. + * * @return array */ - public function getWarningList() + public function getWarningList($testFile='') { - return []; + switch ($testFile) { + case 'InlineControlStructureUnitTest.1.inc': + return [ + 296 => 1, + ]; + + default: + return []; + } }//end getWarningList()