From a9b6fa09169de4640a527e574d046dcf6ea4e6cb Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 4 Oct 2024 15:23:00 -0300 Subject: [PATCH 1/7] Generic/InlineControlStructure: stop listening for T_SWITCH tokens There is no inline version of a `switch` in PHP and JS 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 it to PHPCS: https://github.com/PHPCSStandards/PHP_CodeSniffer/commit/ad96eb#diff-e1ea4eabd79d6324057bbf726a27074250478f87d92c11a3725a97f0afbd5513R50 Some of the sniff tests using the `T_SWITCH` token were added to protect against regressions for changes in the tokenizer. For those, dedicated tokenizer tests will be created in subsequent commits. Those commits will also update the related sniff tests to use different control structures other than `T_SWITCH` when appropriate. The modified JS test lost part of its value over time as now the sniff bails early if there is no opening parenthesis after the control structure. Ideally, it should be moved to a tokenizer test, but since there are no tests for the JS tokenizer and support will be dropped in PHPCS 4.0, I opted to simply use a control structure other than T_SWITCH. This test was originally added in b3f4f83. References: - PHP: https://www.php.net/manual/en/control-structures.switch.php - JS: https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html --- .../Sniffs/ControlStructures/InlineControlStructureSniff.php | 1 - .../Tests/ControlStructures/InlineControlStructureUnitTest.1.js | 2 +- .../ControlStructures/InlineControlStructureUnitTest.1.js.fixed | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php index ff1738328f..1efb15c7be 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, ]; diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js index ca6dae13a0..763c1c1c1c 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js @@ -20,7 +20,7 @@ do { do i++; while (i < 5); -SomeClass.prototype.switch = function() { +SomeClass.prototype.for = function() { // do something }; diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js.fixed index d410cfb122..050a406bba 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js.fixed +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js.fixed @@ -26,7 +26,7 @@ do { do { i++; } while (i < 5); -SomeClass.prototype.switch = function() { +SomeClass.prototype.for = function() { // do something }; From 4c92408c42aef9a0d756a5ca6abdbcbea10595a5 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Wed, 22 May 2024 11:47:12 -0300 Subject: [PATCH 2/7] Tests/Tokenizer: tests to ensure scope is set correctly for T_SWITCH This commit copies, with some non-structural modifications, a sniff test to the tokenizer tests. The original test was added in b24b96b, part of https://github.com/squizlabs/PHP_CodeSniffer/issues/497. b24b96b introduced a test to InlineControlStructureUnitTest.php as there were no Tokenizer tests back then. It was added to ensure that Tokenizer::recurseScopeMap() would correctly add scope information to the `T_SWITCH` token when handling a `switch` that uses the alternative syntax. This commit also adds a test to ensure the scope is correctly set when using the normal switch syntax. This was not part of b24b96b, but it is relevant anyway, as no other tokenizer test covers this part. Since the InlineControlStructure sniff doesn't listen for the `T_SWITCH` token anymore (see baa4f65), the original test added in b24b96b became useless and thus was refactored to use a different control structure. The sniff test was kept as testing code that uses a control structure, and opening and closing PHP tags is an interesting case not covered in other tests. --- .../InlineControlStructureUnitTest.1.inc | 16 +-- ...InlineControlStructureUnitTest.1.inc.fixed | 16 +-- .../RecurseScopeMapSwitchTokenScopeTest.inc | 24 ++++ .../RecurseScopeMapSwitchTokenScopeTest.php | 113 ++++++++++++++++++ 4 files changed, 153 insertions(+), 16 deletions(-) create mode 100644 tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.inc create mode 100644 tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.php diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc index 739ba40a6d..11b4912153 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc @@ -79,14 +79,14 @@ if ($a) error): - case Shop_Customer :: ERROR_INVALID_GENDER: ?> - Ungültiges Geschlecht! - - Die eingetragene E-Mail-Adresse ist bereits registriert. - + Error one! + + Error two! +allowShopping !== true): if ($this->status != Shop_Cart :: OK): diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed index 9a89b0e387..7e2e628ae3 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed @@ -91,14 +91,14 @@ if ($a) { error): - case Shop_Customer :: ERROR_INVALID_GENDER: ?> - Ungültiges Geschlecht! - - Die eingetragene E-Mail-Adresse ist bereits registriert. - + Error one! + + Error two! +allowShopping !== true): if ($this->status != Shop_Cart :: OK): diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.inc b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.inc new file mode 100644 index 0000000000..682e1f46ee --- /dev/null +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.inc @@ -0,0 +1,24 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class RecurseScopeMapSwitchTokenScopeTest extends AbstractTokenizerTestCase +{ + + + /** + * Tests setting the scope for T_SWITCH token (normal and alternative syntax). + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array $expectedTokens The expected token codes for the scope opener/closer. + * @param string|null $testCloserMarker Optional. The comment which prefaces the scope closer if different + * from the test marker. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/497#ref-commit-b24b96b + * + * @dataProvider dataSwitchScope + * @covers \PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testSwitchScope($testMarker, $expectedTokens, $testCloserMarker=null) + { + $tokens = $this->phpcsFile->getTokens(); + $switchIndex = $this->getTargetToken($testMarker, [T_SWITCH]); + $tokenArray = $tokens[$switchIndex]; + + $scopeCloserMarker = $testMarker; + if (isset($testCloserMarker) === true) { + $scopeCloserMarker = $testCloserMarker; + } + + $expectedScopeCondition = $switchIndex; + $expectedScopeOpener = $this->getTargetToken($testMarker, $expectedTokens['scope_opener']); + $expectedScopeCloser = $this->getTargetToken($scopeCloserMarker, $expectedTokens['scope_closer']); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition not set'); + $this->assertSame( + $expectedScopeCondition, + $tokenArray['scope_condition'], + sprintf( + 'Scope condition not set correctly; expected T_SWITCH, found %s', + $tokens[$tokenArray['scope_condition']]['type'] + ) + ); + + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener not set'); + $this->assertSame( + $expectedScopeOpener, + $tokenArray['scope_opener'], + sprintf( + 'Scope opener not set correctly; expected %s, found %s', + $tokens[$expectedScopeOpener]['type'], + $tokens[$tokenArray['scope_opener']]['type'] + ) + ); + + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer not set'); + $this->assertSame( + $expectedScopeCloser, + $tokenArray['scope_closer'], + sprintf( + 'Scope closer not set correctly; expected %s, found %s', + $tokens[$expectedScopeCloser]['type'], + $tokens[$tokenArray['scope_closer']]['type'] + ) + ); + + }//end testSwitchScope() + + + /** + * Data provider. + * + * @see testSwitchScope() + * + * @return array>> + */ + public static function dataSwitchScope() + { + return [ + 'switch normal syntax' => [ + 'testMarker' => '/* testSwitchNormalSyntax */', + 'expectedTokens' => [ + 'scope_opener' => T_OPEN_CURLY_BRACKET, + 'scope_closer' => T_CLOSE_CURLY_BRACKET, + ], + ], + 'switch alternative syntax' => [ + 'testMarker' => '/* testSwitchAlternativeSyntax */', + 'expectedTokens' => [ + 'scope_opener' => T_COLON, + 'scope_closer' => T_ENDSWITCH, + ], + 'testCloserMarker' => '/* testSwitchAlternativeSyntaxEnd */', + ], + ]; + + }//end dataSwitchScope() + + +}//end class From b9809c7b16b686cea25de0d60e1d95fe6c7e17ae Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 26 Jul 2024 10:50:27 +0200 Subject: [PATCH 3/7] Tests/Tokenizer: tests for T_CASE and T_IF scope condition This commit copies, with some non-structural modifications, a sniff test to the tokenizer tests. Two new tokenizer tests are created as the result of this copy. One to ensure that the scope of `T_CASE` is correctly set when the case shares the scope closer with `T_SWITCH` (no `T_BREAK`). And another to ensure that the scope of `T_IF` is correctly set when there is a nested `T_SWITCH` and `T_CASE` without a `T_BREAK`. The original sniff test was added in fddc61a, which is part of https://github.com/squizlabs/PHP_CodeSniffer/issues/497. fddc61a introduced a test to InlineControlStructureUnitTest.php as there were no Tokenizer tests back then. The test was added to ensure that Tokenizer::recurseScopeMap() correctly adds scope information to the `T_CASE` token when it shares the closer with `T_SWITCH` and to `T_IF` when a nested `T_CASE` shares the scope closer with T_SWITCH`. Since the InlineControlStructure sniff doesn't listen for the `T_SWITCH` token anymore (see baa4f65), the original test added in fddc61a became useless and thus was refactored to use a different control structure. This new version of the sniff test was kept as testing code that uses nested alternative syntax control structures is still valid and is not covered in other tests. --- .../InlineControlStructureUnitTest.1.inc | 12 +-- ...InlineControlStructureUnitTest.1.inc.fixed | 12 +-- ...curseScopeMapCaseKeywordConditionsTest.inc | 7 ++ ...curseScopeMapCaseKeywordConditionsTest.php | 1 + ...RecurseScopeMapIfKeywordConditionsTest.inc | 13 ++++ ...RecurseScopeMapIfKeywordConditionsTest.php | 76 +++++++++++++++++++ 6 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 tests/Core/Tokenizers/Tokenizer/RecurseScopeMapIfKeywordConditionsTest.inc create mode 100644 tests/Core/Tokenizers/Tokenizer/RecurseScopeMapIfKeywordConditionsTest.php diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc index 11b4912153..e662111322 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc @@ -88,17 +88,17 @@ if ($error === ERROR_ONE): ?> -if ($this->allowShopping !== true): - if ($this->status != Shop_Cart :: OK): - switch ($this->status): - case Shop_Cart :: NOT_FOUND: - echo 'foo'; - endswitch; +if ($value): + if ($anotherValue): + foreach ($array as $element): + echo (function($element): string { return $element; } )($element); + endforeach; endif; else: echo 'foo'; endif; + // ELSE IF split over multiple lines (not inline) if ($test) { } else diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed index 7e2e628ae3..00c9d664fe 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed @@ -100,17 +100,17 @@ if ($error === ERROR_ONE): ?> -if ($this->allowShopping !== true): - if ($this->status != Shop_Cart :: OK): - switch ($this->status): - case Shop_Cart :: NOT_FOUND: - echo 'foo'; - endswitch; +if ($value): + if ($anotherValue): + foreach ($array as $element): + echo (function($element): string { return $element; } )($element); + endforeach; endif; else: echo 'foo'; endif; + // ELSE IF split over multiple lines (not inline) if ($test) { } else diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc index 13b87242e1..54a017b3d7 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc @@ -93,3 +93,10 @@ enum Foo: string { /* testKeywordAsEnumCaseNameShouldBeString7 */ case ARRAY = 'array'; } + +// Test for https://github.com/squizlabs/PHP_CodeSniffer/issues/497 +switch ($value): + /* testSwitchCaseScopeCloserSharedWithSwitch */ + case 1: + echo 'one'; +endswitch; diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php index 7fa4ba5567..321d04fcb8 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php @@ -106,6 +106,7 @@ public static function dataNotEnumCases() 'switch case with constant, keyword in mixed case' => ['/* testIsNotEnumCaseIsCaseInsensitive */'], 'switch case, body in curlies declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch1 */'], 'switch case, body after semicolon declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch2 */'], + 'switch case, shared closer with switch' => ['/* testSwitchCaseScopeCloserSharedWithSwitch */'], ]; }//end dataNotEnumCases() diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapIfKeywordConditionsTest.inc b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapIfKeywordConditionsTest.inc new file mode 100644 index 0000000000..e303c38500 --- /dev/null +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapIfKeywordConditionsTest.inc @@ -0,0 +1,13 @@ + + * @author Rodrigo Primo + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class RecurseScopeMapIfKeywordConditionsTest extends AbstractTokenizerTestCase +{ + + + /** + * Tests setting the scope for T_IF token with nested case statement missing break statement. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/497#ref-commit-fddc61a + * + * @covers \PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testIfElseWithNestedCaseMissingBreakSharedClosers() + { + + $tokens = $this->phpcsFile->getTokens(); + $ifTestMarker = '/* testIfElseWithNestedCaseMissingBreak */'; + $ifCloserTestMarker = '/* testIfElseWithNestedCaseMissingBreakCloser */'; + $ifTokenIndex = $this->getTargetToken($ifTestMarker, T_IF); + $tokenArray = $tokens[$ifTokenIndex]; + + $expectedScopeCondition = $ifTokenIndex; + $expectedScopeOpener = $this->getTargetToken($ifTestMarker, T_COLON); + $expectedScopeCloser = $this->getTargetToken($ifCloserTestMarker, T_ELSE); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition not set'); + $this->assertSame( + $expectedScopeCondition, + $tokenArray['scope_condition'], + sprintf( + 'Scope condition not set correctly; expected T_IF, found %s', + $tokens[$tokenArray['scope_condition']]['type'] + ) + ); + + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener not set'); + $this->assertSame( + $expectedScopeOpener, + $tokenArray['scope_opener'], + sprintf( + 'Scope opener not set correctly; expected %s, found %s', + $tokens[$expectedScopeOpener]['type'], + $tokens[$tokenArray['scope_opener']]['type'] + ) + ); + + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer not set'); + $this->assertSame( + $expectedScopeCloser, + $tokenArray['scope_closer'], + sprintf( + 'Scope closer not set correctly; expected %s, found %s', + $tokens[$expectedScopeCloser]['type'], + $tokens[$tokenArray['scope_closer']]['type'] + ) + ); + + }//end testIfElseWithNestedCaseMissingBreakSharedClosers() + + +}//end class From 954677560104cd596bab1e4fc16bea2f76f7dd2f Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Mon, 12 Aug 2024 19:25:18 -0300 Subject: [PATCH 4/7] Tests/Tokenizer: scope opener is set correctly for T_SWITCH This commit copies, with some modifications, a sniff test to the tokenizer tests. It ensures that the scope opener is set correctly for T_SWITCH when there is a closure in the condition. This safeguards against regressions related to 30c618e, which fixed https://github .com/squizlabs/PHP_CodeSniffer/issues/543. 30c618e originally added a test to InlineControlStructureUnitTest.php as there were no Tokenizer tests back then. Since the InlineControlStructure sniff doesn't listen for the `T_SWITCH` token anymore (see baa4f65), the original test added in 30c618e became useless and thus was refactored to use a different control structure. This new version of the sniff test was kept as testing code that uses a closure in the condition is still an interesting case and is not covered in other tests. --- .../InlineControlStructureUnitTest.1.inc | 14 +++++------ ...InlineControlStructureUnitTest.1.inc.fixed | 15 +++++------ .../InlineControlStructureUnitTest.php | 1 + .../RecurseScopeMapSwitchTokenScopeTest.inc | 9 +++++++ .../RecurseScopeMapSwitchTokenScopeTest.php | 25 ++++++++++++++++--- 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc index e662111322..c7b2a939b6 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc @@ -106,15 +106,15 @@ if ($test) { } else { } -switch($response = \Bar::baz('bat', function ($foo) { +if ((function () { return 'bar'; -})) { - case 1: - return 'test'; +})()) + echo 'one'; + + + + - case 2: - return 'other'; -} $stuff = [1,2,3]; foreach($stuff as $num) diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed index 00c9d664fe..c6099f4a89 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed @@ -118,16 +118,17 @@ if ($test) { } else { } -switch($response = \Bar::baz('bat', function ($foo) { +if ((function () { return 'bar'; -})) { - case 1: - return 'test'; - - case 2: - return 'other'; +})()) { + echo 'one'; } + + + + + $stuff = [1,2,3]; foreach($stuff as $num) { if ($num %2 ) { diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php index afcaa3a335..19c78e0f96 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php @@ -48,6 +48,7 @@ public function getErrorList($testFile='') 62 => 1, 66 => 1, 78 => 1, + 109 => 1, 120 => 1, 128 => 1, 134 => 1, diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.inc b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.inc index 682e1f46ee..71ef02897a 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.inc +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.inc @@ -22,3 +22,12 @@ switch ($value): break; /* testSwitchAlternativeSyntaxEnd */ endswitch; + +// Test for https://github.com/squizlabs/PHP_CodeSniffer/issues/543 +/* testSwitchClosureWithinCondition */ +switch((function () { + return 'bar'; +})()) /* testSwitchClosureWithinConditionScopeOpener */ { + case 1: + return 'test'; +} diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.php b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.php index e80f7f5134..0977c0365c 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.php +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapSwitchTokenScopeTest.php @@ -20,6 +20,8 @@ final class RecurseScopeMapSwitchTokenScopeTest extends AbstractTokenizerTestCas * * @param string $testMarker The comment which prefaces the target token in the test file. * @param array $expectedTokens The expected token codes for the scope opener/closer. + * @param string|null $testOpenerMarker Optional. The comment which prefaces the scope opener if different + * from the test marker. * @param string|null $testCloserMarker Optional. The comment which prefaces the scope closer if different * from the test marker. * @@ -30,19 +32,24 @@ final class RecurseScopeMapSwitchTokenScopeTest extends AbstractTokenizerTestCas * * @return void */ - public function testSwitchScope($testMarker, $expectedTokens, $testCloserMarker=null) + public function testSwitchScope($testMarker, $expectedTokens, $testOpenerMarker=null, $testCloserMarker=null) { $tokens = $this->phpcsFile->getTokens(); $switchIndex = $this->getTargetToken($testMarker, [T_SWITCH]); $tokenArray = $tokens[$switchIndex]; + $scopeOpenerMarker = $testMarker; + if (isset($testOpenerMarker) === true) { + $scopeOpenerMarker = $testOpenerMarker; + } + $scopeCloserMarker = $testMarker; if (isset($testCloserMarker) === true) { $scopeCloserMarker = $testCloserMarker; } $expectedScopeCondition = $switchIndex; - $expectedScopeOpener = $this->getTargetToken($testMarker, $expectedTokens['scope_opener']); + $expectedScopeOpener = $this->getTargetToken($scopeOpenerMarker, $expectedTokens['scope_opener']); $expectedScopeCloser = $this->getTargetToken($scopeCloserMarker, $expectedTokens['scope_closer']); $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition not set'); @@ -90,21 +97,31 @@ public function testSwitchScope($testMarker, $expectedTokens, $testCloserMarker= public static function dataSwitchScope() { return [ - 'switch normal syntax' => [ + 'switch normal syntax' => [ 'testMarker' => '/* testSwitchNormalSyntax */', 'expectedTokens' => [ 'scope_opener' => T_OPEN_CURLY_BRACKET, 'scope_closer' => T_CLOSE_CURLY_BRACKET, ], ], - 'switch alternative syntax' => [ + 'switch alternative syntax' => [ 'testMarker' => '/* testSwitchAlternativeSyntax */', 'expectedTokens' => [ 'scope_opener' => T_COLON, 'scope_closer' => T_ENDSWITCH, ], + 'testOpenerMarker' => null, 'testCloserMarker' => '/* testSwitchAlternativeSyntaxEnd */', ], + 'switch with closure in the condition' => [ + 'testMarker' => '/* testSwitchClosureWithinCondition */', + 'expectedTokens' => [ + 'scope_opener' => T_OPEN_CURLY_BRACKET, + 'scope_closer' => T_CLOSE_CURLY_BRACKET, + ], + 'testOpenerMarker' => '/* testSwitchClosureWithinConditionScopeOpener */', + 'testCloserMarker' => '/* testSwitchClosureWithinConditionScopeOpener */', + ], ]; }//end dataSwitchScope() From 82fae8e57e10f6a7000daf53910394d109064736 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Mon, 12 Aug 2024 17:02:22 -0300 Subject: [PATCH 5/7] Tests/Tokenizer: expand `recurseScopeMap()` tests for the case keyword This commit expands the existing `Tokenizer::recurseScopeMap()` tests for the `case` keyword when used in a switch statement to check the value of the `scope_condition`, `scope_opener` and `scope_closer` indexes besides checking if they are set. This is needed for a new test case that will be added in a subsequent commit. --- ...curseScopeMapCaseKeywordConditionsTest.inc | 3 + ...curseScopeMapCaseKeywordConditionsTest.php | 120 ++++++++++++++++-- 2 files changed, 110 insertions(+), 13 deletions(-) diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc index 54a017b3d7..a4bb911997 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc @@ -62,6 +62,7 @@ switch (true) { case CONSTANT = 1: /* testIsNotEnumCaseIsCaseInsensitive */ cAsE CONSTANT: +/* testCaseConstantCloserMarker */ } switch ($x) { @@ -69,11 +70,13 @@ switch ($x) { case 'a': { enum Foo {} break; + /* testCaseInSwitchWhenCreatingEnumInSwitch1CloserMarker */ } /* testCaseInSwitchWhenCreatingEnumInSwitch2 */ case 'b'; enum Bar {} + /* testCaseInSwitchWhenCreatingEnumInSwitch2CloserMarker */ break; } diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php index 321d04fcb8..7144289147 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php @@ -66,25 +66,65 @@ public static function dataEnumCases() /** * Test that "case" that is not enum case is still tokenized as `T_CASE`. * - * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array $expectedTokens The expected token codes for the scope opener/closer. + * @param string|null $testCloserMarker Optional. The comment which prefaces the scope closer if different + * from the test marker. * * @dataProvider dataNotEnumCases * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap * * @return void */ - public function testNotEnumCases($testMarker) + public function testNotEnumCases($testMarker, $expectedTokens, $testCloserMarker=null) { $tokens = $this->phpcsFile->getTokens(); - $case = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); - $tokenArray = $tokens[$case]; + $caseIndex = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + $tokenArray = $tokens[$caseIndex]; + + $scopeCloserMarker = $testMarker; + if (isset($testCloserMarker) === true) { + $scopeCloserMarker = $testCloserMarker; + } + + $expectedScopeCondition = $caseIndex; + $expectedScopeOpener = $this->getTargetToken($testMarker, $expectedTokens['scope_opener']); + $expectedScopeCloser = $this->getTargetToken($scopeCloserMarker, $expectedTokens['scope_closer']); // Make sure we're looking at the right token. $this->assertSame(T_CASE, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_CASE (code)'); $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); + $this->assertSame( + $expectedScopeCondition, + $tokenArray['scope_condition'], + sprintf( + 'Scope condition not set correctly; expected T_CASE, found %s.', + $tokens[$tokenArray['scope_condition']]['type'] + ) + ); + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); + $this->assertSame( + $expectedScopeOpener, + $tokenArray['scope_opener'], + sprintf( + 'Scope opener not set correctly; expected %s, found %s.', + $tokens[$expectedScopeOpener]['type'], + $tokens[$tokenArray['scope_opener']]['type'] + ) + ); + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); + $this->assertSame( + $expectedScopeCloser, + $tokenArray['scope_closer'], + sprintf( + 'Scope closer not set correctly; expected %s, found %s.', + $tokens[$expectedScopeCloser]['type'], + $tokens[$tokenArray['scope_closer']]['type'] + ) + ); }//end testNotEnumCases() @@ -94,19 +134,73 @@ public function testNotEnumCases($testMarker) * * @see testNotEnumCases() * - * @return array> + * @return array>> */ public static function dataNotEnumCases() { return [ - 'switch case with constant, semicolon condition end' => ['/* testCaseWithSemicolonIsNotEnumCase */'], - 'switch case with constant, colon condition end' => ['/* testCaseWithConstantIsNotEnumCase */'], - 'switch case with constant, comparison' => ['/* testCaseWithConstantAndIdenticalIsNotEnumCase */'], - 'switch case with constant, assignment' => ['/* testCaseWithAssigmentToConstantIsNotEnumCase */'], - 'switch case with constant, keyword in mixed case' => ['/* testIsNotEnumCaseIsCaseInsensitive */'], - 'switch case, body in curlies declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch1 */'], - 'switch case, body after semicolon declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch2 */'], - 'switch case, shared closer with switch' => ['/* testSwitchCaseScopeCloserSharedWithSwitch */'], + 'switch case with constant, semicolon condition end' => [ + 'testMarker' => '/* testCaseWithSemicolonIsNotEnumCase */', + 'expectedTokens' => [ + 'scope_opener' => T_SEMICOLON, + 'scope_closer' => T_CLOSE_CURLY_BRACKET, + ], + ], + 'switch case with constant, colon condition end' => [ + 'testMarker' => '/* testCaseWithConstantIsNotEnumCase */', + 'expectedTokens' => [ + 'scope_opener' => T_COLON, + 'scope_closer' => T_CLOSE_CURLY_BRACKET, + ], + 'testCloserMarker' => '/* testCaseConstantCloserMarker */', + ], + 'switch case with constant, comparison' => [ + 'testMarker' => '/* testCaseWithConstantAndIdenticalIsNotEnumCase */', + 'expectedTokens' => [ + 'scope_opener' => T_COLON, + 'scope_closer' => T_CLOSE_CURLY_BRACKET, + ], + 'testCloserMarker' => '/* testCaseConstantCloserMarker */', + ], + 'switch case with constant, assignment' => [ + 'testMarker' => '/* testCaseWithAssigmentToConstantIsNotEnumCase */', + 'expectedTokens' => [ + 'scope_opener' => T_COLON, + 'scope_closer' => T_CLOSE_CURLY_BRACKET, + ], + 'testCloserMarker' => '/* testCaseConstantCloserMarker */', + ], + 'switch case with constant, keyword in mixed case' => [ + 'testMarker' => '/* testIsNotEnumCaseIsCaseInsensitive */', + 'expectedTokens' => [ + 'scope_opener' => T_COLON, + 'scope_closer' => T_CLOSE_CURLY_BRACKET, + ], + 'testCloserMarker' => '/* testCaseConstantCloserMarker */', + ], + 'switch case, body in curlies declares enum' => [ + 'testMarker' => '/* testCaseInSwitchWhenCreatingEnumInSwitch1 */', + 'expectedTokens' => [ + 'scope_opener' => T_OPEN_CURLY_BRACKET, + 'scope_closer' => T_CLOSE_CURLY_BRACKET, + ], + 'testCloserMarker' => '/* testCaseInSwitchWhenCreatingEnumInSwitch1CloserMarker */', + ], + 'switch case, body after semicolon declares enum' => [ + 'testMarker' => '/* testCaseInSwitchWhenCreatingEnumInSwitch2 */', + 'expectedTokens' => [ + 'scope_opener' => T_SEMICOLON, + 'scope_closer' => T_BREAK, + ], + 'testCloserMarker' => '/* testCaseInSwitchWhenCreatingEnumInSwitch2CloserMarker */', + ], + 'switch case, shared closer with switch' => [ + 'testMarker' => '/* testSwitchCaseScopeCloserSharedWithSwitch */', + 'expectedTokens' => [ + 'scope_opener' => T_COLON, + 'scope_closer' => T_ENDSWITCH, + ], + ], ]; }//end dataNotEnumCases() From 61b9e9b4ec2af6471eb7e56c18b2da931245b88c Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Tue, 13 Aug 2024 11:15:55 -0300 Subject: [PATCH 6/7] Tests/Tokenizer: test to ensure scope closer is set correctly for T_CASE This commit copies a sniff test from InlineControlStructureUnitTest.php to the `Tokenizer::recurseScopeMap()` tests for the case keyword. This test was added in b498dbe before the Tokenizer tests were created. It ensures that the scope for the `T_CASE` token is correctly set when there is an if/elseif/else with and without braces inside it. Note that this test currently does not fail even when the changes to the tokenizer applied in b498dbe are reverted. I'm assuming that a subsequent commit further improved the tokenizer and made the changes from b498dbe redundant, but I was not able to find the specific commit using `git bissect`. That being said, I was able to confirm that before b498dbe, the scope closer for the `T_CASE` token was incorrectly set to `T_RETURN` instead of `T_BREAK`. The original sniff test was kept without any modification as testing if/elseif/else with and without curly braces inside another control structure is still valid. --- ...curseScopeMapCaseKeywordConditionsTest.inc | 14 +++++++++++ ...curseScopeMapCaseKeywordConditionsTest.php | 23 ++++++++++++------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc index a4bb911997..6c71d80db0 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc @@ -103,3 +103,17 @@ switch ($value): case 1: echo 'one'; endswitch; + +// Test for https://github.com/squizlabs/PHP_CodeSniffer/issues/879 +switch ($type) { + /* testSwitchCaseNestedIfWithAndWithoutBraces */ + case 1: + if ($foo) { + return true; + } elseif ($baz) + return true; + else { + echo 'else'; + } + break; +} diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php index 7144289147..8b651c6d43 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php @@ -139,14 +139,14 @@ public function testNotEnumCases($testMarker, $expectedTokens, $testCloserMarker public static function dataNotEnumCases() { return [ - 'switch case with constant, semicolon condition end' => [ + 'switch case with constant, semicolon condition end' => [ 'testMarker' => '/* testCaseWithSemicolonIsNotEnumCase */', 'expectedTokens' => [ 'scope_opener' => T_SEMICOLON, 'scope_closer' => T_CLOSE_CURLY_BRACKET, ], ], - 'switch case with constant, colon condition end' => [ + 'switch case with constant, colon condition end' => [ 'testMarker' => '/* testCaseWithConstantIsNotEnumCase */', 'expectedTokens' => [ 'scope_opener' => T_COLON, @@ -154,7 +154,7 @@ public static function dataNotEnumCases() ], 'testCloserMarker' => '/* testCaseConstantCloserMarker */', ], - 'switch case with constant, comparison' => [ + 'switch case with constant, comparison' => [ 'testMarker' => '/* testCaseWithConstantAndIdenticalIsNotEnumCase */', 'expectedTokens' => [ 'scope_opener' => T_COLON, @@ -162,7 +162,7 @@ public static function dataNotEnumCases() ], 'testCloserMarker' => '/* testCaseConstantCloserMarker */', ], - 'switch case with constant, assignment' => [ + 'switch case with constant, assignment' => [ 'testMarker' => '/* testCaseWithAssigmentToConstantIsNotEnumCase */', 'expectedTokens' => [ 'scope_opener' => T_COLON, @@ -170,7 +170,7 @@ public static function dataNotEnumCases() ], 'testCloserMarker' => '/* testCaseConstantCloserMarker */', ], - 'switch case with constant, keyword in mixed case' => [ + 'switch case with constant, keyword in mixed case' => [ 'testMarker' => '/* testIsNotEnumCaseIsCaseInsensitive */', 'expectedTokens' => [ 'scope_opener' => T_COLON, @@ -178,7 +178,7 @@ public static function dataNotEnumCases() ], 'testCloserMarker' => '/* testCaseConstantCloserMarker */', ], - 'switch case, body in curlies declares enum' => [ + 'switch case, body in curlies declares enum' => [ 'testMarker' => '/* testCaseInSwitchWhenCreatingEnumInSwitch1 */', 'expectedTokens' => [ 'scope_opener' => T_OPEN_CURLY_BRACKET, @@ -186,7 +186,7 @@ public static function dataNotEnumCases() ], 'testCloserMarker' => '/* testCaseInSwitchWhenCreatingEnumInSwitch1CloserMarker */', ], - 'switch case, body after semicolon declares enum' => [ + 'switch case, body after semicolon declares enum' => [ 'testMarker' => '/* testCaseInSwitchWhenCreatingEnumInSwitch2 */', 'expectedTokens' => [ 'scope_opener' => T_SEMICOLON, @@ -194,13 +194,20 @@ public static function dataNotEnumCases() ], 'testCloserMarker' => '/* testCaseInSwitchWhenCreatingEnumInSwitch2CloserMarker */', ], - 'switch case, shared closer with switch' => [ + 'switch case, shared closer with switch' => [ 'testMarker' => '/* testSwitchCaseScopeCloserSharedWithSwitch */', 'expectedTokens' => [ 'scope_opener' => T_COLON, 'scope_closer' => T_ENDSWITCH, ], ], + 'switch case, nested inline if/elseif/else with and without braces' => [ + 'testMarker' => '/* testSwitchCaseNestedIfWithAndWithoutBraces */', + 'expectedTokens' => [ + 'scope_opener' => T_COLON, + 'scope_closer' => T_BREAK, + ], + ], ]; }//end dataNotEnumCases() From 105b4bec79443173d1a10a598614b1537cef42f7 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Mon, 12 Aug 2024 17:16:12 -0300 Subject: [PATCH 7/7] Tests/Tokenizer: test related to setting the scope for T_CASE This commit copies a sniff test from InlineControlStructureUnitTest.php to the Tokenizer::recurseScopeMap() tests for the `case` keyword. The copied test was added in 65ef053 before the Tokenizer tests were created. It ensures that the scope for the `T_CASE` token is correctly set when there is an inline control structure inside it with more than three lines. The original sniff test was modified to use `T_FOR` instead of `T_SWITCH`, but its purpose was not altered. The test is about adding braces to an `if` that returns a nested function call. --- .../InlineControlStructureUnitTest.1.inc | 20 +++++++++--------- ...InlineControlStructureUnitTest.1.inc.fixed | 21 ++++++++++--------- .../InlineControlStructureUnitTest.php | 3 ++- ...curseScopeMapCaseKeywordConditionsTest.inc | 13 ++++++++++++ ...curseScopeMapCaseKeywordConditionsTest.php | 7 +++++++ 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc index c7b2a939b6..ada26fb7ff 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc @@ -201,16 +201,16 @@ if (true) catch(Exception $e) { } -switch ($num) { - case 0: - if (1 > $num) - return bar( - baz( - "foobarbaz" - ) - ); - break; -} +for ($i = 0; $i <= 4; $i++) + if ($i % 2) + return bar( + baz( + "foobarbaz" + ) + ); + + + do { $i++; diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed index c6099f4a89..53c6f0952c 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed @@ -230,18 +230,19 @@ if (true) { } } -switch ($num) { - case 0: - if (1 > $num) { - return bar( - baz( - "foobarbaz" - ) - ); - } - break; +for ($i = 0; $i <= 4; $i++) { + if ($i % 2) { + return bar( + baz( + "foobarbaz" + ) + ); + } } + + + do { $i++; } diff --git a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php index 19c78e0f96..22eeb075cc 100644 --- a/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php +++ b/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php @@ -70,7 +70,8 @@ public function getErrorList($testFile='') 191 => 1, 195 => 1, 198 => 1, - 206 => 1, + 204 => 1, + 205 => 1, 222 => 1, 232 => 1, 235 => 1, diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc index 6c71d80db0..8df21a6c35 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc @@ -117,3 +117,16 @@ switch ($type) { } break; } + +// Test for https://github.com/squizlabs/PHP_CodeSniffer/issues/1590 +switch ($num) { + /* testSwitchCaseNestedInlineIfWithMoreThanThreeLines */ + case 0: + if (1 > $num) + return bar( + baz( + "foobarbaz" + ) + ); + break; +} diff --git a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php index 8b651c6d43..a4f3c3f089 100644 --- a/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php +++ b/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php @@ -208,6 +208,13 @@ public static function dataNotEnumCases() 'scope_closer' => T_BREAK, ], ], + 'switch case, nested inline if' => [ + 'testMarker' => '/* testSwitchCaseNestedInlineIfWithMoreThanThreeLines */', + 'expectedTokens' => [ + 'scope_opener' => T_COLON, + 'scope_closer' => T_BREAK, + ], + ], ]; }//end dataNotEnumCases()