From 2cf3c9a693fccd6ca3d22c2f9f90dfc04a47ba2d Mon Sep 17 00:00:00 2001 From: Takshil Kunadia Date: Sun, 8 Sep 2024 21:38:51 +0530 Subject: [PATCH 1/2] feat: Add rule to allow only valid `continues` inside case --- .../PHP/PreferBreakInsideSwitchOnlySniff.php | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Travelopia-WordPress/Sniffs/PHP/PreferBreakInsideSwitchOnlySniff.php diff --git a/Travelopia-WordPress/Sniffs/PHP/PreferBreakInsideSwitchOnlySniff.php b/Travelopia-WordPress/Sniffs/PHP/PreferBreakInsideSwitchOnlySniff.php new file mode 100644 index 0000000..c382266 --- /dev/null +++ b/Travelopia-WordPress/Sniffs/PHP/PreferBreakInsideSwitchOnlySniff.php @@ -0,0 +1,66 @@ +getTokens(); + + // Search for continue inside the case. + $continuePtr = $phpcsFile->findNext( T_CONTINUE, $stackPtr, $tokens[ $stackPtr ]['scope_closer'] + 1 ); + + // run a loop for all continue statements inside the case + while ( false !== $continuePtr ) { + // Search for the loop in which the continue is present. + $loopStartPtr = $phpcsFile->findPrevious( [ T_WHILE, T_FOR, T_FOREACH, T_DO ], $continuePtr, $stackPtr ); + $loopEndPtr = $tokens[ $loopStartPtr ]['scope_closer']; + + // If the continue is inside a loop, ignore it. + if ( $loopStartPtr && $continuePtr > $loopStartPtr && $continuePtr < $loopEndPtr ) { + $continuePtr = $phpcsFile->findNext( T_CONTINUE, $continuePtr + 1, $tokens[ $stackPtr ]['scope_closer'] + 1 ); + continue; + } + + // Add an error. + $phpcsFile->addWarningOnLine( + 'Use `break` instead of `continue` inside a switch case.', + $tokens[ $continuePtr ]['line'], + 'UseBreakInsideSwitch' + ); + + // Search for continue inside the case. + $continuePtr = $phpcsFile->findNext( T_CONTINUE, $continuePtr + 1, $tokens[ $stackPtr ]['scope_closer'] + 1 ); + } + } + +} From 85af33fc4540336e315fdb8bcb5f99acd332fc94 Mon Sep 17 00:00:00 2001 From: Takshil Kunadia Date: Sun, 8 Sep 2024 21:43:10 +0530 Subject: [PATCH 2/2] chore: refactor processing --- .../PHP/PreferBreakInsideSwitchOnlySniff.php | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/Travelopia-WordPress/Sniffs/PHP/PreferBreakInsideSwitchOnlySniff.php b/Travelopia-WordPress/Sniffs/PHP/PreferBreakInsideSwitchOnlySniff.php index c382266..20f1fec 100644 --- a/Travelopia-WordPress/Sniffs/PHP/PreferBreakInsideSwitchOnlySniff.php +++ b/Travelopia-WordPress/Sniffs/PHP/PreferBreakInsideSwitchOnlySniff.php @@ -36,31 +36,37 @@ public function process( File $phpcsFile, $stackPtr ): void { // Get tokens. $tokens = $phpcsFile->getTokens(); + // Set Start and End pointers. + $searchStartPtr = $stackPtr + 1; + $caseEndPtr = $tokens[ $stackPtr ]['scope_closer']; + // Search for continue inside the case. - $continuePtr = $phpcsFile->findNext( T_CONTINUE, $stackPtr, $tokens[ $stackPtr ]['scope_closer'] + 1 ); + do { + // Find the next continue. + $continuePtr = $phpcsFile->findNext( T_CONTINUE, $searchStartPtr, $caseEndPtr + 1 ); - // run a loop for all continue statements inside the case - while ( false !== $continuePtr ) { - // Search for the loop in which the continue is present. - $loopStartPtr = $phpcsFile->findPrevious( [ T_WHILE, T_FOR, T_FOREACH, T_DO ], $continuePtr, $stackPtr ); - $loopEndPtr = $tokens[ $loopStartPtr ]['scope_closer']; + // If continue is inside a loop, ignore it. + if ( false !== $continuePtr ) { + // Search for the loop in which the continue is present. + $loopStartPtr = $phpcsFile->findPrevious( [ T_WHILE, T_FOR, T_FOREACH, T_DO ], $continuePtr, $stackPtr ); + $loopEndPtr = $tokens[ $loopStartPtr ]['scope_closer']; - // If the continue is inside a loop, ignore it. - if ( $loopStartPtr && $continuePtr > $loopStartPtr && $continuePtr < $loopEndPtr ) { - $continuePtr = $phpcsFile->findNext( T_CONTINUE, $continuePtr + 1, $tokens[ $stackPtr ]['scope_closer'] + 1 ); - continue; - } + // If the continue is inside a loop, ignore it. + if ( $loopStartPtr && $continuePtr > $loopStartPtr && $continuePtr < $loopEndPtr ) { + $searchStartPtr = $loopEndPtr + 1; + continue; + } - // Add an error. - $phpcsFile->addWarningOnLine( - 'Use `break` instead of `continue` inside a switch case.', - $tokens[ $continuePtr ]['line'], - 'UseBreakInsideSwitch' - ); + // Display warning. + $phpcsFile->addWarningOnLine( + 'Use `break` or `continue x` where x is the nesting level to break out of the switch.', + $tokens[ $continuePtr ]['line'], + 'UseBreakInsideSwitch' + ); - // Search for continue inside the case. - $continuePtr = $phpcsFile->findNext( T_CONTINUE, $continuePtr + 1, $tokens[ $stackPtr ]['scope_closer'] + 1 ); - } + // Set the search pointer to the next token. + $searchStartPtr = $continuePtr + 1; + } + } while ( false !== $continuePtr ); } - }