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;
}
}