function Tokenizer::createLevelMap
Constructs the level map.
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 'conditions' index which is an array of the scope conditions that opened each of the scopes - position 0 being the first scope opener.
Return value
void
1 call to Tokenizer::createLevelMap()
- 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 1504
Class
Namespace
PHP_CodeSniffer\TokenizersCode
private function createLevelMap() {
if (PHP_CODESNIFFER_VERBOSITY > 1) {
echo "\t*** START LEVEL MAP ***" . PHP_EOL;
}
$this->numTokens = count($this->tokens);
$level = 0;
$conditions = [];
$lastOpener = null;
$openers = [];
for ($i = 0; $i < $this->numTokens; $i++) {
if (PHP_CODESNIFFER_VERBOSITY > 1) {
$type = $this->tokens[$i]['type'];
$line = $this->tokens[$i]['line'];
$len = $this->tokens[$i]['length'];
$col = $this->tokens[$i]['column'];
$content = Common::prepareForOutput($this->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) {
$conditionString = 'conds;';
foreach ($conditions as $condition) {
$conditionString .= Tokens::tokenName($condition) . ',';
}
echo rtrim($conditionString, ',') . ';';
}
echo "]: {$type} => {$content}" . PHP_EOL;
}
//end if
$this->tokens[$i]['level'] = $level;
$this->tokens[$i]['conditions'] = $conditions;
if (isset($this->tokens[$i]['scope_condition']) === true) {
// Check to see if this token opened the scope.
if ($this->tokens[$i]['scope_opener'] === $i) {
$stackPtr = $this->tokens[$i]['scope_condition'];
if (PHP_CODESNIFFER_VERBOSITY > 1) {
$type = $this->tokens[$stackPtr]['type'];
echo str_repeat("\t", $level + 1);
echo "=> Found scope opener for {$stackPtr}:{$type}" . PHP_EOL;
}
$stackPtr = $this->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 && $this->tokens[$lastOpener]['scope_closer'] === $this->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 = $this->tokens[$this->tokens[$i]['scope_condition']]['code'];
$opener = $this->tokens[$lastOpener]['scope_condition'];
$isShared = isset($this->scopeOpeners[$thisType]['with'][$this->tokens[$opener]['code']]);
reset($this->scopeOpeners[$thisType]['end']);
reset($this->scopeOpeners[$this->tokens[$opener]['code']]['end']);
$sameEnd = current($this->scopeOpeners[$thisType]['end']) === current($this->scopeOpeners[$this->tokens[$opener]['code']]['end']);
if ($isShared === true && $sameEnd === true) {
$badToken = $opener;
if (PHP_CODESNIFFER_VERBOSITY > 1) {
$type = $this->tokens[$badToken]['type'];
echo str_repeat("\t", $level + 1);
echo "* shared closer, cleaning up {$badToken}:{$type} *" . PHP_EOL;
}
for ($x = $this->tokens[$i]['scope_condition']; $x <= $i; $x++) {
$oldConditions = $this->tokens[$x]['conditions'];
$oldLevel = $this->tokens[$x]['level'];
$this->tokens[$x]['level']--;
unset($this->tokens[$x]['conditions'][$badToken]);
if (PHP_CODESNIFFER_VERBOSITY > 1) {
$type = $this->tokens[$x]['type'];
$oldConds = '';
foreach ($oldConditions as $condition) {
$oldConds .= Tokens::tokenName($condition) . ',';
}
$oldConds = rtrim($oldConds, ',');
$newConds = '';
foreach ($this->tokens[$x]['conditions'] as $condition) {
$newConds .= Tokens::tokenName($condition) . ',';
}
$newConds = rtrim($newConds, ',');
$newLevel = $this->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 = $this->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] = $this->tokens[$stackPtr]['code'];
if (PHP_CODESNIFFER_VERBOSITY > 1) {
$type = $this->tokens[$stackPtr]['type'];
echo str_repeat("\t", $level + 1);
echo "* token {$stackPtr}:{$type} added to conditions array *" . PHP_EOL;
}
$lastOpener = $this->tokens[$i]['scope_opener'];
if ($lastOpener !== null) {
$openers[$lastOpener] = $lastOpener;
}
}
else {
if ($lastOpener !== null && $this->tokens[$lastOpener]['scope_closer'] === $i) {
foreach (array_reverse($openers) as $opener) {
if ($this->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 = $this->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 ' . Tokens::tokenName($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 = $this->tokens[$this->tokens[$i]['scope_condition']]['code'];
if ($condition !== $oldCondition) {
if (isset($this->scopeOpeners[$oldCondition]['with'][$condition]) === false) {
$badToken = $this->tokens[$oldOpener]['scope_condition'];
if (PHP_CODESNIFFER_VERBOSITY > 1) {
$type = Tokens::tokenName($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 = $this->tokens[$x]['conditions'];
$oldLevel = $this->tokens[$x]['level'];
$this->tokens[$x]['level']--;
unset($this->tokens[$x]['conditions'][$badToken]);
if (PHP_CODESNIFFER_VERBOSITY > 1) {
$type = $this->tokens[$x]['type'];
$oldConds = '';
foreach ($oldConditions as $condition) {
$oldConds .= Tokens::tokenName($condition) . ',';
}
$oldConds = rtrim($oldConds, ',');
$newConds = '';
foreach ($this->tokens[$x]['conditions'] as $condition) {
$newConds .= Tokens::tokenName($condition) . ',';
}
$newConds = rtrim($newConds, ',');
$newLevel = $this->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;
}
$this->tokens[$i]['level'] = $level;
$this->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;
}
}