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

Breadcrumb

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

function Tokenizer::createPositionMap

Sets token position information.

Can also convert tabs into spaces. Each tab can represent between 1 and $width spaces, so this cannot be a straight string replace.

Return value

void

1 call to Tokenizer::createPositionMap()
Tokenizer::__construct in vendor/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php
Initialise and run the tokenizer.

File

vendor/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php, line 171

Class

Tokenizer

Namespace

PHP_CodeSniffer\Tokenizers

Code

private function createPositionMap() {
    $currColumn = 1;
    $lineNumber = 1;
    $eolLen = strlen($this->eolChar);
    $ignoring = null;
    $inTests = defined('PHP_CODESNIFFER_IN_TESTS');
    $checkEncoding = false;
    if (function_exists('iconv_strlen') === true) {
        $checkEncoding = true;
    }
    $checkAnnotations = $this->config->annotations;
    $encoding = $this->config->encoding;
    $tabWidth = $this->config->tabWidth;
    $tokensWithTabs = [
        T_WHITESPACE => true,
        T_COMMENT => true,
        T_DOC_COMMENT => true,
        T_DOC_COMMENT_WHITESPACE => true,
        T_DOC_COMMENT_STRING => true,
        T_CONSTANT_ENCAPSED_STRING => true,
        T_DOUBLE_QUOTED_STRING => true,
        T_START_HEREDOC => true,
        T_START_NOWDOC => true,
        T_HEREDOC => true,
        T_NOWDOC => true,
        T_END_HEREDOC => true,
        T_END_NOWDOC => true,
        T_INLINE_HTML => true,
        T_YIELD_FROM => true,
    ];
    $this->numTokens = count($this->tokens);
    for ($i = 0; $i < $this->numTokens; $i++) {
        $this->tokens[$i]['line'] = $lineNumber;
        $this->tokens[$i]['column'] = $currColumn;
        if (isset($this->knownLengths[$this->tokens[$i]['code']]) === true) {
            // There are no tabs in the tokens we know the length of.
            $length = $this->knownLengths[$this->tokens[$i]['code']];
            $currColumn += $length;
        }
        else {
            if ($tabWidth === 0 || isset($tokensWithTabs[$this->tokens[$i]['code']]) === false || strpos($this->tokens[$i]['content'], "\t") === false) {
                // There are no tabs in this content, or we aren't replacing them.
                if ($checkEncoding === true) {
                    // Not using the default encoding, so take a bit more care.
                    $oldLevel = error_reporting();
                    error_reporting(0);
                    $length = iconv_strlen($this->tokens[$i]['content'], $encoding);
                    error_reporting($oldLevel);
                    if ($length === false) {
                        // String contained invalid characters, so revert to default.
                        $length = strlen($this->tokens[$i]['content']);
                    }
                }
                else {
                    $length = strlen($this->tokens[$i]['content']);
                }
                $currColumn += $length;
            }
            else {
                $this->replaceTabsInToken($this->tokens[$i]);
                $length = $this->tokens[$i]['length'];
                $currColumn += $length;
            }
        }
        
        //end if
        $this->tokens[$i]['length'] = $length;
        if (isset($this->knownLengths[$this->tokens[$i]['code']]) === false && strpos($this->tokens[$i]['content'], $this->eolChar) !== false) {
            $lineNumber++;
            $currColumn = 1;
            // Newline chars are not counted in the token length.
            $this->tokens[$i]['length'] -= $eolLen;
        }
        if ($this->tokens[$i]['code'] === T_COMMENT || $this->tokens[$i]['code'] === T_DOC_COMMENT_STRING || $this->tokens[$i]['code'] === T_DOC_COMMENT_TAG || $inTests === true && $this->tokens[$i]['code'] === T_INLINE_HTML) {
            $commentText = ltrim($this->tokens[$i]['content'], " \t/*#");
            $commentText = rtrim($commentText, " */\t\r\n");
            $commentTextLower = strtolower($commentText);
            if (strpos($commentText, '@codingStandards') !== false) {
                // If this comment is the only thing on the line, it tells us
                // to ignore the following line. If the line contains other content
                // then we are just ignoring this one single line.
                $ownLine = false;
                if ($i > 0) {
                    for ($prev = $i - 1; $prev >= 0; $prev--) {
                        if ($this->tokens[$prev]['code'] === T_WHITESPACE) {
                            continue;
                        }
                        break;
                    }
                    if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) {
                        $ownLine = true;
                    }
                }
                if ($ignoring === null && strpos($commentText, '@codingStandardsIgnoreStart') !== false) {
                    $ignoring = [
                        '.all' => true,
                    ];
                    if ($ownLine === true) {
                        $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
                    }
                }
                else {
                    if ($ignoring !== null && strpos($commentText, '@codingStandardsIgnoreEnd') !== false) {
                        if ($ownLine === true) {
                            $this->ignoredLines[$this->tokens[$i]['line']] = [
                                '.all' => true,
                            ];
                        }
                        else {
                            $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
                        }
                        $ignoring = null;
                    }
                    else {
                        if ($ignoring === null && strpos($commentText, '@codingStandardsIgnoreLine') !== false) {
                            $ignoring = [
                                '.all' => true,
                            ];
                            if ($ownLine === true) {
                                $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
                                $this->ignoredLines[$this->tokens[$i]['line'] + 1] = $ignoring;
                            }
                            else {
                                $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
                            }
                            $ignoring = null;
                        }
                    }
                }
                
                //end if
            }
            else {
                if (substr($commentTextLower, 0, 6) === 'phpcs:' || substr($commentTextLower, 0, 7) === '@phpcs:') {
                    // If the @phpcs: syntax is being used, strip the @ to make
                    // comparisons easier.
                    if ($commentText[0] === '@') {
                        $commentText = substr($commentText, 1);
                        $commentTextLower = strtolower($commentText);
                    }
                    // If there is a comment on the end, strip it off.
                    $commentStart = strpos($commentTextLower, ' --');
                    if ($commentStart !== false) {
                        $commentText = substr($commentText, 0, $commentStart);
                        $commentTextLower = strtolower($commentText);
                    }
                    // If this comment is the only thing on the line, it tells us
                    // to ignore the following line. If the line contains other content
                    // then we are just ignoring this one single line.
                    $lineHasOtherContent = false;
                    $lineHasOtherTokens = false;
                    if ($i > 0) {
                        for ($prev = $i - 1; $prev > 0; $prev--) {
                            if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) {
                                // Changed lines.
                                break;
                            }
                            if ($this->tokens[$prev]['code'] === T_WHITESPACE || $this->tokens[$prev]['code'] === T_DOC_COMMENT_WHITESPACE || $this->tokens[$prev]['code'] === T_INLINE_HTML && trim($this->tokens[$prev]['content']) === '') {
                                continue;
                            }
                            $lineHasOtherTokens = true;
                            if ($this->tokens[$prev]['code'] === T_OPEN_TAG || $this->tokens[$prev]['code'] === T_DOC_COMMENT_STAR) {
                                continue;
                            }
                            $lineHasOtherContent = true;
                            break;
                        }
                        
                        //end for
                        $changedLines = false;
                        for ($next = $i; $next < $this->numTokens; $next++) {
                            if ($changedLines === true) {
                                // Changed lines.
                                break;
                            }
                            if (isset($this->knownLengths[$this->tokens[$next]['code']]) === false && strpos($this->tokens[$next]['content'], $this->eolChar) !== false) {
                                // Last token on the current line.
                                $changedLines = true;
                            }
                            if ($next === $i) {
                                continue;
                            }
                            if ($this->tokens[$next]['code'] === T_WHITESPACE || $this->tokens[$next]['code'] === T_DOC_COMMENT_WHITESPACE || $this->tokens[$next]['code'] === T_INLINE_HTML && trim($this->tokens[$next]['content']) === '') {
                                continue;
                            }
                            $lineHasOtherTokens = true;
                            if ($this->tokens[$next]['code'] === T_CLOSE_TAG) {
                                continue;
                            }
                            $lineHasOtherContent = true;
                            break;
                        }
                        
                        //end for
                    }
                    
                    //end if
                    if (substr($commentTextLower, 0, 9) === 'phpcs:set') {
                        // Ignore standards for complete lines that change sniff settings.
                        if ($lineHasOtherTokens === false) {
                            $this->ignoredLines[$this->tokens[$i]['line']] = [
                                '.all' => true,
                            ];
                        }
                        // Need to maintain case here, to get the correct sniff code.
                        $parts = explode(' ', substr($commentText, 10));
                        if (count($parts) >= 2) {
                            $sniffParts = explode('.', $parts[0]);
                            if (count($sniffParts) >= 3) {
                                $this->tokens[$i]['sniffCode'] = array_shift($parts);
                                $this->tokens[$i]['sniffProperty'] = array_shift($parts);
                                $this->tokens[$i]['sniffPropertyValue'] = rtrim(implode(' ', $parts), " */\r\n");
                            }
                        }
                        $this->tokens[$i]['code'] = T_PHPCS_SET;
                        $this->tokens[$i]['type'] = 'T_PHPCS_SET';
                    }
                    else {
                        if (substr($commentTextLower, 0, 16) === 'phpcs:ignorefile') {
                            // The whole file will be ignored, but at least set the correct token.
                            $this->tokens[$i]['code'] = T_PHPCS_IGNORE_FILE;
                            $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE_FILE';
                        }
                        else {
                            if (substr($commentTextLower, 0, 13) === 'phpcs:disable') {
                                if ($lineHasOtherContent === false) {
                                    // Completely ignore the comment line.
                                    $this->ignoredLines[$this->tokens[$i]['line']] = [
                                        '.all' => true,
                                    ];
                                }
                                if ($ignoring === null) {
                                    $ignoring = [];
                                }
                                $disabledSniffs = [];
                                $additionalText = substr($commentText, 14);
                                if (empty($additionalText) === true) {
                                    $ignoring = [
                                        '.all' => true,
                                    ];
                                }
                                else {
                                    $parts = explode(',', $additionalText);
                                    foreach ($parts as $sniffCode) {
                                        $sniffCode = trim($sniffCode);
                                        $disabledSniffs[$sniffCode] = true;
                                        $ignoring[$sniffCode] = true;
                                        // This newly disabled sniff might be disabling an existing
                                        // enabled exception that we are tracking.
                                        if (isset($ignoring['.except']) === true) {
                                            foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) {
                                                if ($ignoredSniffCode === $sniffCode || strpos($ignoredSniffCode, $sniffCode . '.') === 0) {
                                                    unset($ignoring['.except'][$ignoredSniffCode]);
                                                }
                                            }
                                            if (empty($ignoring['.except']) === true) {
                                                unset($ignoring['.except']);
                                            }
                                        }
                                    }
                                    
                                    //end foreach
                                }
                                
                                //end if
                                $this->tokens[$i]['code'] = T_PHPCS_DISABLE;
                                $this->tokens[$i]['type'] = 'T_PHPCS_DISABLE';
                                $this->tokens[$i]['sniffCodes'] = $disabledSniffs;
                            }
                            else {
                                if (substr($commentTextLower, 0, 12) === 'phpcs:enable') {
                                    if ($ignoring !== null) {
                                        $enabledSniffs = [];
                                        $additionalText = substr($commentText, 13);
                                        if (empty($additionalText) === true) {
                                            $ignoring = null;
                                        }
                                        else {
                                            $parts = explode(',', $additionalText);
                                            foreach ($parts as $sniffCode) {
                                                $sniffCode = trim($sniffCode);
                                                $enabledSniffs[$sniffCode] = true;
                                                // This new enabled sniff might remove previously disabled
                                                // sniffs if it is actually a standard or category of sniffs.
                                                foreach (array_keys($ignoring) as $ignoredSniffCode) {
                                                    if ($ignoredSniffCode === $sniffCode || strpos($ignoredSniffCode, $sniffCode . '.') === 0) {
                                                        unset($ignoring[$ignoredSniffCode]);
                                                    }
                                                }
                                                // This new enabled sniff might be able to clear up
                                                // previously enabled sniffs if it is actually a standard or
                                                // category of sniffs.
                                                if (isset($ignoring['.except']) === true) {
                                                    foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) {
                                                        if ($ignoredSniffCode === $sniffCode || strpos($ignoredSniffCode, $sniffCode . '.') === 0) {
                                                            unset($ignoring['.except'][$ignoredSniffCode]);
                                                        }
                                                    }
                                                }
                                            }
                                            
                                            //end foreach
                                            if (empty($ignoring) === true) {
                                                $ignoring = null;
                                            }
                                            else {
                                                if (isset($ignoring['.except']) === true) {
                                                    $ignoring['.except'] += $enabledSniffs;
                                                }
                                                else {
                                                    $ignoring['.except'] = $enabledSniffs;
                                                }
                                            }
                                        }
                                        
                                        //end if
                                        if ($lineHasOtherContent === false) {
                                            // Completely ignore the comment line.
                                            $this->ignoredLines[$this->tokens[$i]['line']] = [
                                                '.all' => true,
                                            ];
                                        }
                                        else {
                                            // The comment is on the same line as the code it is ignoring,
                                            // so respect the new ignore rules.
                                            $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
                                        }
                                        $this->tokens[$i]['sniffCodes'] = $enabledSniffs;
                                    }
                                    
                                    //end if
                                    $this->tokens[$i]['code'] = T_PHPCS_ENABLE;
                                    $this->tokens[$i]['type'] = 'T_PHPCS_ENABLE';
                                }
                                else {
                                    if (substr($commentTextLower, 0, 12) === 'phpcs:ignore') {
                                        $ignoreRules = [];
                                        $additionalText = substr($commentText, 13);
                                        if (empty($additionalText) === true) {
                                            $ignoreRules = [
                                                '.all' => true,
                                            ];
                                        }
                                        else {
                                            $parts = explode(',', $additionalText);
                                            foreach ($parts as $sniffCode) {
                                                $ignoreRules[trim($sniffCode)] = true;
                                            }
                                        }
                                        $this->tokens[$i]['code'] = T_PHPCS_IGNORE;
                                        $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE';
                                        $this->tokens[$i]['sniffCodes'] = $ignoreRules;
                                        if ($ignoring !== null) {
                                            $ignoreRules += $ignoring;
                                        }
                                        if ($lineHasOtherContent === false) {
                                            // Completely ignore the comment line, and set the following
                                            // line to include the ignore rules we've set.
                                            $this->ignoredLines[$this->tokens[$i]['line']] = [
                                                '.all' => true,
                                            ];
                                            $this->ignoredLines[$this->tokens[$i]['line'] + 1] = $ignoreRules;
                                        }
                                        else {
                                            // The comment is on the same line as the code it is ignoring,
                                            // so respect the ignore rules it set.
                                            $this->ignoredLines[$this->tokens[$i]['line']] = $ignoreRules;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    
                    //end if
                }
            }
            
            //end if
        }
        
        //end if
        if ($ignoring !== null && isset($this->ignoredLines[$this->tokens[$i]['line']]) === false) {
            $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
        }
    }
    
    //end for
    // If annotations are being ignored, we clear out all the ignore rules
    // but leave the annotations tokenized as normal.
    if ($checkAnnotations === false) {
        $this->ignoredLines = [];
    }
}

API Navigation

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