/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { for ($index = $tokens->count() - 1; $index >= 0; --$index) { $token = $tokens[$index]; if (!$token->isGivenKind(T_FUNCTION)) { continue; } $startParenthesisIndex = $tokens->getNextTokenOfKind($index, array('(')); $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); for ($iter = $endParenthesisIndex - 1; $iter > $startParenthesisIndex; --$iter) { if (!$tokens[$iter]->isGivenKind(T_VARIABLE)) { continue; } // skip ... before $variable for variadic parameter if (defined('T_ELLIPSIS')) { $prevNonWhitespaceIndex = $tokens->getPrevNonWhitespace($iter); if ($tokens[$prevNonWhitespaceIndex]->isGivenKind(T_ELLIPSIS)) { $iter = $prevNonWhitespaceIndex; } } // skip & before $variable for parameter passed by reference $prevNonWhitespaceIndex = $tokens->getPrevNonWhitespace($iter); if ($tokens[$prevNonWhitespaceIndex]->equals('&')) { $iter = $prevNonWhitespaceIndex; } if (!$tokens[$iter - 1]->equalsAny(array(array(T_WHITESPACE), array(T_COMMENT), array(T_DOC_COMMENT), '(', ','))) { $tokens->insertAt($iter, new Token(array(T_WHITESPACE, ' '))); } } } }
/** * {@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(')'))); } }
/** * 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'); } } }
private function transformIntoDollarCloseBrace(Tokens $tokens, Token $token, $index) { if ($token->isGivenKind(T_DOLLAR_OPEN_CURLY_BRACES)) { $nextIndex = $tokens->getNextTokenOfKind($index, array('}')); $tokens[$nextIndex]->override(array(CT_DOLLAR_CLOSE_CURLY_BRACES, '}')); } }
/** * {@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) { $tokensAnalyzer = new TokensAnalyzer($tokens); foreach ($tokensAnalyzer->getImportUseIndexes() as $index) { $indent = ''; // if previous line ends with comment and current line starts with whitespace, use current indent if ($tokens[$index - 1]->isWhitespace(" \t") && $tokens[$index - 2]->isGivenKind(T_COMMENT)) { $indent = $tokens[$index - 1]->getContent(); } elseif ($tokens[$index - 1]->isWhitespace()) { $indent = Utils::calculateTrailingWhitespaceIndent($tokens[$index - 1]); } $newline = "\n"; // Handle insert index for inline T_COMMENT with whitespace after semicolon $semicolonIndex = $tokens->getNextTokenOfKind($index, array(';', '{')); $insertIndex = $semicolonIndex + 1; if ($tokens[$insertIndex]->isWhitespace(" \t") && $tokens[$insertIndex + 1]->isComment()) { ++$insertIndex; } // Increment insert index for inline T_COMMENT or T_DOC_COMMENT if ($tokens[$insertIndex]->isComment()) { ++$insertIndex; } $afterSemicolon = $tokens->getNextMeaningfulToken($semicolonIndex); if (!$tokens[$afterSemicolon]->isGivenKind(T_USE)) { $newline .= "\n"; } if ($tokens[$insertIndex]->isWhitespace()) { $nextToken = $tokens[$insertIndex]; $nextToken->setContent($newline . $indent . ltrim($nextToken->getContent())); } elseif ($newline && $indent) { $tokens->insertAt($insertIndex, new Token(array(T_WHITESPACE, $newline . $indent))); } } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { $tokensAnalyzer = new TokensAnalyzer($tokens); $uses = array_reverse($tokensAnalyzer->getImportUseIndexes()); foreach ($uses as $index) { $endIndex = $tokens->getNextTokenOfKind($index, array(';')); $declarationContent = $tokens->generatePartialCode($index + 1, $endIndex - 1); $declarationParts = explode(',', $declarationContent); if (1 === count($declarationParts)) { continue; } $declarationContent = array(); foreach ($declarationParts as $declarationPart) { $declarationContent[] = 'use ' . trim($declarationPart) . ';'; } $declarationContent = implode("\n" . $this->detectIndent($tokens, $index), $declarationContent); for ($i = $index; $i <= $endIndex; ++$i) { $tokens[$i]->clear(); } $declarationTokens = Tokens::fromCode('<?php ' . $declarationContent); $declarationTokens[0]->clear(); $declarationTokens->clearEmptyTokens(); $tokens->insertAt($index, $declarationTokens); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { $tokensAnalyzer = new TokensAnalyzer($tokens); for ($index = $tokens->count() - 1; $index >= 0; --$index) { $token = $tokens[$index]; if (!$token->isGivenKind(T_FUNCTION)) { continue; } $startParenthesisIndex = $tokens->getNextTokenOfKind($index, array('(')); $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); $startBraceIndex = $tokens->getNextTokenOfKind($endParenthesisIndex, array(';', '{')); $startBraceToken = $tokens[$startBraceIndex]; if ($startBraceToken->equals('{')) { // fix single-line whitespace before { // eg: `function foo(){}` => `function foo() {}` // eg: `function foo() {}` => `function foo() {}` if (!$tokens[$startBraceIndex - 1]->isWhitespace() || $tokens[$startBraceIndex - 1]->isWhitespace($this->singleLineWhitespaceOptions)) { $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); } } $afterParenthesisIndex = $tokens->getNextNonWhitespace($endParenthesisIndex); $afterParenthesisToken = $tokens[$afterParenthesisIndex]; if ($afterParenthesisToken->isGivenKind(CT_USE_LAMBDA)) { $useStartParenthesisIndex = $tokens->getNextTokenOfKind($afterParenthesisIndex, array('(')); $useEndParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $useStartParenthesisIndex); // fix whitespace after CT_USE_LAMBDA $tokens->ensureWhitespaceAtIndex($afterParenthesisIndex + 1, 0, ' '); // remove single-line edge whitespaces inside use parentheses $this->fixParenthesisInnerEdge($tokens, $useStartParenthesisIndex, $useEndParenthesisIndex); // fix whitespace before CT_USE_LAMBDA $tokens->ensureWhitespaceAtIndex($afterParenthesisIndex - 1, 1, ' '); } // remove single-line edge whitespaces inside parameters list parentheses $this->fixParenthesisInnerEdge($tokens, $startParenthesisIndex, $endParenthesisIndex); if (!$tokensAnalyzer->isLambda($index)) { // remove whitespace before ( // eg: `function foo () {}` => `function foo() {}` if ($tokens[$startParenthesisIndex - 1]->isWhitespace()) { $tokens[$startParenthesisIndex - 1]->clear(); } } // fix whitespace after T_FUNCTION // eg: `function foo() {}` => `function foo() {}` $tokens->ensureWhitespaceAtIndex($index + 1, 0, ' '); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { for ($i = 0, $l = $tokens->count(); $i < $l; ++$i) { if (!$tokens[$i]->isGivenKind(T_FUNCTION)) { continue; } $startIndex = $tokens->getNextTokenOfKind($i, array('(')); $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); $this->fixFunctionDefinition($tokens, $startIndex, $i); } }
private function removeBetweenUse($index) { $next = $this->tokens->getNextTokenOfKind($index, array(';', T_CLOSE_TAG)); if (null === $next || $this->tokens[$next]->isGivenKind(T_CLOSE_TAG)) { return; } $nextUseCandidate = $this->tokens->getNextMeaningfulToken($next); if (null === $nextUseCandidate || 1 === $nextUseCandidate - $next || !$this->tokens[$nextUseCandidate]->isGivenKind($this->tokens[$index]->getId())) { return; } return $this->removeEmptyLinesAfterLineWithTokenAt($next); }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { $ending = $this->whitespacesConfig->getLineEnding(); $tokensAnalyzer = new TokensAnalyzer($tokens); foreach ($tokensAnalyzer->getImportUseIndexes() as $index) { $indent = ''; // if previous line ends with comment and current line starts with whitespace, use current indent if ($tokens[$index - 1]->isWhitespace(" \t") && $tokens[$index - 2]->isGivenKind(T_COMMENT)) { $indent = $tokens[$index - 1]->getContent(); } elseif ($tokens[$index - 1]->isWhitespace()) { $indent = Utils::calculateTrailingWhitespaceIndent($tokens[$index - 1]); } $semicolonIndex = $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))); // Handle insert index for inline T_COMMENT with whitespace after semicolon $insertIndex = $semicolonIndex; if ($tokens[$semicolonIndex]->isGivenKind(T_CLOSE_TAG)) { if ($tokens[$insertIndex - 1]->isWhitespace()) { --$insertIndex; } $tokens->insertAt($insertIndex, new Token(';')); } if ($semicolonIndex === count($tokens) - 1) { $tokens->insertAt($insertIndex + 1, new Token(array(T_WHITESPACE, $ending . $ending . $indent))); } else { $newline = $ending; $tokens[$semicolonIndex]->isGivenKind(T_CLOSE_TAG) ? --$insertIndex : ++$insertIndex; if ($tokens[$insertIndex]->isWhitespace(" \t") && $tokens[$insertIndex + 1]->isComment()) { ++$insertIndex; } // Increment insert index for inline T_COMMENT or T_DOC_COMMENT if ($tokens[$insertIndex]->isComment()) { ++$insertIndex; } $afterSemicolon = $tokens->getNextMeaningfulToken($semicolonIndex); if (null === $afterSemicolon || !$tokens[$afterSemicolon]->isGivenKind(T_USE)) { $newline .= $ending; } if ($tokens[$insertIndex]->isWhitespace()) { $nextToken = $tokens[$insertIndex]; $nextMeaningfulAfterUseIndex = $tokens->getNextMeaningfulToken($insertIndex); if (null !== $nextMeaningfulAfterUseIndex && $tokens[$nextMeaningfulAfterUseIndex]->isGivenKind(T_USE)) { if (substr_count($nextToken->getContent(), "\n") < 2) { $nextToken->setContent($newline . $indent . ltrim($nextToken->getContent())); } } else { $nextToken->setContent($newline . $indent . ltrim($nextToken->getContent())); } } else { $tokens->insertAt($insertIndex, new Token(array(T_WHITESPACE, $newline . $indent))); } } } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_FUNCTION)) { continue; } $index = $tokens->getNextTokenOfKind($index, array(';', '{')); if ($tokens[$index]->equals('{')) { $this->fixFunction($tokens, $index, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index)); } } }
/** * Replaces ::class keyword, namespace by namespace. * * It uses recursive method to get rid of token index changes. * * @param Tokens $tokens * @param int $namespaceNumber */ private function replaceClassKeywords(Tokens $tokens, $namespaceNumber = -1) { $namespaceIndexes = array_keys($tokens->findGivenKind(T_NAMESPACE)); // Namespace blocks if (!empty($namespaceIndexes) && isset($namespaceIndexes[$namespaceNumber])) { $startIndex = $namespaceIndexes[$namespaceNumber]; $namespaceBlockStartIndex = $tokens->getNextTokenOfKind($startIndex, array(';', '{')); $endIndex = $tokens[$namespaceBlockStartIndex]->equals('{') ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $namespaceBlockStartIndex) : $tokens->getNextTokenOfKind($namespaceBlockStartIndex, array(T_NAMESPACE)); $endIndex = $endIndex ?: $tokens->count() - 1; } elseif (-1 === $namespaceNumber) { // Out of any namespace block $startIndex = 0; $endIndex = !empty($namespaceIndexes) ? $namespaceIndexes[0] : $tokens->count() - 1; } else { return; } $this->storeImports($tokens, $startIndex, $endIndex); $tokens->rewind(); $this->replaceClassKeywordsSection($tokens, $startIndex, $endIndex); $this->replaceClassKeywords($tokens, $namespaceNumber + 1); }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { foreach ($tokens as $index => $token) { if (!$token->isClassy()) { continue; } $startBraceIndex = $tokens->getNextTokenOfKind($index, array('{')); if (!$tokens[$startBraceIndex + 1]->isWhitespace()) { continue; } $this->fixWhitespace($tokens[$startBraceIndex + 1]); } }
/** * {@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, ']')); } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { $tokensAnalyzer = new TokensAnalyzer($tokens); $uses = array_reverse($tokensAnalyzer->getImportUseIndexes()); foreach ($uses as $index) { $endIndex = $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))); $groupClose = $tokens->getPrevMeaningfulToken($endIndex); if ($tokens[$groupClose]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_CLOSE)) { $this->fixGroupUse($tokens, $index, $endIndex); } else { $this->fixMultipleUse($tokens, $index, $endIndex); } } }
/** * Fix the line breaks per group. * * For each use token reach the nearest ; and ensure every * token after has one \n before next non empty token (next line). * It skips the first pass from the bottom. * * @param Tokens $tokens * @param array $uses */ private function fixLineBreaksPerImportGroup(Tokens $tokens, array $uses) { foreach ($uses as $index) { $endIndex = $tokens->getNextTokenOfKind($index, array(';')); $afterSemicolonIndex = $tokens->getNextNonWhitespace($endIndex); if (null !== $afterSemicolonIndex && !$tokens[$afterSemicolonIndex]->isGivenKind(T_USE)) { continue; } $nextToken = $tokens[$endIndex + 1]; if ($nextToken->isWhitespace()) { $nextToken->setContent(preg_replace('/\\n{2,}/', "\n", $nextToken->getContent())); } } }
private function fixFunction(Tokens $tokens, $functionIndex, array $functionParams) { $startBraceIndex = $tokens->getNextTokenOfKind($functionIndex, array('(')); $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startBraceIndex); $commaCounter = 0; $sawParameter = false; for ($index = $startBraceIndex + 1; $index < $endBraceIndex; ++$index) { $token = $tokens[$index]; if (!$token->isWhitespace() && !$token->isComment()) { $sawParameter = true; } if ($token->equals('(')) { $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); continue; } if ($token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index); continue; } if ($token->equals(',')) { ++$commaCounter; continue; } } $functionParamsQuantity = count($functionParams); $paramsQuantity = ($sawParameter ? 1 : 0) + $commaCounter; if ($paramsQuantity === $functionParamsQuantity) { return; } $tokensToInsert = array(); for ($i = $paramsQuantity; $i < $functionParamsQuantity; ++$i) { // function call do not have all params that are required to set useStrict flag, exit from method! if (!$functionParams[$i]) { return; } $tokensToInsert[] = new Token(','); $tokensToInsert[] = new Token(array(T_WHITESPACE, ' ')); if (!is_array($functionParams[$i])) { $tokensToInsert[] = clone $functionParams[$i]; continue; } foreach ($functionParams[$i] as $param) { $tokensToInsert[] = clone $param; } } $beforeEndBraceIndex = $tokens->getPrevNonWhitespace($endBraceIndex); $tokens->insertAt($beforeEndBraceIndex + 1, $tokensToInsert); }
/** * Method to fix spacing in array declaration. * * @param int $index * @param Tokens $tokens */ private function fixSpacing($index, Tokens $tokens) { if ($tokens[$index]->isGivenKind(CT_ARRAY_SQUARE_BRACE_OPEN)) { $startIndex = $index; $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $startIndex); } else { $startIndex = $tokens->getNextTokenOfKind($index, array('(')); $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); } for ($i = $endIndex - 1; $i > $startIndex; --$i) { $i = $this->skipNonArrayElements($i, $tokens); if ($tokens[$i]->equals(',') && !$tokens[$i + 1]->isWhitespace()) { $tokens->insertAt($i + 1, new Token(array(T_WHITESPACE, ' '))); } } }
/** * Method to fix spacing in array declaration. * * @param int $index * @param Tokens $tokens */ private function fixSpacing($index, Tokens $tokens) { if ($tokens[$index]->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { $startIndex = $index; $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $startIndex); } else { $startIndex = $tokens->getNextTokenOfKind($index, array('(')); $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); } for ($i = $endIndex - 1; $i > $startIndex; --$i) { $i = $this->skipNonArrayElements($i, $tokens); $currentToken = $tokens[$i]; $prevIndex = $tokens->getPrevNonWhitespace($i - 1); if ($currentToken->equals(',') && !$tokens[$prevIndex]->equals(array(T_END_HEREDOC))) { $tokens->removeLeadingWhitespace($i); } } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { static $nextTokenKinds = null; if (null === $nextTokenKinds) { $nextTokenKinds = array('?', ';', ',', '(', ')', '[', ']', ':', '<', '>', '+', '-', '*', '/', '%', '&', '^', '|', array(T_CLASS), array(T_IS_SMALLER_OR_EQUAL), array(T_IS_GREATER_OR_EQUAL), array(T_IS_EQUAL), array(T_IS_NOT_EQUAL), array(T_IS_IDENTICAL), array(T_IS_NOT_IDENTICAL), array(T_CLOSE_TAG), array(T_LOGICAL_AND), array(T_LOGICAL_OR), array(T_LOGICAL_XOR), array(T_BOOLEAN_AND), array(T_BOOLEAN_OR), array(T_SL), array(T_SR), array(T_INSTANCEOF), array(T_AS), array(T_DOUBLE_ARROW), array(CT_ARRAY_SQUARE_BRACE_OPEN), array(CT_ARRAY_SQUARE_BRACE_CLOSE), array(CT_BRACE_CLASS_INSTANTIATION_OPEN), array(CT_BRACE_CLASS_INSTANTIATION_CLOSE)); if (defined('T_POW')) { $nextTokenKinds[] = array(T_POW); } if (defined('T_SPACESHIP')) { $nextTokenKinds[] = array(T_SPACESHIP); } } for ($index = $tokens->count() - 3; $index > 0; --$index) { $token = $tokens[$index]; if (!$token->isGivenKind(T_NEW)) { continue; } $nextIndex = $tokens->getNextTokenOfKind($index, $nextTokenKinds); $nextToken = $tokens[$nextIndex]; // new anonymous class definition if ($nextToken->isGivenKind(T_CLASS)) { if (!$tokens[$tokens->getNextMeaningfulToken($nextIndex)]->equals('(')) { $this->insertBracesAfter($tokens, $nextIndex); } continue; } // 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; } $this->insertBracesAfter($tokens, $tokens->getPrevMeaningfulToken($nextIndex)); } }
private function fixArray(Tokens $tokens, $index) { $tokensAnalyzer = new TokensAnalyzer($tokens); if ($tokensAnalyzer->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_ARRAY_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) { for ($index = $tokens->count() - 1; $index >= 0; --$index) { $token = $tokens[$index]; if (!$token->isGivenKind(T_NAMESPACE)) { continue; } $semicolonIndex = $tokens->getNextTokenOfKind($index, array(';', '{')); $semicolonToken = $tokens[$semicolonIndex]; if (!isset($tokens[$semicolonIndex + 1]) || !$semicolonToken->equals(';')) { continue; } $nextToken = $tokens[$semicolonIndex + 1]; if (!$nextToken->isWhitespace()) { $tokens->insertAt($semicolonIndex + 1, new Token(array(T_WHITESPACE, "\n\n"))); } else { $nextToken->setContent("\n\n" . ltrim($nextToken->getContent())); } } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { $tokensAnalyzer = new TokensAnalyzer($tokens); $uses = array_reverse($tokensAnalyzer->getImportUseIndexes()); foreach ($uses as $index) { $endIndex = $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))); $previous = $tokens->getPrevMeaningfulToken($endIndex); if ($tokens[$previous]->equals('}')) { $start = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $previous, false); $declarationContent = $tokens->generatePartialCode($start + 1, $previous - 1); $prefix = ''; for ($i = $index + 1; $i < $start; ++$i) { $prefix .= $tokens[$i]->getContent(); } $prefix = ' ' . ltrim($prefix); } else { $declarationContent = $tokens->generatePartialCode($index + 1, $endIndex - 1); $prefix = ' '; } $declarationParts = explode(',', $declarationContent); if (1 === count($declarationParts)) { continue; } $declarationContent = array(); foreach ($declarationParts as $declarationPart) { $declarationContent[] = 'use' . $prefix . trim($declarationPart) . ';'; } $declarationContent = implode("\n" . $this->detectIndent($tokens, $index), $declarationContent); for ($i = $index; $i < $endIndex; ++$i) { $tokens[$i]->clear(); } if ($tokens[$endIndex]->equals(';')) { $tokens[$endIndex]->clear(); } $declarationTokens = Tokens::fromCode('<?php ' . $declarationContent); $declarationTokens[0]->clear(); $declarationTokens->clearEmptyTokens(); $tokens->insertAt($index, $declarationTokens); } }
private function findIncludies(Tokens $tokens) { static $includyTokenKinds = array(T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE); $includies = array(); foreach ($tokens->findGivenKind($includyTokenKinds) as $includyTokens) { foreach ($includyTokens as $index => $token) { $includy = array('begin' => $index, 'braces' => null, 'end' => $tokens->getNextTokenOfKind($index, array(';'))); $nextTokenIndex = $tokens->getNextMeaningfulToken($index); $nextToken = $tokens[$nextTokenIndex]; if ($nextToken->equals('(')) { // Don't remove braces when the statement is wrapped. // Include is also legal as function parameter or condition statement but requires being wrapped then. $braceCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nextTokenIndex); if ($tokens[$tokens->getNextMeaningfulToken($braceCloseIndex)]->equals(';')) { $includy['braces'] = array('open' => $nextTokenIndex, 'close' => $braceCloseIndex); } } $includies[] = $includy; } } return $includies; }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { for ($index = $tokens->count() - 1; $index >= 0; --$index) { $token = $tokens[$index]; if (!$token->equals(array(T_STRING, 'trigger_error'), false)) { continue; } $start = $index; $prev = $tokens->getPrevMeaningfulToken($start); if ($tokens[$prev]->isGivenKind(T_NS_SEPARATOR)) { $start = $prev; $prev = $tokens->getPrevMeaningfulToken($start); } if ($tokens[$prev]->isGivenKind(T_STRING) || $tokens[$prev]->equals('@')) { continue; } $end = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextTokenOfKind($index, array(T_STRING, '('))); if ($tokens[$tokens->getPrevMeaningfulToken($end)]->equals(array(T_STRING, 'E_USER_DEPRECATED'))) { $tokens->insertAt($start, new Token('@')); } } }
/** * {@inheritdoc} */ public function fix(\SplFileInfo $file, Tokens $tokens) { $ending = $this->whitespacesConfig->getLineEnding(); $lastIndex = $tokens->count() - 1; for ($index = $lastIndex; $index >= 0; --$index) { $token = $tokens[$index]; if (!$token->isGivenKind(T_NAMESPACE)) { continue; } $semicolonIndex = $tokens->getNextTokenOfKind($index, array(';', '{', array(T_CLOSE_TAG))); $semicolonToken = $tokens[$semicolonIndex]; if (!isset($tokens[$semicolonIndex + 1]) || !$semicolonToken->equals(';')) { continue; } $nextIndex = $semicolonIndex + 1; $nextToken = $tokens[$nextIndex]; if (!$nextToken->isWhitespace()) { $tokens->insertAt($semicolonIndex + 1, new Token(array(T_WHITESPACE, $ending . $ending))); } else { $nextToken->setContent(($nextIndex === $lastIndex ? $ending : $ending . $ending) . ltrim($nextToken->getContent())); } } }
/** * {@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); } } }
private function fixArray(Tokens $tokens, $index) { $tokensAnalyzer = new TokensAnalyzer($tokens); if (!$tokensAnalyzer->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_ARRAY_SQUARE_BRACE, $startIndex); } $beforeEndIndex = $tokens->getPrevMeaningfulToken($endIndex); $beforeEndToken = $tokens[$beforeEndIndex]; // if there is some item between braces then add `,` after it 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, ' '); } } }