isAnonymousClass() публичный Метод

Check if there is an anonymous class under given index.
public isAnonymousClass ( integer $index ) : boolean
$index integer
Результат boolean
 /**
  * @dataProvider provideIsAnonymousClassCases
  */
 public function testIsAnonymousClass($source, array $expected)
 {
     $tokensAnalyzer = new TokensAnalyzer(Tokens::fromCode($source));
     foreach ($expected as $index => $expectedValue) {
         $this->assertSame($expectedValue, $tokensAnalyzer->isAnonymousClass($index));
     }
 }
 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);
 }
 /**
  * {@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);
     }
 }
Пример #4
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];
         if ($token->isGivenKind(T_CLASS) && $tokensAnalyzer->isAnonymousClass($i) || $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');
         }
     }
 }
 /**
  * @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);
 }
Пример #6
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);
     }
 }
Пример #7
0
 /**
  * @param Tokens $tokens
  * @param int    $classyIndex Class definition token start index
  */
 private function fixClassyDefinition(Tokens $tokens, $classyIndex)
 {
     $classDefInfo = $this->getClassyDefinitionInfo($tokens, $classyIndex);
     // PSR: class definition open curly brace must go on a new line
     $classDefInfo['open'] = $this->fixClassyDefinitionOpenSpacing($tokens, $classDefInfo['open']);
     // PSR2 4.1 Lists of implements MAY be split across multiple lines, where each subsequent line is indented once.
     // When doing so, the first item in the list MUST be on the next line, and there MUST be only one interface per line.
     if (false !== $classDefInfo['implements']) {
         $this->fixClassyDefinitionImplements($tokens, $classDefInfo['open'], $classDefInfo['implements']);
     }
     if (false !== $classDefInfo['extends']) {
         $this->fixClassyDefinitionExtends($tokens, false === $classDefInfo['implements'] ? $classDefInfo['open'] : 1 + $classDefInfo['implements']['start'], $classDefInfo['extends']);
     }
     if ($classDefInfo['implements']) {
         $end = $classDefInfo['implements']['start'];
     } elseif ($classDefInfo['extends']) {
         $end = $classDefInfo['extends']['start'];
     } else {
         $end = $tokens->getPrevNonWhitespace($classDefInfo['open']);
     }
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     // 4.1 The extends and implements keywords MUST be declared on the same line as the class name.
     $this->makeClassyDefinitionSingleLine($tokens, $tokensAnalyzer->isAnonymousClass($classyIndex) ? $tokens->getPrevMeaningfulToken($classyIndex) : $classDefInfo['start'], $end);
 }
 /**
  * Fix semicolon after closing curly brace if needed.
  *
  * Test for the following cases
  * - just '{' '}' block (following open tag or ';')
  * - if, else, elseif
  * - interface, trait, class (but not anonymous)
  * - catch, finally (but not try)
  * - for, foreach, while (but not 'do - while')
  * - switch
  * - function (declaration, but not lambda)
  * - declare (with '{' '}')
  * - namespace (with '{' '}')
  *
  * @param Tokens $tokens
  * @param int    $index           Semicolon index
  * @param int    $curlyCloseIndex
  */
 private function fixSemicolonAfterCurlyBraceClose(Tokens $tokens, $index, $curlyCloseIndex)
 {
     static $beforeCurlyOpeningKinds = null;
     if (null === $beforeCurlyOpeningKinds) {
         $beforeCurlyOpeningKinds = array(T_ELSE, T_NAMESPACE, T_OPEN_TAG);
         if (defined('T_FINALLY')) {
             $beforeCurlyOpeningKinds[] = T_FINALLY;
         }
     }
     $curlyOpeningIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $curlyCloseIndex, false);
     $beforeCurlyOpening = $tokens->getPrevMeaningfulToken($curlyOpeningIndex);
     if ($tokens[$beforeCurlyOpening]->isGivenKind($beforeCurlyOpeningKinds) || $tokens[$beforeCurlyOpening]->equalsAny(array(';', '{', '}'))) {
         $tokens->clearTokenAndMergeSurroundingWhitespace($index);
         return;
     }
     // check for namespaces and class, interface and trait definitions
     if ($tokens[$beforeCurlyOpening]->isGivenKind(T_STRING)) {
         $classyTest = $tokens->getPrevMeaningfulToken($beforeCurlyOpening);
         while ($tokens[$classyTest]->equals(',') || $tokens[$classyTest]->isGivenKind(array(T_STRING, T_NS_SEPARATOR, T_EXTENDS, T_IMPLEMENTS))) {
             $classyTest = $tokens->getPrevMeaningfulToken($classyTest);
         }
         $tokensAnalyzer = new TokensAnalyzer($tokens);
         if ($tokens[$classyTest]->isGivenKind(T_NAMESPACE) || $tokens[$classyTest]->isClassy() && !$tokensAnalyzer->isAnonymousClass($classyTest)) {
             $tokens->clearTokenAndMergeSurroundingWhitespace($index);
         }
         return;
     }
     // early return check, below only control structures with conditions are fixed
     if (!$tokens[$beforeCurlyOpening]->equals(')')) {
         return;
     }
     $openingBrace = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $beforeCurlyOpening, false);
     $beforeOpeningBrace = $tokens->getPrevMeaningfulToken($openingBrace);
     if ($tokens[$beforeOpeningBrace]->isGivenKind(array(T_IF, T_ELSEIF, T_FOR, T_FOREACH, T_WHILE, T_SWITCH, T_CATCH, T_DECLARE))) {
         $tokens->clearTokenAndMergeSurroundingWhitespace($index);
         return;
     }
     // check for function definition
     if ($tokens[$beforeOpeningBrace]->isGivenKind(T_STRING)) {
         $beforeString = $tokens->getPrevMeaningfulToken($beforeOpeningBrace);
         if ($tokens[$beforeString]->isGivenKind(T_FUNCTION)) {
             $tokens->clearTokenAndMergeSurroundingWhitespace($index);
             // implicit return
         }
     }
 }