Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. SwitchDeclarationSniff.php

function SwitchDeclarationSniff::findNestedTerminator

Returns the position of the nested terminating statement.

Returns false if no terminating statement was found.

Parameters

\PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.:

int $stackPtr The position to start looking at.:

int $end The position to stop looking at.:

Return value

int|bool

1 call to SwitchDeclarationSniff::findNestedTerminator()
SwitchDeclarationSniff::process in vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php
Processes this test, when one of its tokens is encountered.

File

vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php, line 246

Class

SwitchDeclarationSniff

Namespace

PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures

Code

private function findNestedTerminator($phpcsFile, $stackPtr, $end) {
    $tokens = $phpcsFile->getTokens();
    $lastToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, $end - 1, $stackPtr, true);
    if ($lastToken === false) {
        return false;
    }
    if ($tokens[$lastToken]['code'] === T_CLOSE_CURLY_BRACKET) {
        // We found a closing curly bracket and want to check if its block
        // belongs to a SWITCH, IF, ELSEIF or ELSE, TRY, CATCH OR FINALLY clause.
        // If yes, we continue searching for a terminating statement within that
        // block. Note that we have to make sure that every block of
        // the entire if/else/switch statement has a terminating statement.
        // For a try/catch/finally statement, either the finally block has
        // to have a terminating statement or every try/catch block has to have one.
        $currentCloser = $lastToken;
        $hasElseBlock = false;
        $hasCatchWithoutTerminator = false;
        do {
            $scopeOpener = $tokens[$currentCloser]['scope_opener'];
            $scopeCloser = $tokens[$currentCloser]['scope_closer'];
            $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, $scopeOpener - 1, $stackPtr, true);
            if ($prevToken === false) {
                return false;
            }
            // SWITCH, IF, ELSEIF, CATCH clauses possess a condition we have to account for.
            if ($tokens[$prevToken]['code'] === T_CLOSE_PARENTHESIS) {
                $prevToken = $tokens[$prevToken]['parenthesis_owner'];
            }
            if ($tokens[$prevToken]['code'] === T_IF) {
                // If we have not encountered an ELSE clause by now, we cannot
                // be sure that the whole statement terminates in every case.
                if ($hasElseBlock === false) {
                    return false;
                }
                return $this->findNestedTerminator($phpcsFile, $scopeOpener + 1, $scopeCloser);
            }
            else {
                if ($tokens[$prevToken]['code'] === T_ELSEIF || $tokens[$prevToken]['code'] === T_ELSE) {
                    // If we find a terminating statement within this block,
                    // we continue with the previous ELSEIF or IF clause.
                    $hasTerminator = $this->findNestedTerminator($phpcsFile, $scopeOpener + 1, $scopeCloser);
                    if ($hasTerminator === false) {
                        return false;
                    }
                    $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prevToken - 1, $stackPtr, true);
                    if ($tokens[$prevToken]['code'] === T_ELSE) {
                        $hasElseBlock = true;
                    }
                }
                else {
                    if ($tokens[$prevToken]['code'] === T_FINALLY) {
                        // If we find a terminating statement within this block,
                        // the whole try/catch/finally statement is covered.
                        $hasTerminator = $this->findNestedTerminator($phpcsFile, $scopeOpener + 1, $scopeCloser);
                        if ($hasTerminator !== false) {
                            return $hasTerminator;
                        }
                        // Otherwise, we continue with the previous TRY or CATCH clause.
                        $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prevToken - 1, $stackPtr, true);
                    }
                    else {
                        if ($tokens[$prevToken]['code'] === T_TRY) {
                            // If we've seen CATCH blocks without terminator statement and
                            // have not seen a FINALLY *with* a terminator statement, we
                            // don't even need to bother checking the TRY.
                            if ($hasCatchWithoutTerminator === true) {
                                return false;
                            }
                            return $this->findNestedTerminator($phpcsFile, $scopeOpener + 1, $scopeCloser);
                        }
                        else {
                            if ($tokens[$prevToken]['code'] === T_CATCH) {
                                // Keep track of seen catch statements without terminating statement,
                                // but don't bow out yet as there may still be a FINALLY clause
                                // with a terminating statement before the CATCH.
                                $hasTerminator = $this->findNestedTerminator($phpcsFile, $scopeOpener + 1, $scopeCloser);
                                if ($hasTerminator === false) {
                                    $hasCatchWithoutTerminator = true;
                                }
                                $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prevToken - 1, $stackPtr, true);
                            }
                            else {
                                if ($tokens[$prevToken]['code'] === T_SWITCH) {
                                    $hasDefaultBlock = false;
                                    $endOfSwitch = $tokens[$prevToken]['scope_closer'];
                                    $nextCase = $prevToken;
                                    // We look for a terminating statement within every blocks.
                                    while (($nextCase = $this->findNextCase($phpcsFile, $nextCase + 1, $endOfSwitch)) !== false) {
                                        if ($tokens[$nextCase]['code'] === T_DEFAULT) {
                                            $hasDefaultBlock = true;
                                        }
                                        $opener = $tokens[$nextCase]['scope_opener'];
                                        $nextCode = $phpcsFile->findNext(Tokens::$emptyTokens, $opener + 1, $endOfSwitch, true);
                                        if ($tokens[$nextCode]['code'] === T_CASE || $tokens[$nextCode]['code'] === T_DEFAULT) {
                                            // This case statement has no content, so skip it.
                                            continue;
                                        }
                                        $endOfCase = $this->findNextCase($phpcsFile, $opener + 1, $endOfSwitch);
                                        if ($endOfCase === false) {
                                            $endOfCase = $endOfSwitch;
                                        }
                                        $hasTerminator = $this->findNestedTerminator($phpcsFile, $opener + 1, $endOfCase);
                                        if ($hasTerminator === false) {
                                            return false;
                                        }
                                    }
                                    
                                    //end while
                                    // If we have not encountered a DEFAULT block by now, we cannot
                                    // be sure that the whole statement terminates in every case.
                                    if ($hasDefaultBlock === false) {
                                        return false;
                                    }
                                    return $hasTerminator;
                                }
                                else {
                                    return false;
                                }
                            }
                        }
                    }
                }
            }
            
            //end if
        } while ($currentCloser !== false && $tokens[$currentCloser]['code'] === T_CLOSE_CURLY_BRACKET);
        return true;
    }
    else {
        if ($tokens[$lastToken]['code'] === T_SEMICOLON) {
            // We found the last statement of the CASE. Now we want to
            // check whether it is a terminating one.
            $terminators = [
                T_RETURN => T_RETURN,
                T_BREAK => T_BREAK,
                T_CONTINUE => T_CONTINUE,
                T_THROW => T_THROW,
                T_EXIT => T_EXIT,
            ];
            $terminator = $phpcsFile->findStartOfStatement($lastToken - 1);
            if (isset($terminators[$tokens[$terminator]['code']]) === true) {
                return $terminator;
            }
        }
    }
    
    //end if
    return false;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal