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

Breadcrumb

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

function File::findStartOfStatement

Returns the position of the first non-whitespace token in a statement.

Parameters

int $start The position to start searching from in the token stack.:

int|string|array $ignore Token types that should not be considered stop points.:

Return value

int

File

vendor/squizlabs/php_codesniffer/src/Files/File.php, line 2410

Class

File

Namespace

PHP_CodeSniffer\Files

Code

public function findStartOfStatement($start, $ignore = null) {
    $startTokens = Tokens::$blockOpeners;
    $startTokens[T_OPEN_SHORT_ARRAY] = true;
    $startTokens[T_OPEN_TAG] = true;
    $startTokens[T_OPEN_TAG_WITH_ECHO] = true;
    $endTokens = [
        T_CLOSE_TAG => true,
        T_COLON => true,
        T_COMMA => true,
        T_DOUBLE_ARROW => true,
        T_MATCH_ARROW => true,
        T_SEMICOLON => true,
    ];
    if ($ignore !== null) {
        $ignore = (array) $ignore;
        foreach ($ignore as $code) {
            if (isset($startTokens[$code]) === true) {
                unset($startTokens[$code]);
            }
            if (isset($endTokens[$code]) === true) {
                unset($endTokens[$code]);
            }
        }
    }
    // If the start token is inside the case part of a match expression,
    // find the start of the condition. If it's in the statement part, find
    // the token that comes after the match arrow.
    if (empty($this->tokens[$start]['conditions']) === false) {
        $conditions = $this->tokens[$start]['conditions'];
        $lastConditionOwner = end($conditions);
        $matchExpression = key($conditions);
        if ($lastConditionOwner === T_MATCH && (empty($this->tokens[$matchExpression]['nested_parenthesis']) === true && empty($this->tokens[$start]['nested_parenthesis']) === true || empty($this->tokens[$matchExpression]['nested_parenthesis']) === false && empty($this->tokens[$start]['nested_parenthesis']) === false && $this->tokens[$matchExpression]['nested_parenthesis'] === $this->tokens[$start]['nested_parenthesis'])) {
            // Walk back to the previous match arrow (if it exists).
            $lastComma = null;
            $inNestedExpression = false;
            for ($prevMatch = $start; $prevMatch > $this->tokens[$matchExpression]['scope_opener']; $prevMatch--) {
                if ($prevMatch !== $start && $this->tokens[$prevMatch]['code'] === T_MATCH_ARROW) {
                    break;
                }
                if ($prevMatch !== $start && $this->tokens[$prevMatch]['code'] === T_COMMA) {
                    $lastComma = $prevMatch;
                    continue;
                }
                // Skip nested statements.
                if (isset($this->tokens[$prevMatch]['bracket_opener']) === true && $prevMatch === $this->tokens[$prevMatch]['bracket_closer']) {
                    $prevMatch = $this->tokens[$prevMatch]['bracket_opener'];
                    continue;
                }
                if (isset($this->tokens[$prevMatch]['parenthesis_opener']) === true && $prevMatch === $this->tokens[$prevMatch]['parenthesis_closer']) {
                    $prevMatch = $this->tokens[$prevMatch]['parenthesis_opener'];
                    continue;
                }
                // Stop if we're _within_ a nested short array statement, which may contain comma's too.
                // No need to deal with parentheses, those are handled above via the `nested_parenthesis` checks.
                if (isset($this->tokens[$prevMatch]['bracket_opener']) === true && $this->tokens[$prevMatch]['bracket_closer'] > $start) {
                    $inNestedExpression = true;
                    break;
                }
            }
            
            //end for
            if ($inNestedExpression === false) {
                // $prevMatch will now either be the scope opener or a match arrow.
                // If it is the scope opener, go the first non-empty token after. $start will have been part of the first condition.
                if ($prevMatch <= $this->tokens[$matchExpression]['scope_opener']) {
                    // We're before the arrow in the first case.
                    $next = $this->findNext(Tokens::$emptyTokens, $this->tokens[$matchExpression]['scope_opener'] + 1, null, true);
                    if ($next === false) {
                        // Shouldn't be possible.
                        return $start;
                    }
                    return $next;
                }
                // Okay, so we found a match arrow.
                // If $start was part of the "next" condition, the last comma will be set.
                // Otherwise, $start must have been part of a return expression.
                if (isset($lastComma) === true && $lastComma > $prevMatch) {
                    $prevMatch = $lastComma;
                }
                // In both cases, go to the first non-empty token after.
                $next = $this->findNext(Tokens::$emptyTokens, $prevMatch + 1, null, true);
                if ($next === false) {
                    // Shouldn't be possible.
                    return $start;
                }
                return $next;
            }
            
            //end if
        }
        
        //end if
    }
    
    //end if
    $lastNotEmpty = $start;
    // If we are starting at a token that ends a scope block, skip to
    // the start and continue from there.
    // If we are starting at a token that ends a statement, skip this
    // token so we find the true start of the statement.
    while (isset($endTokens[$this->tokens[$start]['code']]) === true || isset($this->tokens[$start]['scope_condition']) === true && $start === $this->tokens[$start]['scope_closer']) {
        if (isset($this->tokens[$start]['scope_condition']) === true) {
            $start = $this->tokens[$start]['scope_condition'];
        }
        else {
            $start--;
        }
    }
    for ($i = $start; $i >= 0; $i--) {
        if (isset($startTokens[$this->tokens[$i]['code']]) === true || isset($endTokens[$this->tokens[$i]['code']]) === true) {
            // Found the end of the previous statement.
            return $lastNotEmpty;
        }
        if (isset($this->tokens[$i]['scope_opener']) === true && $i === $this->tokens[$i]['scope_closer'] && $this->tokens[$i]['code'] !== T_CLOSE_PARENTHESIS && $this->tokens[$i]['code'] !== T_END_NOWDOC && $this->tokens[$i]['code'] !== T_END_HEREDOC && $this->tokens[$i]['code'] !== T_BREAK && $this->tokens[$i]['code'] !== T_RETURN && $this->tokens[$i]['code'] !== T_CONTINUE && $this->tokens[$i]['code'] !== T_THROW && $this->tokens[$i]['code'] !== T_EXIT) {
            // Found the end of the previous scope block.
            return $lastNotEmpty;
        }
        // Skip nested statements.
        if (isset($this->tokens[$i]['bracket_opener']) === true && $i === $this->tokens[$i]['bracket_closer']) {
            $i = $this->tokens[$i]['bracket_opener'];
        }
        else {
            if (isset($this->tokens[$i]['parenthesis_opener']) === true && $i === $this->tokens[$i]['parenthesis_closer']) {
                $i = $this->tokens[$i]['parenthesis_opener'];
            }
            else {
                if ($this->tokens[$i]['code'] === T_CLOSE_USE_GROUP) {
                    $start = $this->findPrevious(T_OPEN_USE_GROUP, $i - 1);
                    if ($start !== false) {
                        $i = $start;
                    }
                }
            }
        }
        
        //end if
        if (isset(Tokens::$emptyTokens[$this->tokens[$i]['code']]) === false) {
            $lastNotEmpty = $i;
        }
    }
    
    //end for
    return 0;
}

API Navigation

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