PHP_CodeSniffer_File::_createLevelMap PHP Method

_createLevelMap() private static method

The level map adds a 'level' index to each token which indicates the depth that a token within a set of scope blocks. It also adds a 'condition' index which is an array of the scope conditions that opened each of the scopes - position 0 being the first scope opener.
private static _createLevelMap ( array &$tokens, object $tokenizer, string $eolChar ) : void
$tokens array The array of tokens to process.
$tokenizer object The tokenizer being used to process this file.
$eolChar string The EOL character to use for splitting strings.
return void
    private static function _createLevelMap(&$tokens, $tokenizer, $eolChar)
    {
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** START LEVEL MAP ***" . PHP_EOL;
        }
        $numTokens = count($tokens);
        $level = 0;
        $conditions = array();
        $lastOpener = null;
        $openers = array();
        for ($i = 0; $i < $numTokens; $i++) {
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                $type = $tokens[$i]['type'];
                $line = $tokens[$i]['line'];
                $len = $tokens[$i]['length'];
                $col = $tokens[$i]['column'];
                $content = PHP_CodeSniffer::prepareForOutput($tokens[$i]['content']);
                echo str_repeat("\t", $level + 1);
                echo "Process token {$i} on line {$line} [col:{$col};len:{$len};lvl:{$level};";
                if (empty($conditions) !== true) {
                    $condString = 'conds;';
                    foreach ($conditions as $condition) {
                        $condString .= token_name($condition) . ',';
                    }
                    echo rtrim($condString, ',') . ';';
                }
                echo "]: {$type} => {$content}" . PHP_EOL;
            }
            //end if
            $tokens[$i]['level'] = $level;
            $tokens[$i]['conditions'] = $conditions;
            if (isset($tokens[$i]['scope_condition']) === true) {
                // Check to see if this token opened the scope.
                if ($tokens[$i]['scope_opener'] === $i) {
                    $stackPtr = $tokens[$i]['scope_condition'];
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $type = $tokens[$stackPtr]['type'];
                        echo str_repeat("\t", $level + 1);
                        echo "=> Found scope opener for {$stackPtr}:{$type}" . PHP_EOL;
                    }
                    $stackPtr = $tokens[$i]['scope_condition'];
                    // If we find a scope opener that has a shared closer,
                    // then we need to go back over the condition map that we
                    // just created and fix ourselves as we just added some
                    // conditions where there was none. This happens for T_CASE
                    // statements that are using the same break statement.
                    if ($lastOpener !== null && $tokens[$lastOpener]['scope_closer'] === $tokens[$i]['scope_closer']) {
                        // This opener shares its closer with the previous opener,
                        // but we still need to check if the two openers share their
                        // closer with each other directly (like CASE and DEFAULT)
                        // or if they are just sharing because one doesn't have a
                        // closer (like CASE with no BREAK using a SWITCHes closer).
                        $thisType = $tokens[$tokens[$i]['scope_condition']]['code'];
                        $opener = $tokens[$lastOpener]['scope_condition'];
                        $isShared = isset($tokenizer->scopeOpeners[$thisType]['with'][$tokens[$opener]['code']]);
                        reset($tokenizer->scopeOpeners[$thisType]['end']);
                        reset($tokenizer->scopeOpeners[$tokens[$opener]['code']]['end']);
                        $sameEnd = current($tokenizer->scopeOpeners[$thisType]['end']) === current($tokenizer->scopeOpeners[$tokens[$opener]['code']]['end']);
                        if ($isShared === true && $sameEnd === true) {
                            $badToken = $opener;
                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                $type = $tokens[$badToken]['type'];
                                echo str_repeat("\t", $level + 1);
                                echo "* shared closer, cleaning up {$badToken}:{$type} *" . PHP_EOL;
                            }
                            for ($x = $tokens[$i]['scope_condition']; $x <= $i; $x++) {
                                $oldConditions = $tokens[$x]['conditions'];
                                $oldLevel = $tokens[$x]['level'];
                                $tokens[$x]['level']--;
                                unset($tokens[$x]['conditions'][$badToken]);
                                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                    $type = $tokens[$x]['type'];
                                    $oldConds = '';
                                    foreach ($oldConditions as $condition) {
                                        $oldConds .= token_name($condition) . ',';
                                    }
                                    $oldConds = rtrim($oldConds, ',');
                                    $newConds = '';
                                    foreach ($tokens[$x]['conditions'] as $condition) {
                                        $newConds .= token_name($condition) . ',';
                                    }
                                    $newConds = rtrim($newConds, ',');
                                    $newLevel = $tokens[$x]['level'];
                                    echo str_repeat("\t", $level + 1);
                                    echo "* cleaned {$x}:{$type} *" . PHP_EOL;
                                    echo str_repeat("\t", $level + 2);
                                    echo "=> level changed from {$oldLevel} to {$newLevel}" . PHP_EOL;
                                    echo str_repeat("\t", $level + 2);
                                    echo "=> conditions changed from {$oldConds} to {$newConds}" . PHP_EOL;
                                }
                                //end if
                            }
                            //end for
                            unset($conditions[$badToken]);
                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                $type = $tokens[$badToken]['type'];
                                echo str_repeat("\t", $level + 1);
                                echo "* token {$badToken}:{$type} removed from conditions array *" . PHP_EOL;
                            }
                            unset($openers[$lastOpener]);
                            $level--;
                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                echo str_repeat("\t", $level + 2);
                                echo '* level decreased *' . PHP_EOL;
                            }
                        }
                        //end if
                    }
                    //end if
                    $level++;
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", $level + 1);
                        echo '* level increased *' . PHP_EOL;
                    }
                    $conditions[$stackPtr] = $tokens[$stackPtr]['code'];
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $type = $tokens[$stackPtr]['type'];
                        echo str_repeat("\t", $level + 1);
                        echo "* token {$stackPtr}:{$type} added to conditions array *" . PHP_EOL;
                    }
                    $lastOpener = $tokens[$i]['scope_opener'];
                    if ($lastOpener !== null) {
                        $openers[$lastOpener] = $lastOpener;
                    }
                } else {
                    if ($lastOpener !== null && $tokens[$lastOpener]['scope_closer'] === $i) {
                        foreach (array_reverse($openers) as $opener) {
                            if ($tokens[$opener]['scope_closer'] === $i) {
                                $oldOpener = array_pop($openers);
                                if (empty($openers) === false) {
                                    $lastOpener = array_pop($openers);
                                    $openers[$lastOpener] = $lastOpener;
                                } else {
                                    $lastOpener = null;
                                }
                                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                    $type = $tokens[$oldOpener]['type'];
                                    echo str_repeat("\t", $level + 1);
                                    echo "=> Found scope closer for {$oldOpener}:{$type}" . PHP_EOL;
                                }
                                $oldCondition = array_pop($conditions);
                                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                    echo str_repeat("\t", $level + 1);
                                    echo '* token ' . token_name($oldCondition) . ' removed from conditions array *' . PHP_EOL;
                                }
                                // Make sure this closer actually belongs to us.
                                // Either the condition also has to think this is the
                                // closer, or it has to allow sharing with us.
                                $condition = $tokens[$tokens[$i]['scope_condition']]['code'];
                                if ($condition !== $oldCondition) {
                                    if (isset($tokenizer->scopeOpeners[$oldCondition]['with'][$condition]) === false) {
                                        $badToken = $tokens[$oldOpener]['scope_condition'];
                                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                            $type = token_name($oldCondition);
                                            echo str_repeat("\t", $level + 1);
                                            echo "* scope closer was bad, cleaning up {$badToken}:{$type} *" . PHP_EOL;
                                        }
                                        for ($x = $oldOpener + 1; $x <= $i; $x++) {
                                            $oldConditions = $tokens[$x]['conditions'];
                                            $oldLevel = $tokens[$x]['level'];
                                            $tokens[$x]['level']--;
                                            unset($tokens[$x]['conditions'][$badToken]);
                                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                                $type = $tokens[$x]['type'];
                                                $oldConds = '';
                                                foreach ($oldConditions as $condition) {
                                                    $oldConds .= token_name($condition) . ',';
                                                }
                                                $oldConds = rtrim($oldConds, ',');
                                                $newConds = '';
                                                foreach ($tokens[$x]['conditions'] as $condition) {
                                                    $newConds .= token_name($condition) . ',';
                                                }
                                                $newConds = rtrim($newConds, ',');
                                                $newLevel = $tokens[$x]['level'];
                                                echo str_repeat("\t", $level + 1);
                                                echo "* cleaned {$x}:{$type} *" . PHP_EOL;
                                                echo str_repeat("\t", $level + 2);
                                                echo "=> level changed from {$oldLevel} to {$newLevel}" . PHP_EOL;
                                                echo str_repeat("\t", $level + 2);
                                                echo "=> conditions changed from {$oldConds} to {$newConds}" . PHP_EOL;
                                            }
                                            //end if
                                        }
                                        //end for
                                    }
                                    //end if
                                }
                                //end if
                                $level--;
                                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                    echo str_repeat("\t", $level + 2);
                                    echo '* level decreased *' . PHP_EOL;
                                }
                                $tokens[$i]['level'] = $level;
                                $tokens[$i]['conditions'] = $conditions;
                            }
                            //end if
                        }
                        //end foreach
                    }
                }
                //end if
            }
            //end if
        }
        //end for
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** END LEVEL MAP ***" . PHP_EOL;
        }
    }