private function findStart(Tokens $tokens, $index) { do { $index = $tokens->getPrevMeaningfulToken($index); $token = $tokens[$index]; $blockType = $tokens->detectBlockType($token); if (null !== $blockType && !$blockType['isStart']) { $index = $tokens->findBlockEnd($blockType['type'], $index, false); $token = $tokens[$index]; } } while (!$token->equalsAny(array('$', array(T_VARIABLE)))); $prevIndex = $tokens->getPrevMeaningfulToken($index); $prevToken = $tokens[$prevIndex]; if ($prevToken->equals('$')) { $index = $prevIndex; $prevIndex = $tokens->getPrevMeaningfulToken($index); $prevToken = $tokens[$prevIndex]; } if ($prevToken->isGivenKind(T_OBJECT_OPERATOR)) { return $this->findStart($tokens, $prevIndex); } if ($prevToken->isGivenKind(T_PAAMAYIM_NEKUDOTAYIM)) { $prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex); if (!$tokens[$prevPrevIndex]->isGivenKind(T_STRING)) { return $this->findStart($tokens, $prevIndex); } $index = $tokens->getTokenNotOfKindSibling($prevIndex, -1, array(array(T_NS_SEPARATOR), array(T_STRING))); $index = $tokens->getNextMeaningfulToken($index); } return $index; }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { static $nativeFunctionNames = null; if (null === $nativeFunctionNames) { $nativeFunctionNames = $this->getNativeFunctionNames(); } for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { // test if we are at a function all if (!$tokens[$index]->isGivenKind(T_STRING)) { continue; } $next = $tokens->getNextMeaningfulToken($index); if (!$tokens[$next]->equals('(')) { $index = $next; continue; } $functionNamePrefix = $tokens->getPrevMeaningfulToken($index); if ($tokens[$functionNamePrefix]->isGivenKind(array(T_DOUBLE_COLON, T_NEW, T_OBJECT_OPERATOR, T_FUNCTION))) { continue; } // do not though the function call if it is to a function in a namespace other than the default if ($tokens[$functionNamePrefix]->isGivenKind(T_NS_SEPARATOR) && $tokens[$tokens->getPrevMeaningfulToken($functionNamePrefix)]->isGivenKind(T_STRING)) { continue; } // test if the function call is to a native PHP function $lower = strtolower($tokens[$index]->getContent()); if (!array_key_exists($lower, $nativeFunctionNames)) { continue; } $tokens[$index]->setContent($nativeFunctionNames[$lower]); $index = $next; } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { /** @var $token \Symfony\CS\Tokenizer\Token */ foreach ($tokens->findGivenKind(T_STRING) as $index => $token) { // skip expressions without parameters list $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; if (!$nextToken->equals('(')) { continue; } // skip expressions which are not function reference $prevTokenIndex = $tokens->getPrevMeaningfulToken($index); $prevToken = $tokens[$prevTokenIndex]; if ($prevToken->isGivenKind(array(T_DOUBLE_COLON, T_NEW, T_OBJECT_OPERATOR, T_FUNCTION))) { continue; } // handle function reference with namespaces if ($prevToken->isGivenKind(array(T_NS_SEPARATOR))) { $twicePrevTokenIndex = $tokens->getPrevMeaningfulToken($prevTokenIndex); $twicePrevToken = $tokens[$twicePrevTokenIndex]; if ($twicePrevToken->isGivenKind(array(T_DOUBLE_COLON, T_NEW, T_OBJECT_OPERATOR, T_FUNCTION, T_STRING, CT_NAMESPACE_OPERATOR))) { continue; } } // check mapping hit $tokenContent = strtolower($token->getContent()); if (!isset(self::$aliases[$tokenContent])) { continue; } $token->setContent(self::$aliases[$tokenContent]); } }
/** * @param Tokens $tokens * @param int $index * * @return bool|int */ private function isDeclareStatement(Tokens $tokens, $index) { $prevMeaningfulIndex = $tokens->getPrevMeaningfulToken($index); if ($tokens[$prevMeaningfulIndex]->isGivenKind(T_STRING)) { $prevMeaningfulIndex = $tokens->getPrevMeaningfulToken($prevMeaningfulIndex); if ($tokens[$prevMeaningfulIndex]->equals('(')) { $prevMeaningfulIndex = $tokens->getPrevMeaningfulToken($prevMeaningfulIndex); if ($tokens[$prevMeaningfulIndex]->isGivenKind(T_DECLARE)) { return $prevMeaningfulIndex; } } } return false; }
private function fixArray(Tokens $tokens, $index) { if (!$tokens->isArrayMultiLine($index)) { return; } $startIndex = $index; if ($tokens[$startIndex]->isGivenKind(T_ARRAY)) { $startIndex = $tokens->getNextTokenOfKind($startIndex, array('(')); $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); } else { $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $startIndex); } $beforeEndIndex = $tokens->getPrevMeaningfulToken($endIndex); $beforeEndToken = $tokens[$beforeEndIndex]; if ($startIndex !== $beforeEndIndex && !$beforeEndToken->equalsAny(array(',', array(T_END_HEREDOC)))) { $tokens->insertAt($beforeEndIndex + 1, new Token(',')); $endToken = $tokens[$endIndex]; if (!$endToken->isComment() && !$endToken->isWhitespace()) { $tokens->ensureWhitespaceAtIndex($endIndex, 1, ' '); } } }
/** * {@inheritdoc} */ public function process(Tokens $tokens, Token $token, $index) { $prevTokenIndex = $tokens->getPrevMeaningfulToken($index); $prevToken = $prevTokenIndex === null ? null : $tokens[$prevTokenIndex]; // Skip whole class braces content. // That way we can skip whole tokens in class declaration, therefore skip `T_USE` for traits. if ($token->isClassy() && !$prevToken->isGivenKind(T_DOUBLE_COLON)) { $index = $tokens->getNextTokenOfKind($index, array('{')); $innerLimit = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); while ($index < $innerLimit) { $token = $tokens[++$index]; if (!$token->isGivenKind(T_USE)) { continue; } if ($this->isUseForLambda($tokens, $index)) { $token->override(array(CT_USE_LAMBDA, $token->getContent())); } else { $token->override(array(CT_USE_TRAIT, $token->getContent())); } } return; } if ($token->isGivenKind(T_USE) && $this->isUseForLambda($tokens, $index)) { $token->override(array(CT_USE_LAMBDA, $token->getContent())); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { for ($index = $tokens->count() - 3; $index > 0; --$index) { $token = $tokens[$index]; if (!$token->isGivenKind(T_NEW)) { continue; } $nextIndex = $tokens->getNextTokenOfKind($index, array(':', ';', ',', '(', ')', '[', ']', array(T_CLOSE_TAG), array(CT_ARRAY_SQUARE_BRACE_OPEN), array(CT_ARRAY_SQUARE_BRACE_CLOSE), array(CT_BRACE_CLASS_INSTANTIATION_OPEN), array(CT_BRACE_CLASS_INSTANTIATION_CLOSE))); $nextToken = $tokens[$nextIndex]; // entrance into array index syntax - need to look for exit while ($nextToken->equals('[')) { $nextIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $nextIndex) + 1; $nextToken = $tokens[$nextIndex]; } // new statement has a gap in it - advance to the next token if ($nextToken->isWhitespace()) { $nextIndex = $tokens->getNextNonWhitespace($nextIndex); $nextToken = $tokens[$nextIndex]; } // new statement with () - nothing to do if ($nextToken->equals('(')) { continue; } $meaningBeforeNextIndex = $tokens->getPrevMeaningfulToken($nextIndex); $tokens->insertAt($meaningBeforeNextIndex + 1, array(new Token('('), new Token(')'))); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { // Checks if specific statements are set and uses them in this case. $loops = array_intersect_key(self::$loops, array_flip($this->controlStatements)); foreach ($tokens as $index => $token) { if (!$token->equals('(')) { continue; } $blockStartIndex = $index; $index = $tokens->getPrevMeaningfulToken($index); $token = $tokens[$index]; foreach ($loops as $loop) { if (!$token->isGivenKind($loop['lookupTokens'])) { continue; } $blockEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $blockStartIndex); $blockEndNextIndex = $tokens->getNextMeaningfulToken($blockEndIndex); if (!$tokens[$blockEndNextIndex]->equalsAny($loop['neededSuccessors'])) { continue; } if ($tokens[$blockStartIndex - 1]->isWhitespace() || $tokens[$blockStartIndex - 1]->isComment()) { $this->clearParenthesis($tokens, $blockStartIndex); } else { // Adds a space to prevent broken code like `return2`. $tokens->overrideAt($blockStartIndex, array(T_WHITESPACE, ' ')); } $this->clearParenthesis($tokens, $blockEndIndex); } } }
/** * Replace occurrences of the name of the classy element by "self" (if possible). * * @param Tokens $tokens * @param string $name * @param int $startIndex * @param int $endIndex */ private function replaceNameOccurrences(Tokens $tokens, $name, $startIndex, $endIndex) { $tokensAnalyzer = new TokensAnalyzer($tokens); for ($i = $startIndex; $i < $endIndex; ++$i) { $token = $tokens[$i]; // skip lambda functions (PHP < 5.4 compatibility) if ($token->isGivenKind(T_FUNCTION) && $tokensAnalyzer->isLambda($i)) { $i = $tokens->getNextTokenOfKind($i, array('{')); $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $i); continue; } if (!$token->equals(array(T_STRING, $name), false)) { continue; } $prevToken = $tokens[$tokens->getPrevMeaningfulToken($i)]; $nextToken = $tokens[$tokens->getNextMeaningfulToken($i)]; // skip tokens that are part of a fully qualified name if ($prevToken->isGivenKind(T_NS_SEPARATOR) || $nextToken->isGivenKind(T_NS_SEPARATOR)) { continue; } if ($prevToken->isGivenKind(array(T_INSTANCEOF, T_NEW)) || $nextToken->isGivenKind(T_PAAMAYIM_NEKUDOTAYIM)) { $token->setContent('self'); } } }
/** * {@inheritdoc} */ public function process(Tokens $tokens) { foreach ($tokens->findGivenKind(T_CLASS) as $index => $token) { $prevIndex = $tokens->getPrevMeaningfulToken($index); $prevToken = $tokens[$prevIndex]; if ($prevToken->isGivenKind(T_DOUBLE_COLON)) { $token->override(array(CT_CLASS_CONSTANT, $token->getContent(), $token->getLine())); } } }
/** * {@inheritdoc} */ public function process(Tokens $tokens, Token $token, $index) { if (!$token->isGivenKind(array(T_CONST, T_FUNCTION))) { return; } $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; if ($prevToken->isGivenKind(T_USE)) { $token->override(array($token->isGivenKind(T_FUNCTION) ? CT_FUNCTION_IMPORT : CT_CONST_IMPORT, $token->getContent())); } }
/** * {@inheritdoc} */ public function process(Tokens $tokens, Token $token, $index) { if (!$token->isGivenKind(T_CLASS)) { return; } $prevIndex = $tokens->getPrevMeaningfulToken($index); $prevToken = $tokens[$prevIndex]; if ($prevToken->isGivenKind(T_DOUBLE_COLON)) { $token->override(array(CT_CLASS_CONSTANT, $token->getContent())); } }
/** * Check if token under given index is short array opening. * * @param Tokens $tokens * @param int $index * * @return bool */ private function isShortArray(Tokens $tokens, $index) { static $disallowedPrevTokens = array(')', ']', '}', '"', array(T_CONSTANT_ENCAPSED_STRING), array(T_STRING), array(T_STRING_VARNAME), array(T_VARIABLE), array(CT_ARRAY_SQUARE_BRACE_CLOSE), array(CT_DYNAMIC_PROP_BRACE_CLOSE), array(CT_DYNAMIC_VAR_BRACE_CLOSE)); $token = $tokens[$index]; if (!$token->equals('[')) { return false; } $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; if (!$prevToken->equalsAny($disallowedPrevTokens)) { return true; } return false; }
/** * {@inheritdoc} */ public function process(Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->equalsAny(array(array(T_CLASS, 'class'), array(T_STRING, 'class')), false)) { continue; } $prevIndex = $tokens->getPrevMeaningfulToken($index); $prevToken = $tokens[$prevIndex]; if ($prevToken->isGivenKind(T_DOUBLE_COLON)) { $token->override(array(CT_CLASS_CONSTANT, $token->getContent(), $token->getLine())); } } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_PRINT)) { continue; } $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; if (!$prevToken->equalsAny(array(';', '{', '}', array(T_OPEN_TAG)))) { continue; } $tokens->overrideAt($index, array(T_ECHO, 'echo')); } }
/** * Method to move index over the non-array elements like function calls or function declarations. * * @param int $index * @param Tokens $tokens * * @return int New index */ private function skipNonArrayElements($index, Tokens $tokens) { if ($tokens[$index]->equals('}')) { return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index, false); } if ($tokens[$index]->equals(')')) { $startIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index, false); $startIndex = $tokens->getPrevMeaningfulToken($startIndex); if (!$tokens->isArray($startIndex)) { return $startIndex; } } return $index; }
/** * @see http://php.net/manual/en/language.operators.precedence.php * * @param Tokens|Token[] $tokens * * @return void */ protected function fixConditions(Tokens $tokens) { $whitelistedTokens = [T_IS_IDENTICAL, T_IS_NOT_IDENTICAL, T_IS_EQUAL, T_IS_NOT_EQUAL, T_IS_GREATER_OR_EQUAL, T_IS_SMALLER_OR_EQUAL]; foreach ($tokens as $index => $token) { if (!$token->isGivenKind($whitelistedTokens) && !in_array($token->getContent(), ['<', '>'], true)) { continue; } // Only sniff for specified tokens on left side $prevIndex = $tokens->getPrevMeaningfulToken($index); if (!$tokens[$prevIndex]->isNativeConstant() && !in_array($tokens[$prevIndex]->getId(), [T_LNUMBER, T_CONSTANT_ENCAPSED_STRING])) { continue; } $leftIndexEnd = $prevIndex; $leftIndexStart = $prevIndex; $prevIndex = $tokens->getPrevMeaningfulToken($leftIndexStart); $prevContent = $tokens[$prevIndex]->getContent(); if (!$tokens[$prevIndex]->isGivenKind([T_BOOLEAN_AND, T_BOOLEAN_OR, T_RETURN]) && $prevContent !== '=' && $prevContent !== '(') { continue; } $rightIndexStart = $tokens->getNextMeaningfulToken($index); if ($tokens[$rightIndexStart]->getContent() === '(') { $rightIndexEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $rightIndexStart); } else { $rightIndexEnd = $this->detectRightEnd($tokens, $rightIndexStart); if ($prevContent === '(') { $closingBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $prevIndex); if ($tokens[$closingBraceIndex]->getContent() !== ')') { continue; } $rightIndexEndLimit = $tokens->getPrevMeaningfulToken($closingBraceIndex); $rightIndexEnd = min($rightIndexEndLimit, $rightIndexEnd); } } $this->applyFix($tokens, $index, $leftIndexStart, $leftIndexEnd, $rightIndexStart, $rightIndexEnd); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { $limit = $tokens->count(); for ($index = 0; $index < $limit; ++$index) { $token = $tokens[$index]; // skip T_FOR parenthesis to ignore duplicated `;` like `for ($i = 1; ; ++$i) {...}` if ($token->isGivenKind(T_FOR)) { $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextMeaningfulToken($index)) + 1; continue; } if (!$token->equals(';') || !$tokens[$tokens->getPrevMeaningfulToken($index)]->equals(';')) { continue; } $tokens->removeLeadingWhitespace($index); $token->clear(); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { $end = $tokens->count() - 1; foreach (self::$functions as $map) { // the sequence is the function name, followed by "(" and a quoted string $seq = array(array(T_STRING, $map[0]), '(', array(T_CONSTANT_ENCAPSED_STRING)); $currIndex = 0; while (null !== $currIndex) { $match = $tokens->findSequence($seq, $currIndex, $end, false); // did we find a match? if (null === $match) { break; } // findSequence also returns the tokens, but we're only interested in the indexes, i.e.: // 0 => function name, // 1 => bracket "(" // 2 => quoted string passed as 1st parameter $match = array_keys($match); // advance tokenizer cursor $currIndex = $match[2]; // ensure it's a function call (not a method / static call) $prev = $tokens->getPrevMeaningfulToken($match[0]); if (null === $prev || $tokens[$prev]->isGivenKind(array(T_OBJECT_OPERATOR, T_DOUBLE_COLON))) { continue; } // ensure the first parameter is just a string (e.g. has nothing appended) $next = $tokens->getNextMeaningfulToken($match[2]); if (null === $next || !$tokens[$next]->equalsAny(array(',', ')'))) { continue; } // convert to PCRE $string = substr($tokens[$match[2]]->getContent(), 1, -1); $quote = substr($tokens[$match[2]]->getContent(), 0, 1); $delim = $this->getBestDelimiter($string); $preg = $delim . addcslashes($string, $delim) . $delim . 'D' . $map[2]; // check if the preg is valid if (!$this->checkPreg($preg)) { continue; } // modify function and argument $tokens[$match[2]]->setContent($quote . $preg . $quote); $tokens[$match[0]]->setContent($map[1]); } } }
private function fixArray(Tokens $tokens, $index) { if ($tokens->isArrayMultiLine($index)) { return; } $startIndex = $index; if ($tokens[$startIndex]->isGivenKind(T_ARRAY)) { $startIndex = $tokens->getNextTokenOfKind($startIndex, array('(')); $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); } else { $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $startIndex); } $beforeEndIndex = $tokens->getPrevMeaningfulToken($endIndex); $beforeEndToken = $tokens[$beforeEndIndex]; if ($beforeEndToken->equals(',')) { $tokens->removeTrailingWhitespace($beforeEndIndex); $beforeEndToken->clear(); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->equals('(')) { continue; } $prevIndex = $tokens->getPrevMeaningfulToken($index); // ignore parenthesis for T_ARRAY if (null !== $prevIndex && $tokens[$prevIndex]->isGivenKind(T_ARRAY)) { continue; } $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); // remove space after opening `(` $this->removeSpaceAroundToken($tokens, $index, 1); // remove space after closing `)` if it is not `list($a, $b, )` case if (!$tokens[$tokens->getPrevMeaningfulToken($endIndex)]->equals(',')) { $this->removeSpaceAroundToken($tokens, $endIndex, -1); } } }
/** * @param Tokens $tokens * @param int $start Token index of the opening brace token of the function * @param int $end Token index of the closing brace token of the function */ private function fixFunction(Tokens $tokens, $start, $end) { for ($index = $end; $index > $start; --$index) { if (!$tokens[$index]->isGivenKind(T_RETURN)) { continue; } $nextAt = $tokens->getNextMeaningfulToken($index); if (!$tokens[$nextAt]->equals(';')) { continue; } if ($tokens->getNextMeaningfulToken($nextAt) !== $end) { continue; } $previous = $tokens->getPrevMeaningfulToken($index); if ($tokens[$previous]->equalsAny(array(array(T_ELSE), ')'))) { continue; } $tokens->clearTokenAndMergeSurroundingWhitespace($index); $tokens->clearTokenAndMergeSurroundingWhitespace($nextAt); } }
/** * @param Tokens $tokens * @param int $index * * @return bool */ private function isAnonymousClass(Tokens $tokens, $index) { return $tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_NEW); }
/** * @param Tokens $tokens * @param int $index Index of the token to check * @param int $lowerLimitIndex Lower limit index. Since the token to check will always be in a conditional we must stop checking at this index * * @return bool */ private function isInConditional(Tokens $tokens, $index, $lowerLimitIndex) { $candidateIndex = $tokens->getTokenOfKindSibling($index, -1, array(')', ';', ':')); if ($tokens[$candidateIndex]->equals(':')) { return true; } if (!$tokens[$candidateIndex]->equals(')')) { return false; // token is ';' or close tag } // token is always ')' here. // If it is part of the condition the token is always in, return false. // If it is not it is a nested condition so return true $open = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $candidateIndex, false); return $tokens->getPrevMeaningfulToken($open) > $lowerLimitIndex; }
/** * @param Tokens $tokens * @param int $variableIndex * * @return bool */ private function isEllipsis(Tokens $tokens, $variableIndex) { if (PHP_VERSION_ID < 50600) { return $tokens[$tokens->getPrevMeaningfulToken($variableIndex)]->equals('.'); } return $tokens[$tokens->getPrevMeaningfulToken($variableIndex)]->isGivenKind(T_ELLIPSIS); }
private function getNewOrder(array $uses, Tokens $tokens) { $uses = array_reverse($uses); $indexes = array(); $originalIndexes = array(); foreach ($uses as $index) { $startIndex = $tokens->getTokenNotOfKindSibling($index + 1, 1, array(array(T_WHITESPACE))); $endIndex = $tokens->getNextTokenOfKind($startIndex, array(';', array(T_CLOSE_TAG))); $previous = $tokens->getPrevMeaningfulToken($endIndex); $group = $tokens[$previous]->equals('}'); if ($tokens[$startIndex]->isGivenKind(array(T_CONST))) { $type = self::IMPORT_TYPE_CONST; } elseif ($tokens[$startIndex]->isGivenKind(array(T_FUNCTION))) { $type = self::IMPORT_TYPE_FUNCTION; } else { $type = self::IMPORT_TYPE_CLASS; } $namespace = ''; $index = $startIndex; while ($index <= $endIndex) { $token = $tokens[$index]; if ($index === $endIndex || !$group && $token->equals(',')) { $indexes[$startIndex] = array('namespace' => $namespace, 'startIndex' => $startIndex, 'endIndex' => $index - 1, 'importType' => $type); $originalIndexes[] = $startIndex; if ($index === $endIndex) { break; } $namespace = ''; $nextPartIndex = $tokens->getTokenNotOfKindSibling($index, 1, array(array(','), array(T_WHITESPACE))); $startIndex = $nextPartIndex; $index = $nextPartIndex; continue; } $namespace .= $token->getContent(); ++$index; } } uasort($indexes, 'self::sortingCallBack'); $index = -1; $usesOrder = array(); // Loop trough the index but use original index order foreach ($indexes as $v) { $usesOrder[$originalIndexes[++$index]] = $v; } return $usesOrder; }
/** * @param Tokens $tokens * @param int $prevIndex * @param int $nextEndBraceIndex * * @return bool */ protected function isFixableComparison($tokens, $prevIndex, $nextEndBraceIndex) { if ($tokens[$prevIndex]->isGivenKind([T_IS_NOT_IDENTICAL, T_IS_IDENTICAL])) { $prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex); if ($tokens[$prevPrevIndex]->getContent() === 'true' || $tokens[$prevPrevIndex]->getContent() === 'false') { $this->startIndex = $prevPrevIndex; return true; } } if ($nextEndBraceIndex === null) { return false; } if ($tokens[$nextEndBraceIndex]->isGivenKind([T_IS_NOT_IDENTICAL, T_IS_IDENTICAL])) { $nextNextIndex = $tokens->getNextMeaningfulToken($nextEndBraceIndex); if ($tokens[$nextNextIndex]->getContent() === 'true' || $tokens[$nextNextIndex]->getContent() === 'false') { $this->endIndex = $nextNextIndex; return true; } } return false; }
/** * Find a function or method matching a given name within certain bounds. * * @param Tokens $tokens the Tokens instance * @param string $name the function/Method name * @param int $startIndex the search start index * @param int $endIndex the search end index * * @return array|null An associative array, if a match is found: * * - nameIndex (int): The index of the function/method name. * - startIndex (int): The index of the function/method start. * - endIndex (int): The index of the function/method end. * - bodyIndex (int): The index of the function/method body. * - modifiers (array): The modifiers as array keys and their index as * the values, e.g. array(T_PUBLIC => 10). */ private function findFunction(Tokens $tokens, $name, $startIndex, $endIndex) { $function = $tokens->findSequence(array(array(T_FUNCTION), array(T_STRING, $name), '('), $startIndex, $endIndex, false); if (null === $function) { return; } // keep only the indexes $function = array_keys($function); // find previous block, saving method modifiers for later use $possibleModifiers = array(T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_ABSTRACT, T_FINAL); $modifiers = array(); $prevBlock = $tokens->getPrevMeaningfulToken($function[0]); while (null !== $prevBlock && $tokens[$prevBlock]->isGivenKind($possibleModifiers)) { $modifiers[$tokens[$prevBlock]->getId()] = $prevBlock; $prevBlock = $tokens->getPrevMeaningfulToken($prevBlock); } if (isset($modifiers[T_ABSTRACT])) { // abstract methods have no body $bodyStart = null; $funcEnd = $tokens->getNextTokenOfKind($function[2], array(';')); } else { // find method body start and the end of the function definition $bodyStart = $tokens->getNextTokenOfKind($function[2], array('{')); $funcEnd = $bodyStart !== null ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $bodyStart) : null; } return array('nameIndex' => $function[1], 'startIndex' => $prevBlock + 1, 'endIndex' => $funcEnd, 'bodyIndex' => $bodyStart, 'modifiers' => $modifiers); }
private function findFunction(Tokens $tokens, $name, $startIndex, $endIndex) { $function = $tokens->findSequence(array( array(T_FUNCTION), array(T_STRING, $name), '(', ), $startIndex, $endIndex, false); if (null === $function) { return; } $function = array_keys($function); $possibleModifiers = array(T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_ABSTRACT, T_FINAL); $modifiers = array(); $prevBlock = $tokens->getPrevMeaningfulToken($function[0]); while (null !== $prevBlock && $tokens[$prevBlock]->isGivenKind($possibleModifiers)) { $modifiers[$tokens[$prevBlock]->getId()] = $prevBlock; $prevBlock = $tokens->getPrevMeaningfulToken($prevBlock); } if (isset($modifiers[T_ABSTRACT])) { $bodyStart = null; $funcEnd = $tokens->getNextTokenOfKind($function[2], array(';')); } else { $bodyStart = $tokens->getNextTokenOfKind($function[2], array('{')); $funcEnd = $bodyStart !== null ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $bodyStart) : null; } return array( 'nameIndex' => $function[1], 'startIndex' => $prevBlock + 1, 'endIndex' => $funcEnd, 'bodyIndex' => $bodyStart, 'modifiers' => $modifiers, ); }
/** * @param Tokens $tokens * @param int $index Index of "=" * * @return bool */ private function isTypehintedNullableVariable(Tokens $tokens, $index) { $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; if (!$nextToken->equals(array(T_STRING, 'null'), false)) { return false; } $variableIndex = $tokens->getPrevMeaningfulToken($index); $searchTokens = array(',', '(', array(T_STRING), array(CT_ARRAY_TYPEHINT)); $typehintKinds = array(T_STRING, CT_ARRAY_TYPEHINT); if (defined('T_CALLABLE')) { $searchTokens[] = array(T_CALLABLE); $typehintKinds[] = T_CALLABLE; } $prevIndex = $tokens->getPrevTokenOfKind($variableIndex, $searchTokens); return $tokens[$prevIndex]->isGivenKind($typehintKinds); }