/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if ($token->isGivenKind(CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN)) { $tokens->overrideAt($index, new Token('[')); } elseif ($token->isGivenKind(CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE)) { $tokens->overrideAt($index, new Token(']')); } } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { for ($index = $tokens->count() - 1; 0 <= $index; --$index) { $token = $tokens[$index]; if (!$token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { continue; } $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index); $tokens->overrideAt($index, '('); $tokens->overrideAt($closeIndex, ')'); $tokens->insertAt($index, new Token(array(T_ARRAY, 'array'))); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_ARRAY)) { continue; } $openIndex = $tokens->getNextTokenOfKind($index, array('(')); $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); $token->clear(); $tokens->overrideAt($openIndex, array(CT_ARRAY_SQUARE_BRACE_OPEN, '[')); $tokens->overrideAt($closeIndex, array(CT_ARRAY_SQUARE_BRACE_CLOSE, ']')); } }
/** * Replace all `else if` (T_ELSE T_IF) with `elseif` (T_ELSEIF). * * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_ELSE)) { continue; } $ifTokenIndex = $tokens->getNextMeaningfulToken($index); $beforeIfTokenIndex = $tokens->getPrevNonWhitespace($ifTokenIndex); // if next meaning token is not T_IF - continue searching, this is not the case for fixing if (!$tokens[$ifTokenIndex]->isGivenKind(T_IF)) { continue; } // now we have T_ELSE following by T_IF so we could fix this // 1. clear whitespaces between T_ELSE and T_IF $tokens[$index + 1]->clear(); // 2. change token from T_ELSE into T_ELSEIF $tokens->overrideAt($index, array(T_ELSEIF, 'elseif')); // 3. clear succeeding T_IF $tokens[$ifTokenIndex]->clear(); // 4. clear extra whitespace after T_IF in T_COMMENT,T_WHITESPACE?,T_IF,T_WHITESPACE sequence if ($tokens[$beforeIfTokenIndex]->isComment() && $tokens[$ifTokenIndex + 1]->isWhitespace()) { $tokens[$ifTokenIndex + 1]->clear(); } } }
/** * Replace all `else if` (T_ELSE T_IF) with `elseif` (T_ELSEIF). * * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_ELSE)) { continue; } $ifTokenIndex = $tokens->getNextMeaningfulToken($index); $beforeIfTokenIndex = $tokens->getPrevNonWhitespace($ifTokenIndex); // if next meaning token is not T_IF - continue searching, this is not the case for fixing if (!$tokens[$ifTokenIndex]->isGivenKind(T_IF)) { continue; } // now we have T_ELSE following by T_IF so we could fix this // 1. clear whitespaces between T_ELSE and T_IF $tokens[$index + 1]->clear(); // 2. change token from T_ELSE into T_ELSEIF $tokens->overrideAt($index, array(T_ELSEIF, 'elseif')); // 3. clear succeeding T_IF $tokens[$ifTokenIndex]->clear(); // 4. clear extra whitespace after T_IF in T_COMMENT,T_WHITESPACE?,T_IF,T_WHITESPACE sequence if ($tokens[$beforeIfTokenIndex]->isComment() && $tokens[$ifTokenIndex + 1]->isWhitespace()) { $tokens[$ifTokenIndex + 1]->clear(); } } // handle `T_ELSE T_WHITESPACE T_IF` treated as single `T_ELSEIF` by HHVM // see https://github.com/facebook/hhvm/issues/4796 if (defined('HHVM_VERSION')) { foreach ($tokens->findGivenKind(T_ELSEIF) as $token) { $token->setContent('elseif'); } } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_ECHO)) { continue; } $nextTokenIndex = $tokens->getNextMeaningfulToken($index); $endTokenIndex = $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))); $canBeConverted = true; for ($i = $nextTokenIndex; $i < $endTokenIndex; ++$i) { if ($tokens[$i]->equalsAny(array('(', array(CT_ARRAY_SQUARE_BRACE_OPEN)))) { $blockType = $tokens->detectBlockType($tokens[$i]); $i = $tokens->findBlockEnd($blockType['type'], $i); } if ($tokens[$i]->equals(',')) { $canBeConverted = false; break; } } if (false === $canBeConverted) { continue; } $tokens->overrideAt($index, array(T_PRINT, 'print')); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_ECHO)) { continue; } /* * HHVM parses '<?=' as T_ECHO instead of T_OPEN_TAG_WITH_ECHO * * @see https://github.com/facebook/hhvm/issues/4809 * @see https://github.com/facebook/hhvm/issues/7161 */ if (defined('HHVM_VERSION') && 0 === strpos($token->getContent(), '<?=')) { continue; } $nextTokenIndex = $tokens->getNextMeaningfulToken($index); $endTokenIndex = $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))); $canBeConverted = true; for ($i = $nextTokenIndex; $i < $endTokenIndex; ++$i) { if ($tokens[$i]->equalsAny(array('(', array(CT_ARRAY_SQUARE_BRACE_OPEN)))) { $blockType = Tokens::detectBlockType($tokens[$i]); $i = $tokens->findBlockEnd($blockType['type'], $i); } if ($tokens[$i]->equals(',')) { $canBeConverted = false; break; } } if (false === $canBeConverted) { continue; } $tokens->overrideAt($index, array(T_PRINT, 'print')); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { static $controlStructures = array(T_FOREACH, T_IF, T_SWITCH, T_WHILE, T_FOR); foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_DOC_COMMENT)) { continue; } $nextIndex = $tokens->getNextMeaningfulToken($index); $nextToken = null !== $nextIndex ? $tokens[$nextIndex] : null; if (null === $nextToken || $nextToken->equals('}')) { $tokens->overrideAt($index, array(T_COMMENT, '/*' . ltrim($token->getContent(), '/*'))); continue; } if ($this->isStructuralElement($nextToken)) { continue; } if ($nextToken->isGivenKind($controlStructures) && $this->isValidControl($tokens, $token, $nextIndex)) { continue; } if ($nextToken->isGivenKind(T_VARIABLE) && $this->isValidVariable($tokens, $token, $nextIndex)) { continue; } if ($nextToken->isGivenKind(T_LIST) && $this->isValidList($tokens, $token, $nextIndex)) { continue; } // First docblock after open tag can be file-level docblock, so its left as is. $prevIndex = $tokens->getPrevMeaningfulToken($index); if ($tokens[$prevIndex]->isGivenKind(array(T_OPEN_TAG, T_NAMESPACE))) { continue; } $tokens->overrideAt($index, array(T_COMMENT, '/*' . ltrim($token->getContent(), '/*'))); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { static $map = array(T_IS_EQUAL => array('id' => T_IS_IDENTICAL, 'content' => '==='), T_IS_NOT_EQUAL => array('id' => T_IS_NOT_IDENTICAL, 'content' => '!==')); foreach ($tokens as $index => $token) { $tokenId = $token->getId(); if (isset($map[$tokenId])) { $tokens->overrideAt($index, array($map[$tokenId]['id'], $map[$tokenId]['content'])); } } }
/** * @param Tokens $tokens * @param int $classIndex * @param int $classOpenIndex * @param int $classCloseIndex */ private function fixClass(Tokens $tokens, $classIndex, $classOpenIndex, $classCloseIndex) { for ($index = $classOpenIndex + 1; $index < $classCloseIndex; ++$index) { if ($tokens[$index]->equals('{')) { $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); continue; } if (!$tokens[$index]->isGivenKind(T_PROTECTED)) { continue; } $tokens->overrideAt($index, array(T_PRIVATE, 'private')); } }
/** * {@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')); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { /** @var Token $token */ foreach ($tokens as $index => $token) { if ($token->isGivenKind(T_DOC_COMMENT)) { $token->setContent($this->fixTokenContent($token->getContent())); continue; } if (!$token->isGivenKind(T_COMMENT)) { continue; } $content = $token->getContent(); $fixedContent = $this->fixTokenContent($content); if ($content !== $fixedContent) { $tokens->overrideAt($index, array(T_DOC_COMMENT, $fixedContent)); } } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->isGivenKind(array(T_CASE, T_DEFAULT))) { continue; } $ternariesCount = 0; for ($colonIndex = $index + 1;; ++$colonIndex) { // We have to skip ternary case for colons. if ($tokens[$colonIndex]->equals('?')) { ++$ternariesCount; } if ($tokens[$colonIndex]->equalsAny(array(':', ';'))) { if (0 === $ternariesCount) { break; } --$ternariesCount; } } if ($tokens[$colonIndex]->equals(';')) { $tokens->overrideAt($colonIndex, ':'); } } }
private function removeUseDeclaration(Tokens $tokens, array $useDeclaration) { for ($index = $useDeclaration['end'] - 1; $index >= $useDeclaration['start']; --$index) { $tokens->clearTokenAndMergeSurroundingWhitespace($index); } if ($tokens[$useDeclaration['end']]->equals(';')) { $tokens[$useDeclaration['end']]->clear(); } $prevToken = $tokens[$useDeclaration['start'] - 1]; if ($prevToken->isWhitespace()) { $prevToken->setContent(rtrim($prevToken->getContent(), " \t")); } if (!isset($tokens[$useDeclaration['end'] + 1])) { return; } $nextIndex = $useDeclaration['end'] + 1; $nextToken = $tokens[$nextIndex]; if ($nextToken->isWhitespace()) { $content = ltrim($nextToken->getContent(), " \t"); $content = preg_replace("#^\r\n|^\n#", '', $content, 1); $nextToken->setContent($content); } if ($prevToken->isWhitespace() && $nextToken->isWhitespace()) { $tokens->overrideAt($nextIndex, array(T_WHITESPACE, $prevToken->getContent() . $nextToken->getContent())); $prevToken->clear(); } }
private function fixMultipleUse(Tokens $tokens, $index, $endIndex) { $ending = $this->whitespacesConfig->getLineEnding(); for ($i = $endIndex - 1; $i > $index; --$i) { if (!$tokens[$i]->equals(',')) { continue; } $tokens->overrideAt($i, new Token(';')); $i = $tokens->getNextMeaningfulToken($i); $tokens->insertAt($i, new Token(array(T_USE, 'use'))); $tokens->insertAt($i + 1, new Token(array(T_WHITESPACE, ' '))); $indent = $this->detectIndent($tokens, $index); if ($tokens[$i - 1]->isWhitespace()) { $tokens[$i - 1]->setContent($ending . $indent); continue; } if (false === strpos($tokens[$i - 1]->getContent(), "\n")) { $tokens->insertAt($i, new Token(array(T_WHITESPACE, $ending . $indent))); } } }
/** * @param Tokens $tokens * @param int $index */ private function fixPrintToEcho(Tokens $tokens, $index) { $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; if (!$prevToken->equalsAny(array(';', '{', '}', array(T_OPEN_TAG)))) { return; } $tokens->overrideAt($index, array(T_ECHO, 'echo')); }
private function removeUseDeclaration(Tokens $tokens, array $useDeclaration) { for ($index = $useDeclaration['start']; $index <= $useDeclaration['end']; ++$index) { $tokens[$index]->clear(); } $prevToken = $tokens[$useDeclaration['start'] - 1]; if ($prevToken->isWhitespace()) { $prevToken->setContent(rtrim($prevToken->getContent(), " \t")); } if (!isset($tokens[$useDeclaration['end'] + 1])) { return; } $nextIndex = $useDeclaration['end'] + 1; $nextToken = $tokens[$nextIndex]; if ($nextToken->isWhitespace()) { $content = ltrim($nextToken->getContent(), " \t"); if ($content && "\n" === $content[0]) { $content = substr($content, 1); } $nextToken->setContent($content); } if ($prevToken->isWhitespace() && $nextToken->isWhitespace()) { $tokens->overrideAt($nextIndex, array(T_WHITESPACE, $prevToken->getContent() . $nextToken->getContent())); $prevToken->clear(); } }
/** * @param Tokens $tokens * @param int $index */ private function fixToShortArraySyntax(Tokens $tokens, $index) { $openIndex = $tokens->getNextTokenOfKind($index, array('(')); $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); $tokens->overrideAt($openIndex, array(CT::T_ARRAY_SQUARE_BRACE_OPEN, '[')); $tokens->overrideAt($closeIndex, array(CT::T_ARRAY_SQUARE_BRACE_CLOSE, ']')); $tokens->clearTokenAndMergeSurroundingWhitespace($index); }
/** * {@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 (array_key_exists('forbiddenContents', $loop)) { $forbiddenTokenIndex = $tokens->getNextTokenOfKind($blockStartIndex, $loop['forbiddenContents']); // A forbidden token is found and is inside the parenthesis. if (null !== $forbiddenTokenIndex && $forbiddenTokenIndex < $blockEndIndex) { continue; } } if ($tokens[$blockStartIndex - 1]->isWhitespace() || $tokens[$blockStartIndex - 1]->isComment()) { $tokens->clearTokenAndMergeSurroundingWhitespace($blockStartIndex); } else { // Adds a space to prevent broken code like `return2`. $tokens->overrideAt($blockStartIndex, array(T_WHITESPACE, ' ')); } $tokens->clearTokenAndMergeSurroundingWhitespace($blockEndIndex); } } }
/** * @param Tokens $tokens * @param int $functionNameIndex * @param int $openParenthesisIndex * @param int $closeParenthesisIndex * @param array<int,int> $arguments * * @return int number of tokens added to the collection */ private function fixPowToExponentiation(Tokens $tokens, $functionNameIndex, $openParenthesisIndex, $closeParenthesisIndex, array $arguments) { // find the argument separator ',' directly after the last token of the first argument; // replace it with T_POW '**' $tokens->overrideAt($tokens->getNextTokenOfKind(reset($arguments), array(',')), new Token(array(T_POW, '**'))); // clean up the function call tokens prt. I $tokens[$closeParenthesisIndex]->clear(); $added = 0; // check if the arguments need to be wrapped in parenthesis foreach (array_reverse($arguments, true) as $argumentStartIndex => $argumentEndIndex) { if ($this->isParenthesisNeeded($tokens, $argumentStartIndex, $argumentEndIndex)) { $tokens->insertAt($argumentEndIndex + 1, new Token(')')); $tokens->insertAt($argumentStartIndex, new Token('(')); $added += 2; } } // clean up the function call tokens prt. II $tokens[$openParenthesisIndex]->clear(); $tokens[$functionNameIndex]->clear(); $prev = $tokens->getPrevMeaningfulToken($functionNameIndex); if ($tokens[$prev]->isGivenKind(T_NS_SEPARATOR)) { $tokens[$prev]->clear(); } return $added; }