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

Breadcrumb

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

function AbstractPatternSniff::processPattern

Processes the pattern and verifies the code at $stackPtr.

Parameters

array $patternInfo Information about the pattern used: for checking, which includes are parsed token representation of the pattern.

\PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the: token occurred.

int $stackPtr The position in the tokens stack where: the listening token type was found.

Return value

array|false

1 call to AbstractPatternSniff::processPattern()
AbstractPatternSniff::process in vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php
Processes the test.

File

vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php, line 255

Class

AbstractPatternSniff

Namespace

PHP_CodeSniffer\Sniffs

Code

protected function processPattern($patternInfo, File $phpcsFile, $stackPtr) {
    $tokens = $phpcsFile->getTokens();
    $pattern = $patternInfo['pattern'];
    $patternCode = $patternInfo['pattern_code'];
    $errors = [];
    $found = '';
    $ignoreTokens = [
        T_WHITESPACE => T_WHITESPACE,
    ];
    if ($this->ignoreComments === true) {
        $ignoreTokens += Tokens::$commentTokens;
    }
    $origStackPtr = $stackPtr;
    $hasError = false;
    if ($patternInfo['listen_pos'] > 0) {
        $stackPtr--;
        for ($i = $patternInfo['listen_pos'] - 1; $i >= 0; $i--) {
            if ($pattern[$i]['type'] === 'token') {
                if ($pattern[$i]['token'] === T_WHITESPACE) {
                    if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
                        $found = $tokens[$stackPtr]['content'] . $found;
                    }
                    // Only check the size of the whitespace if this is not
                    // the first token. We don't care about the size of
                    // leading whitespace, just that there is some.
                    if ($i !== 0) {
                        if ($tokens[$stackPtr]['content'] !== $pattern[$i]['value']) {
                            $hasError = true;
                        }
                    }
                }
                else {
                    // Check to see if this important token is the same as the
                    // previous important token in the pattern. If it is not,
                    // then the pattern cannot be for this piece of code.
                    $prev = $phpcsFile->findPrevious($ignoreTokens, $stackPtr, null, true);
                    if ($prev === false || $tokens[$prev]['code'] !== $pattern[$i]['token']) {
                        return false;
                    }
                    // If we skipped past some whitespace tokens, then add them
                    // to the found string.
                    $tokenContent = $phpcsFile->getTokensAsString($prev + 1, $stackPtr - $prev - 1);
                    $found = $tokens[$prev]['content'] . $tokenContent . $found;
                    if (isset($pattern[$i - 1]) === true && $pattern[$i - 1]['type'] === 'skip') {
                        $stackPtr = $prev;
                    }
                    else {
                        $stackPtr = $prev - 1;
                    }
                }
                
                //end if
            }
            else {
                if ($pattern[$i]['type'] === 'skip') {
                    // Skip to next piece of relevant code.
                    if ($pattern[$i]['to'] === 'parenthesis_closer') {
                        $to = 'parenthesis_opener';
                    }
                    else {
                        $to = 'scope_opener';
                    }
                    // Find the previous opener.
                    $next = $phpcsFile->findPrevious($ignoreTokens, $stackPtr, null, true);
                    if ($next === false || isset($tokens[$next][$to]) === false) {
                        // If there was not opener, then we must be
                        // using the wrong pattern.
                        return false;
                    }
                    if ($to === 'parenthesis_opener') {
                        $found = '{' . $found;
                    }
                    else {
                        $found = '(' . $found;
                    }
                    $found = '...' . $found;
                    // Skip to the opening token.
                    $stackPtr = $tokens[$next][$to] - 1;
                }
                else {
                    if ($pattern[$i]['type'] === 'string') {
                        $found = 'abc';
                    }
                    else {
                        if ($pattern[$i]['type'] === 'newline') {
                            if ($this->ignoreComments === true && isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) {
                                $startComment = $phpcsFile->findPrevious(Tokens::$commentTokens, $stackPtr - 1, null, true);
                                if ($tokens[$startComment]['line'] !== $tokens[$startComment + 1]['line']) {
                                    $startComment++;
                                }
                                $tokenContent = $phpcsFile->getTokensAsString($startComment, $stackPtr - $startComment + 1);
                                $found = $tokenContent . $found;
                                $stackPtr = $startComment - 1;
                            }
                            if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
                                if ($tokens[$stackPtr]['content'] !== $phpcsFile->eolChar) {
                                    $found = $tokens[$stackPtr]['content'] . $found;
                                    // This may just be an indent that comes after a newline
                                    // so check the token before to make sure. If it is a newline, we
                                    // can ignore the error here.
                                    if ($tokens[$stackPtr - 1]['content'] !== $phpcsFile->eolChar && ($this->ignoreComments === true && isset(Tokens::$commentTokens[$tokens[$stackPtr - 1]['code']]) === false)) {
                                        $hasError = true;
                                    }
                                    else {
                                        $stackPtr--;
                                    }
                                }
                                else {
                                    $found = 'EOL' . $found;
                                }
                            }
                            else {
                                $found = $tokens[$stackPtr]['content'] . $found;
                                $hasError = true;
                            }
                            
                            //end if
                            if ($hasError === false && $pattern[$i - 1]['type'] !== 'newline') {
                                // Make sure they only have 1 newline.
                                $prev = $phpcsFile->findPrevious($ignoreTokens, $stackPtr - 1, null, true);
                                if ($prev !== false && $tokens[$prev]['line'] !== $tokens[$stackPtr]['line']) {
                                    $hasError = true;
                                }
                            }
                        }
                    }
                }
            }
            
            //end if
        }
        
        //end for
    }
    
    //end if
    $stackPtr = $origStackPtr;
    $lastAddedStackPtr = null;
    $patternLen = count($pattern);
    if ($stackPtr + $patternLen - $patternInfo['listen_pos'] > $phpcsFile->numTokens) {
        // Pattern can never match as there are not enough tokens left in the file.
        return false;
    }
    for ($i = $patternInfo['listen_pos']; $i < $patternLen; $i++) {
        if (isset($tokens[$stackPtr]) === false) {
            break;
        }
        if ($pattern[$i]['type'] === 'token') {
            if ($pattern[$i]['token'] === T_WHITESPACE) {
                if ($this->ignoreComments === true) {
                    // If we are ignoring comments, check to see if this current
                    // token is a comment. If so skip it.
                    if (isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) {
                        continue;
                    }
                    // If the next token is a comment, the we need to skip the
                    // current token as we should allow a space before a
                    // comment for readability.
                    if (isset($tokens[$stackPtr + 1]) === true && isset(Tokens::$commentTokens[$tokens[$stackPtr + 1]['code']]) === true) {
                        continue;
                    }
                }
                $tokenContent = '';
                if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
                    if (isset($pattern[$i + 1]) === false) {
                        // This is the last token in the pattern, so just compare
                        // the next token of content.
                        $tokenContent = $tokens[$stackPtr]['content'];
                    }
                    else {
                        // Get all the whitespace to the next token.
                        $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr, null, true);
                        $tokenContent = $phpcsFile->getTokensAsString($stackPtr, $next - $stackPtr);
                        $lastAddedStackPtr = $stackPtr;
                        $stackPtr = $next;
                    }
                    
                    //end if
                    if ($stackPtr !== $lastAddedStackPtr) {
                        $found .= $tokenContent;
                    }
                }
                else {
                    if ($stackPtr !== $lastAddedStackPtr) {
                        $found .= $tokens[$stackPtr]['content'];
                        $lastAddedStackPtr = $stackPtr;
                    }
                }
                
                //end if
                if (isset($pattern[$i + 1]) === true && $pattern[$i + 1]['type'] === 'skip') {
                    // The next token is a skip token, so we just need to make
                    // sure the whitespace we found has *at least* the
                    // whitespace required.
                    if (strpos($tokenContent, $pattern[$i]['value']) !== 0) {
                        $hasError = true;
                    }
                }
                else {
                    if ($tokenContent !== $pattern[$i]['value']) {
                        $hasError = true;
                    }
                }
            }
            else {
                // Check to see if this important token is the same as the
                // next important token in the pattern. If it is not, then
                // the pattern cannot be for this piece of code.
                $next = $phpcsFile->findNext($ignoreTokens, $stackPtr, null, true);
                if ($next === false || $tokens[$next]['code'] !== $pattern[$i]['token']) {
                    // The next important token did not match the pattern.
                    return false;
                }
                if ($lastAddedStackPtr !== null) {
                    if (($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) && isset($tokens[$next]['scope_condition']) === true && $tokens[$next]['scope_condition'] > $lastAddedStackPtr) {
                        // This is a brace, but the owner of it is after the current
                        // token, which means it does not belong to any token in
                        // our pattern. This means the pattern is not for us.
                        return false;
                    }
                    if (($tokens[$next]['code'] === T_OPEN_PARENTHESIS || $tokens[$next]['code'] === T_CLOSE_PARENTHESIS) && isset($tokens[$next]['parenthesis_owner']) === true && $tokens[$next]['parenthesis_owner'] > $lastAddedStackPtr) {
                        // This is a bracket, but the owner of it is after the current
                        // token, which means it does not belong to any token in
                        // our pattern. This means the pattern is not for us.
                        return false;
                    }
                }
                
                //end if
                // If we skipped past some whitespace tokens, then add them
                // to the found string.
                if ($next - $stackPtr > 0) {
                    $hasComment = false;
                    for ($j = $stackPtr; $j < $next; $j++) {
                        $found .= $tokens[$j]['content'];
                        if (isset(Tokens::$commentTokens[$tokens[$j]['code']]) === true) {
                            $hasComment = true;
                        }
                    }
                    // If we are not ignoring comments, this additional
                    // whitespace or comment is not allowed. If we are
                    // ignoring comments, there needs to be at least one
                    // comment for this to be allowed.
                    if ($this->ignoreComments === false || $this->ignoreComments === true && $hasComment === false) {
                        $hasError = true;
                    }
                    // Even when ignoring comments, we are not allowed to include
                    // newlines without the pattern specifying them, so
                    // everything should be on the same line.
                    if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) {
                        $hasError = true;
                    }
                }
                
                //end if
                if ($next !== $lastAddedStackPtr) {
                    $found .= $tokens[$next]['content'];
                    $lastAddedStackPtr = $next;
                }
                if (isset($pattern[$i + 1]) === true && $pattern[$i + 1]['type'] === 'skip') {
                    $stackPtr = $next;
                }
                else {
                    $stackPtr = $next + 1;
                }
            }
            
            //end if
        }
        else {
            if ($pattern[$i]['type'] === 'skip') {
                if ($pattern[$i]['to'] === 'unknown') {
                    $next = $phpcsFile->findNext($pattern[$i + 1]['token'], $stackPtr);
                    if ($next === false) {
                        // Couldn't find the next token, so we must
                        // be using the wrong pattern.
                        return false;
                    }
                    $found .= '...';
                    $stackPtr = $next;
                }
                else {
                    // Find the previous opener.
                    $next = $phpcsFile->findPrevious(Tokens::$blockOpeners, $stackPtr);
                    if ($next === false || isset($tokens[$next][$pattern[$i]['to']]) === false) {
                        // If there was not opener, then we must
                        // be using the wrong pattern.
                        return false;
                    }
                    $found .= '...';
                    if ($pattern[$i]['to'] === 'parenthesis_closer') {
                        $found .= ')';
                    }
                    else {
                        $found .= '}';
                    }
                    // Skip to the closing token.
                    $stackPtr = $tokens[$next][$pattern[$i]['to']] + 1;
                }
                
                //end if
            }
            else {
                if ($pattern[$i]['type'] === 'string') {
                    if ($tokens[$stackPtr]['code'] !== T_STRING) {
                        $hasError = true;
                    }
                    if ($stackPtr !== $lastAddedStackPtr) {
                        $found .= 'abc';
                        $lastAddedStackPtr = $stackPtr;
                    }
                    $stackPtr++;
                }
                else {
                    if ($pattern[$i]['type'] === 'newline') {
                        // Find the next token that contains a newline character.
                        $newline = 0;
                        for ($j = $stackPtr; $j < $phpcsFile->numTokens; $j++) {
                            if (strpos($tokens[$j]['content'], $phpcsFile->eolChar) !== false) {
                                $newline = $j;
                                break;
                            }
                        }
                        if ($newline === 0) {
                            // We didn't find a newline character in the rest of the file.
                            $next = $phpcsFile->numTokens - 1;
                            $hasError = true;
                        }
                        else {
                            if ($this->ignoreComments === false) {
                                // The newline character cannot be part of a comment.
                                if (isset(Tokens::$commentTokens[$tokens[$newline]['code']]) === true) {
                                    $hasError = true;
                                }
                            }
                            if ($newline === $stackPtr) {
                                $next = $stackPtr + 1;
                            }
                            else {
                                // Check that there were no significant tokens that we
                                // skipped over to find our newline character.
                                $next = $phpcsFile->findNext($ignoreTokens, $stackPtr, null, true);
                                if ($next < $newline) {
                                    // We skipped a non-ignored token.
                                    $hasError = true;
                                }
                                else {
                                    $next = $newline + 1;
                                }
                            }
                        }
                        
                        //end if
                        if ($stackPtr !== $lastAddedStackPtr) {
                            $found .= $phpcsFile->getTokensAsString($stackPtr, $next - $stackPtr);
                            $lastAddedStackPtr = $next - 1;
                        }
                        $stackPtr = $next;
                    }
                }
            }
        }
        
        //end if
    }
    
    //end for
    if ($hasError === true) {
        $error = $this->prepareError($found, $patternCode);
        $errors[$origStackPtr] = $error;
    }
    return $errors;
}

API Navigation

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