Its role is to provide the ability to analyze collection.
저자: Dariusz Rumiński (dariusz.ruminski@gmail.com)
저자: Gregor Harlan (gharlan@web.de)
 /**
  * {@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)));
         }
     }
 }
예제 #2
0
 /**
  * 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 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);
     }
 }
예제 #4
0
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $namespacesImports = $tokensAnalyzer->getImportUseIndexes(true);
     $usesOrder = array();
     if (!count($namespacesImports)) {
         return;
     }
     foreach ($namespacesImports as $uses) {
         $uses = array_reverse($uses);
         $usesOrder = array_replace($usesOrder, $this->getNewOrder($uses, $tokens));
     }
     $usesOrder = array_reverse($usesOrder, true);
     $mapStartToEnd = array();
     foreach ($usesOrder as $use) {
         $mapStartToEnd[$use[1]] = $use[2];
     }
     // Now insert the new tokens, starting from the end
     foreach ($usesOrder as $index => $use) {
         $declarationTokens = Tokens::fromCode('<?php use ' . $use[0] . ';');
         $declarationTokens->clearRange(0, 2);
         // clear `<?php use `
         $declarationTokens[count($declarationTokens) - 1]->clear();
         // clear `;`
         $declarationTokens->clearEmptyTokens();
         $tokens->overrideRange($index, $mapStartToEnd[$index], $declarationTokens);
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $namespaceDeclarations = $this->getNamespaceDeclarations($tokens);
     $useDeclarationsIndexes = $tokensAnalyzer->getImportUseIndexes();
     $useDeclarations = $this->getNamespaceUseDeclarations($tokens, $useDeclarationsIndexes);
     $contentWithoutUseDeclarations = $this->generateCodeWithoutPartials($tokens, array_merge($namespaceDeclarations, $useDeclarations));
     $useUsages = $this->detectUseUsages($contentWithoutUseDeclarations, $useDeclarations);
     $this->removeUnusedUseDeclarations($tokens, $useDeclarations, $useUsages);
     $this->removeUsesInSameNamespace($tokens, $useDeclarations, $namespaceDeclarations);
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $namespacesImports = $tokensAnalyzer->getImportUseIndexes(true);
     if (!count($namespacesImports)) {
         return;
     }
     foreach ($namespacesImports as $uses) {
         $uses = array_reverse($uses);
         $this->fixLineBreaksPerImportGroup($tokens, $uses);
     }
 }
 /**
  * {@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)
 {
     $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);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     for ($index = $tokens->count() - 1; $index >= 0; --$index) {
         if ($tokensAnalyzer->isUnarySuccessorOperator($index)) {
             $tokens->removeLeadingWhitespace($index);
             continue;
         }
         if ($tokensAnalyzer->isUnaryPredecessorOperator($index)) {
             $tokens->removeTrailingWhitespace($index);
             continue;
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     for ($index = $tokens->count() - 1; $index >= 0; --$index) {
         $token = $tokens[$index];
         if ($tokensAnalyzer->isUnaryPredecessorOperator($index) && $token->equals('!')) {
             if (!$tokens[$index + 1]->isWhitespace()) {
                 $tokens->insertAt($index + 1, new Token(array(T_WHITESPACE, ' ')));
             } else {
                 $tokens[$index + 1]->setContent(' ');
             }
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     for ($index = $tokens->count() - 1; $index >= 0; --$index) {
         if (!$tokensAnalyzer->isBinaryOperator($index)) {
             continue;
         }
         if (!$tokens[$index + 1]->isWhitespace()) {
             $tokens->insertAt($index + 1, new Token(array(T_WHITESPACE, ' ')));
         }
         if (!$tokens[$index - 1]->isWhitespace()) {
             $tokens->insertAt($index, new Token(array(T_WHITESPACE, ' ')));
         }
     }
 }
 /**
  * {@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, ' ');
     }
 }
예제 #13
0
 /**
  * @param Tokens         $tokens
  * @param TokensAnalyzer $tokensAnalyzer
  * @param int            $classStart
  * @param int            $classEnd
  */
 private function fixClass(Tokens $tokens, TokensAnalyzer $tokensAnalyzer, $classStart, $classEnd)
 {
     for ($index = $classEnd; $index > $classStart; --$index) {
         if (!$tokens[$index]->isGivenKind(T_FUNCTION) || $tokensAnalyzer->isLambda($index)) {
             continue;
         }
         $attributes = $tokensAnalyzer->getMethodAttributes($index);
         if (true === $attributes['abstract']) {
             $methodEnd = $tokens->getNextTokenOfKind($index, array(';'));
         } else {
             $methodStart = $tokens->getNextTokenOfKind($index, array('{'));
             $methodEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $methodStart, true);
         }
         $this->fixSpaceBelowMethod($tokens, $classEnd, $methodEnd);
         $this->fixSpaceAboveMethod($tokens, $classStart, $index);
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $classes = array_keys($tokens->findGivenKind(T_CLASS));
     $numClasses = count($classes);
     for ($i = 0; $i < $numClasses; ++$i) {
         $index = $classes[$i];
         // is it an an anonymous class definition?
         if ($tokensAnalyzer->isAnonymousClass($index)) {
             continue;
         }
         // is it inside a namespace?
         $nspIndex = $tokens->getPrevTokenOfKind($index, array(array(T_NAMESPACE, 'namespace')));
         if (null !== $nspIndex) {
             $nspIndex = $tokens->getNextMeaningfulToken($nspIndex);
             // make sure it's not the global namespace, as PHP4 constructors are allowed in there
             if (!$tokens[$nspIndex]->equals('{')) {
                 // unless it's the global namespace, the index currently points to the name
                 $nspIndex = $tokens->getNextTokenOfKind($nspIndex, array(';', '{'));
                 if ($tokens[$nspIndex]->equals(';')) {
                     // the class is inside a (non-block) namespace, no PHP4-code should be in there
                     break;
                 }
                 // the index points to the { of a block-namespace
                 $nspEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $nspIndex);
                 if ($index < $nspEnd) {
                     // the class is inside a block namespace, skip other classes that might be in it
                     for ($j = $i + 1; $j < $numClasses; ++$j) {
                         if ($classes[$j] < $nspEnd) {
                             ++$i;
                         }
                     }
                     // and continue checking the classes that might follow
                     continue;
                 }
             }
         }
         $classNameIndex = $tokens->getNextMeaningfulToken($index);
         $className = $tokens[$classNameIndex]->getContent();
         $classStart = $tokens->getNextTokenOfKind($classNameIndex, array('{'));
         $classEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classStart);
         $this->fixConstructor($tokens, $className, $classStart, $classEnd);
         $this->fixParent($tokens, $classStart, $classEnd);
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     // last and first tokens cannot be an operator
     for ($index = $tokens->count() - 2; $index >= 0; --$index) {
         if (!$tokensAnalyzer->isBinaryOperator($index)) {
             continue;
         }
         $isDeclare = $this->isDeclareStatement($tokens, $index);
         if (false !== $isDeclare) {
             $index = $isDeclare;
             // skip `declare(foo ==bar)`, see `declare_equal_normalize`
         } else {
             $this->fixWhiteSpaceAroundOperator($tokens, $index);
         }
         // previous of binary operator is now never an operator / previous of declare statement cannot be an operator
         --$index;
     }
 }
예제 #16
0
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     for ($index = $tokens->count() - 1; 0 <= $index; --$index) {
         $token = $tokens[$index];
         if (!$token->isGivenKind(array(T_INC, T_DEC)) || !$tokensAnalyzer->isUnarySuccessorOperator($index)) {
             continue;
         }
         $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)];
         if (!$nextToken->equalsAny(array(';', ')'))) {
             continue;
         }
         $startIndex = $this->findStart($tokens, $index);
         $prevToken = $tokens[$tokens->getPrevMeaningfulToken($startIndex)];
         if ($prevToken->equalsAny(array(';', '{', '}', array(T_OPEN_TAG)))) {
             $tokens->insertAt($startIndex, clone $token);
             $token->clear();
         }
     }
 }
 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)
 {
     $foundNamespace = $tokens->findGivenKind(T_NAMESPACE);
     if (empty($foundNamespace)) {
         return;
     }
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $firstNamespaceIdx = key($foundNamespace);
     $usesIdxs = $tokensAnalyzer->getImportUseIndexes();
     foreach ($usesIdxs as $idx) {
         if ($idx < $firstNamespaceIdx) {
             continue;
         }
         $nextTokenIdx = $tokens->getNextNonWhitespace($idx);
         $nextToken = $tokens[$nextTokenIdx];
         if ($nextToken->isGivenKind(T_NS_SEPARATOR)) {
             $nextToken->clear();
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $elements = $tokensAnalyzer->getClassyElements();
     foreach (array_reverse($elements, true) as $index => $element) {
         if ('method' === $element['type']) {
             $this->overrideAttribs($tokens, $index, $this->grabAttribsBeforeMethodToken($tokens, $index));
             // force whitespace between function keyword and function name to be single space char
             $afterToken = $tokens[++$index];
             if ($afterToken->isWhitespace()) {
                 $afterToken->setContent(' ');
             }
         } elseif ('property' === $element['type']) {
             $prevIndex = $tokens->getPrevTokenOfKind($index, array(';', ',', '{'));
             if (!$prevIndex || !$tokens[$prevIndex]->equals(',')) {
                 $this->overrideAttribs($tokens, $index, $this->grabAttribsBeforePropertyToken($tokens, $index));
             }
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $elements = $tokensAnalyzer->getClassyElements();
     foreach (array_reverse($elements, true) as $index => $element) {
         if (!in_array($element['type'], $this->configuration, true)) {
             continue;
         }
         switch ($element['type']) {
             case 'method':
                 $this->fixMethodVisibility($tokens, $index);
                 break;
             case 'property':
                 $this->fixPropertyVisibility($tokens, $index);
                 break;
             case 'const':
                 $this->fixConstVisibility($tokens, $index);
                 break;
         }
     }
 }
 /**
  * {@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);
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     for ($index = $tokens->count() - 1; $index >= 0; --$index) {
         if (!$tokensAnalyzer->isBinaryOperator($index)) {
             continue;
         }
         // skip `declare(foo ==bar)`
         $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)) {
                     continue;
                 }
             }
         }
         // fix white space after operator
         if ($tokens[$index + 1]->isWhitespace()) {
             $content = $tokens[$index + 1]->getContent();
             if (' ' !== $content && false === strpos($content, "\n") && !$tokens[$tokens->getNextNonWhitespace($index + 1)]->isComment()) {
                 $tokens[$index + 1]->setContent(' ');
             }
         } else {
             $tokens->insertAt($index + 1, new Token(array(T_WHITESPACE, ' ')));
         }
         // fix white space before operator
         if ($tokens[$index - 1]->isWhitespace()) {
             $content = $tokens[$index - 1]->getContent();
             if (' ' !== $content && false === strpos($content, "\n") && !$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) {
                 $tokens[$index - 1]->setContent(' ');
             }
         } else {
             $tokens->insertAt($index, new Token(array(T_WHITESPACE, ' ')));
         }
         --$index;
         // skip check for binary operator on the whitespace token that is fixed.
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $namespacesImports = $tokensAnalyzer->getImportUseIndexes(true);
     if (0 === count($namespacesImports)) {
         return;
     }
     $usesOrder = array();
     foreach ($namespacesImports as $uses) {
         $usesOrder = array_replace($usesOrder, $this->getNewOrder(array_reverse($uses), $tokens));
     }
     $usesOrder = array_reverse($usesOrder, true);
     $mapStartToEnd = array();
     foreach ($usesOrder as $use) {
         $mapStartToEnd[$use['startIndex']] = $use['endIndex'];
     }
     // Now insert the new tokens, starting from the end
     foreach ($usesOrder as $index => $use) {
         $declarationTokens = Tokens::fromCode('<?php use ' . $use['namespace'] . ';');
         $declarationTokens->clearRange(0, 2);
         // clear `<?php use `
         $declarationTokens[count($declarationTokens) - 1]->clear();
         // clear `;`
         $declarationTokens->clearEmptyTokens();
         $tokens->overrideRange($index, $mapStartToEnd[$index], $declarationTokens);
         if ($use['group']) {
             // a group import must start with `use` and cannot be part of comma separated import list
             $prev = $tokens->getPrevMeaningfulToken($index);
             if ($tokens[$prev]->equals(',')) {
                 $tokens[$prev]->setContent(';');
                 $tokens->insertAt($prev + 1, new Token(array(T_USE, 'use')));
                 if (!$tokens[$prev + 2]->isWhitespace()) {
                     $tokens->insertAt($prev + 2, new Token(array(T_WHITESPACE, ' ')));
                 }
             }
         }
     }
 }
 /**
  * @param Tokens $tokens
  */
 private function storeImports(Tokens $tokens, $startIndex, $endIndex)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $this->imports = array();
     foreach ($tokensAnalyzer->getImportUseIndexes() as $index) {
         if ($index < $startIndex || $index > $endIndex) {
             continue;
         }
         $import = '';
         while ($index = $tokens->getNextMeaningfulToken($index)) {
             if ($tokens[$index]->equalsAny(array(';', array(CT::T_GROUP_IMPORT_BRACE_OPEN))) || $tokens[$index]->isGivenKind(T_AS)) {
                 break;
             }
             $import .= $tokens[$index]->getContent();
         }
         // Imports group (PHP 7 spec)
         if ($tokens[$index]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_OPEN)) {
             $groupEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_GROUP_IMPORT_BRACE, $index);
             $groupImports = array_map('trim', explode(',', $tokens->generatePartialCode($index + 1, $groupEndIndex - 1)));
             foreach ($groupImports as $groupImport) {
                 $groupImportParts = array_map('trim', explode(' as ', $groupImport));
                 if (2 === count($groupImportParts)) {
                     $this->imports[$groupImportParts[1]] = $import . $groupImportParts[0];
                 } else {
                     $this->imports[] = $import . $groupImport;
                 }
             }
         } elseif ($tokens[$index]->isGivenKind(T_AS)) {
             $aliasIndex = $tokens->getNextMeaningfulToken($index);
             $alias = $tokens[$aliasIndex]->getContent();
             $this->imports[$alias] = $import;
         } else {
             $this->imports[] = $import;
         }
     }
 }
 private function fixAfterToken($index)
 {
     for ($i = $index - 1; $i > 0; --$i) {
         if ($this->tokens[$i]->isGivenKind(T_FUNCTION) && $this->tokensAnalyzer->isLambda($i)) {
             return;
         }
         if ($this->tokens[$i]->isGivenKind(T_CLASS) && $this->tokensAnalyzer->isAnonymousClass($i)) {
             return;
         }
         if ($this->tokens[$i]->isWhitespace() && false !== strpos($this->tokens[$i]->getContent(), "\n")) {
             break;
         }
     }
     $this->removeEmptyLinesAfterLineWithTokenAt($index);
 }
 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, ' ');
         }
     }
 }
예제 #27
0
 private function fixLambdas(Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     for ($index = $tokens->count() - 1; 0 <= $index; --$index) {
         $token = $tokens[$index];
         if (!$token->isGivenKind(T_FUNCTION) || !$tokensAnalyzer->isLambda($index)) {
             continue;
         }
         $nextIndex = $tokens->getNextTokenOfKind($index, array('{'));
         $tokens->ensureWhitespaceAtIndex($nextIndex - 1, 1, ' ');
     }
 }
 /**
  * @param Tokens $tokens
  * @param int    $index
  */
 private function fixElement(Tokens $tokens, $index)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     $repeatIndex = $index;
     while (true) {
         $repeatIndex = $tokens->getNextMeaningfulToken($repeatIndex);
         $repeatToken = $tokens[$repeatIndex];
         if ($tokensAnalyzer->isArray($repeatIndex)) {
             if ($repeatToken->isGivenKind(T_ARRAY)) {
                 $repeatIndex = $tokens->getNextTokenOfKind($repeatIndex, array('('));
                 $repeatIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $repeatIndex);
             } else {
                 $repeatIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $repeatIndex);
             }
             continue;
         }
         if ($repeatToken->equals(';')) {
             return;
             // no repeating found, no fixing needed
         }
         if ($repeatToken->equals(',')) {
             break;
         }
     }
     $start = $tokens->getPrevTokenOfKind($index, array(';', '{', '}'));
     $this->expandElement($tokens, $tokens->getNextMeaningfulToken($start), $tokens->getNextTokenOfKind($index, array(';')));
 }
예제 #29
0
 private function fixIndents(Tokens $tokens)
 {
     $classyTokens = Token::getClassyTokenKinds();
     $classyAndFunctionTokens = array_merge(array(T_FUNCTION), $classyTokens);
     $controlTokens = $this->getControlTokens();
     $indentTokens = array_filter(array_merge($classyAndFunctionTokens, $controlTokens), function ($item) {
         return T_SWITCH !== $item;
     });
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     for ($index = 0, $limit = count($tokens); $index < $limit; ++$index) {
         $token = $tokens[$index];
         // if token is not a structure element - continue
         if (!$token->isGivenKind($indentTokens)) {
             continue;
         }
         // do not change indent for `while` in `do ... while ...`
         if ($token->isGivenKind(T_WHILE) && $tokensAnalyzer->isWhilePartOfDoWhile($index)) {
             continue;
         }
         // do not change import of functions
         if ($token->isGivenKind(T_FUNCTION) && $tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_USE)) {
             continue;
         }
         if ($token->isGivenKind($classyAndFunctionTokens)) {
             $startBraceIndex = $tokens->getNextTokenOfKind($index, array(';', '{'));
             $startBraceToken = $tokens[$startBraceIndex];
         } else {
             $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $index);
             $startBraceIndex = $tokens->getNextNonWhitespace($parenthesisEndIndex);
             $startBraceToken = $tokens[$startBraceIndex];
         }
         // structure without braces block - nothing to do, e.g. do { } while (true);
         if (!$startBraceToken->equals('{')) {
             continue;
         }
         $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startBraceIndex);
         $indent = $this->detectIndent($tokens, $index);
         // fix indent near closing brace
         $tokens->ensureWhitespaceAtIndex($endBraceIndex - 1, 1, "\n" . $indent);
         // fix indent between braces
         $lastCommaIndex = $tokens->getPrevTokenOfKind($endBraceIndex - 1, array(';', '}'));
         $nestLevel = 1;
         for ($nestIndex = $lastCommaIndex; $nestIndex >= $startBraceIndex; --$nestIndex) {
             $nestToken = $tokens[$nestIndex];
             if ($nestToken->equals(')')) {
                 $nestIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nestIndex, false);
                 continue;
             }
             if (1 === $nestLevel && $nestToken->equalsAny(array(';', '}'))) {
                 $nextNonWhitespaceNestIndex = $tokens->getNextNonWhitespace($nestIndex);
                 $nextNonWhitespaceNestToken = $tokens[$nextNonWhitespaceNestIndex];
                 if (!$nextNonWhitespaceNestToken->isComment() && !($nestToken->equals('}') && $nextNonWhitespaceNestToken->equalsAny(array(';', ',', ']', array(CT_ARRAY_SQUARE_BRACE_CLOSE)))) && !($nestToken->equals('}') && $nextNonWhitespaceNestToken->equals('(')) && !($nestToken->equals('}') && $tokens[$nestIndex - 1]->equalsAny(array('"', "'", array(T_CONSTANT_ENCAPSED_STRING))))) {
                     if ($nextNonWhitespaceNestToken->isGivenKind($this->getControlContinuationTokens()) || $nextNonWhitespaceNestToken->isGivenKind(T_CLOSE_TAG) || $nextNonWhitespaceNestToken->isGivenKind(T_WHILE) && $tokensAnalyzer->isWhilePartOfDoWhile($nextNonWhitespaceNestIndex)) {
                         $whitespace = ' ';
                     } else {
                         $nextToken = $tokens[$nestIndex + 1];
                         $nextWhitespace = '';
                         if ($nextToken->isWhitespace()) {
                             $nextWhitespace = rtrim($nextToken->getContent(), " \t");
                             if (strlen($nextWhitespace) && "\n" === $nextWhitespace[strlen($nextWhitespace) - 1]) {
                                 $nextWhitespace = substr($nextWhitespace, 0, -1);
                             }
                         }
                         $whitespace = $nextWhitespace . "\n" . $indent;
                         if (!$nextNonWhitespaceNestToken->equals('}')) {
                             $whitespace .= '    ';
                         }
                     }
                     $tokens->ensureWhitespaceAtIndex($nestIndex + 1, 0, $whitespace);
                 }
             }
             if ($nestToken->equals('}')) {
                 ++$nestLevel;
                 continue;
             }
             if ($nestToken->equals('{')) {
                 --$nestLevel;
                 continue;
             }
         }
         // fix indent near opening brace
         if (isset($tokens[$startBraceIndex + 2]) && $tokens[$startBraceIndex + 2]->equals('}')) {
             $tokens->ensureWhitespaceAtIndex($startBraceIndex + 1, 0, "\n" . $indent);
         } else {
             $nextToken = $tokens[$startBraceIndex + 1];
             $nextNonWhitespaceToken = $tokens[$tokens->getNextNonWhitespace($startBraceIndex)];
             // set indent only if it is not a case, when comment is following { in same line
             if (!$nextNonWhitespaceToken->isComment() || !($nextToken->isWhitespace() && $nextToken->isWhitespace(" \t")) && substr_count($nextToken->getContent(), "\n") === 1) {
                 $tokens->ensureWhitespaceAtIndex($startBraceIndex + 1, 0, "\n" . $indent . '    ');
             }
         }
         if ($token->isGivenKind($classyTokens) && !$tokensAnalyzer->isAnonymousClass($index)) {
             $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, "\n" . $indent);
         } elseif ($token->isGivenKind(T_FUNCTION) && !$tokensAnalyzer->isLambda($index)) {
             $closingParenthesisIndex = $tokens->getPrevTokenOfKind($startBraceIndex, array(')'));
             if (null === $closingParenthesisIndex) {
                 continue;
             }
             $prevToken = $tokens[$closingParenthesisIndex - 1];
             if ($prevToken->isWhitespace() && false !== strpos($prevToken->getContent(), "\n")) {
                 if (!$tokens[$startBraceIndex - 2]->isComment()) {
                     $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' ');
                 }
             } else {
                 $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, "\n" . $indent);
             }
         } else {
             $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' ');
         }
         // reset loop limit due to collection change
         $limit = count($tokens);
     }
 }
 /**
  * @param Tokens $tokens
  * @param int    $classyIndex
  *
  * @return array
  */
 private function getClassyDefinitionInfo(Tokens $tokens, $classyIndex)
 {
     $openIndex = $tokens->getNextTokenOfKind($classyIndex, array('{'));
     $prev = $tokens->getPrevMeaningfulToken($classyIndex);
     $startIndex = $tokens[$prev]->isGivenKind(array(T_FINAL, T_ABSTRACT)) ? $prev : $classyIndex;
     $extends = false;
     $implements = false;
     $anonymousClass = false;
     if (!(defined('T_TRAIT') && $tokens[$classyIndex]->isGivenKind(T_TRAIT))) {
         $extends = $tokens->findGivenKind(T_EXTENDS, $classyIndex, $openIndex);
         $extends = count($extends) ? $this->getClassyInheritanceInfo($tokens, key($extends), $openIndex, 'numberOfExtends') : false;
         if (!$tokens[$classyIndex]->isGivenKind(T_INTERFACE)) {
             $implements = $tokens->findGivenKind(T_IMPLEMENTS, $classyIndex, $openIndex);
             $implements = count($implements) ? $this->getClassyInheritanceInfo($tokens, key($implements), $openIndex, 'numberOfImplements') : false;
             $tokensAnalyzer = new TokensAnalyzer($tokens);
             $anonymousClass = $tokensAnalyzer->isAnonymousClass($classyIndex);
         }
     }
     return array('start' => $startIndex, 'classy' => $classyIndex, 'open' => $openIndex, 'extends' => $extends, 'implements' => $implements, 'anonymousClass' => $anonymousClass);
 }