Exemple #1
0
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) {
         $token = $tokens[$index];
         if (!$token->isGivenKind(T_RETURN)) {
             continue;
         }
         $prevNonWhitespaceToken = $tokens[$tokens->getPrevNonWhitespace($index)];
         if (!$prevNonWhitespaceToken->equalsAny(array(';', '}'))) {
             continue;
         }
         $prevToken = $tokens[$index - 1];
         if ($prevToken->isWhitespace()) {
             $parts = explode("\n", $prevToken->getContent());
             $countParts = count($parts);
             if (1 === $countParts) {
                 $prevToken->setContent(rtrim($prevToken->getContent(), " \t") . "\n\n");
             } elseif (count($parts) <= 2) {
                 $prevToken->setContent("\n" . $prevToken->getContent());
             }
         } else {
             $tokens->insertAt($index, new Token(array(T_WHITESPACE, "\n\n")));
             ++$index;
             ++$limit;
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = $tokens->count() - 1; $index >= 0; --$index) {
         $token = $tokens[$index];
         if (!$token->isGivenKind(T_NEW)) {
             continue;
         }
         $nextIndex = $tokens->getNextTokenOfKind($index, array(':', ';', ',', '(', ')', '[', ']', 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->isGivenKind(T_WHITESPACE)) {
             $nextIndex = $tokens->getNextNonWhitespace($nextIndex);
             $nextToken = $tokens[$nextIndex];
         }
         // new statement with () - nothing to do
         if ($nextToken->equals('(')) {
             continue;
         }
         $meaningBeforeNextIndex = $tokens->getPrevNonWhitespace($nextIndex);
         $tokens->insertAt($meaningBeforeNextIndex + 1, array(new Token('('), new Token(')')));
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     static $nativeFunctionNames = null;
     if (null === $nativeFunctionNames) {
         $nativeFunctionNames = $this->getNativeFunctionNames();
     }
     for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) {
         // test if we are at a function all
         if (!$tokens[$index]->isGivenKind(T_STRING)) {
             continue;
         }
         $next = $tokens->getNextMeaningfulToken($index);
         if (!$tokens[$next]->equals('(')) {
             $index = $next;
             continue;
         }
         $functionNamePrefix = $tokens->getPrevMeaningfulToken($index);
         if ($tokens[$functionNamePrefix]->isGivenKind(array(T_DOUBLE_COLON, T_NEW, T_OBJECT_OPERATOR, T_FUNCTION))) {
             continue;
         }
         // do not though the function call if it is to a function in a namespace other than the default
         if ($tokens[$functionNamePrefix]->isGivenKind(T_NS_SEPARATOR) && $tokens[$tokens->getPrevMeaningfulToken($functionNamePrefix)]->isGivenKind(T_STRING)) {
             continue;
         }
         // test if the function call is to a native PHP function
         $lower = strtolower($tokens[$index]->getContent());
         if (!array_key_exists($lower, $nativeFunctionNames)) {
             continue;
         }
         $tokens[$index]->setContent($nativeFunctionNames[$lower]);
         $index = $next;
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     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, ' ')));
             }
         }
     }
 }
 /**
  * Inject into the text placeholders of candidates of vertical alignment.
  *
  * @param Tokens $tokens
  */
 private function injectAlignmentPlaceholders(Tokens $tokens)
 {
     $deepestLevel = 0;
     $limit = $tokens->count();
     for ($index = 0; $index < $limit; ++$index) {
         $token = $tokens[$index];
         if ($token->equals('=')) {
             $token->setContent(sprintf(self::ALIGNABLE_PLACEHOLDER, $deepestLevel) . $token->getContent());
             continue;
         }
         if ($token->isGivenKind(T_FUNCTION)) {
             ++$deepestLevel;
             continue;
         }
         if ($token->equals('(')) {
             $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index);
             continue;
         }
         if ($token->equals('[')) {
             $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $index);
             continue;
         }
         if ($token->isGivenKind(CT_ARRAY_SQUARE_BRACE_OPEN)) {
             $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index);
             continue;
         }
     }
     $this->deepestLevel = $deepestLevel;
 }
 /**
  * Returns the attributes of the class under the given index.
  *
  * The array has the following items:
  * 'abstract'   bool
  * 'final'      bool
  * 'name'       string
  * 'extends'    null|string
  * 'implements' string[]
  *
  * @param int $index Token index of the method (T_FUNCTION)
  *
  * @return array
  */
 public static function getClassAttributes(Tokens $tokens, $index)
 {
     $token = $tokens[$index];
     if (!$token->isGivenKind(T_CLASS)) {
         throw new \LogicException(sprintf('No T_CLASS at given index %d, got %s', $index, $token->getName()));
     }
     $attributes = array('abstract' => false, 'final' => false, 'name' => null, 'extends' => null, 'implements' => []);
     // class-modifier
     for ($i = $index; $i >= 0; $i--) {
         $tokenIndex = $tokens->getPrevMeaningfulToken($i);
         if (null === $tokenIndex) {
             break;
         }
         $i = $tokenIndex;
         $token = $tokens[$tokenIndex];
         if ($token->isGivenKind(T_FINAL)) {
             $attributes['final'] = true;
             continue;
         }
         if ($token->isGivenKind(T_ABSTRACT)) {
             $attributes['abstract'] = true;
             continue;
         }
         // found a meaningful token that is not part of
         // the class signature; stop looking
         break;
     }
     $current = 'name';
     for ($i = $index; $i < $tokens->count(); $i++) {
         $tokenIndex = $tokens->getNextMeaningfulToken($i);
         if (null === $tokenIndex) {
             break;
         }
         $i = $tokenIndex;
         $token = $tokens[$tokenIndex];
         // name
         if ($token->isGivenKind(T_STRING)) {
             if (is_array($attributes[$current])) {
                 $attributes[$current][] = $token->getContent();
             } else {
                 $attributes[$current] = $token->getContent();
             }
             continue;
         }
         // class-base-clause
         if ($token->isGivenKind(T_EXTENDS)) {
             $current = 'extends';
             continue;
         }
         // class-interface-clause
         if ($token->isGivenKind(T_IMPLEMENTS)) {
             $current = 'implements';
             continue;
         }
         // found a meaningful token that is not part of
         // the class signature; stop looking
         break;
     }
     return $attributes;
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = 0, $c = $tokens->count(); $index < $c; ++$index) {
         if ($tokens[$index]->isGivenKind(array(T_ARRAY, CT_ARRAY_SQUARE_BRACE_OPEN))) {
             self::fixArray($tokens, $index);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($i = 0, $l = $tokens->count(); $i < $l; ++$i) {
         if ($tokens[$i]->isGivenKind(T_FUNCTION)) {
             $this->fixFunctionDefinition($tokens, $i);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = $tokens->count() - 1; $index >= 0; --$index) {
         if ($tokens[$index]->isGivenKind(array(T_ARRAY, CT_ARRAY_SQUARE_BRACE_OPEN))) {
             $this->fixSpacing($index, $tokens);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $tokensAnalyzer = new TokensAnalyzer($tokens);
     for ($index = 0, $c = $tokens->count(); $index < $c; ++$index) {
         if ($tokensAnalyzer->isArray($index)) {
             $this->fixArray($tokens, $index);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = $tokens->count() - 1; $index >= 0; --$index) {
         $token = $tokens[$index];
         if ($token->isGivenKind(T_NAMESPACE)) {
             $this->fixLinesBeforeNamespace($tokens, $index, 2);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = $tokens->count() - 1; $index >= 0; --$index) {
         $token = $tokens[$index];
         if ($token->equals('(') && !$tokens[$index - 1]->isGivenKind(T_ARRAY)) {
             $this->fixFunction($tokens, $index);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) {
         if (!$tokens[$index]->isCast()) {
             continue;
         }
         $tokens[$index]->setContent(strtolower($tokens[$index]->getContent()));
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) {
         $token = $tokens[$index];
         if (!$token->isGivenKind(T_NAMESPACE)) {
             continue;
         }
         $this->fixLinesBeforeNamespace($tokens, $index, 1);
     }
 }
 /**
  * {@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);
     }
 }
 /**
  * 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);
 }
 private function assertTokens(Tokens $expectedTokens, Tokens $inputTokens)
 {
     foreach ($expectedTokens as $index => $expectedToken) {
         $inputToken = $inputTokens[$index];
         $this->assertTrue($expectedToken->equals($inputToken), sprintf('The token at index %d must be %s, got %s', $index, $expectedToken->toJson(), $inputToken->toJson()));
     }
     $this->assertSame($expectedTokens->count(), $inputTokens->count(), 'The collection must have the same length than the expected one.');
     $foundTokenKinds = array_keys(AccessibleObject::create($expectedTokens)->foundTokenKinds);
     foreach ($foundTokenKinds as $tokenKind) {
         $this->assertTrue($inputTokens->isTokenKindFound($tokenKind), sprintf('The token kind %s must be found in fixed tokens collection.', $tokenKind));
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = $tokens->count() - 1; 0 <= $index; --$index) {
         $token = $tokens[$index];
         if (!$token->isGivenKind(CT_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')));
     }
 }
 private function assertTokens(Tokens $expectedTokens, Tokens $tokens)
 {
     foreach ($expectedTokens as $index => $expectedToken) {
         $token = $tokens[$index];
         $expectedPrototype = $expectedToken->getPrototype();
         if (is_array($expectedPrototype)) {
             unset($expectedPrototype[2]);
             // don't compare token lines as our token mutations don't deal with line numbers
         }
         $this->assertTrue($token->equals($expectedPrototype), sprintf('The token at index %d should be %s, got %s', $index, json_encode($expectedPrototype), $token->toJson()));
     }
     $this->assertSame($expectedTokens->count(), $tokens->count(), 'The collection should have the same length than the expected one');
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) {
         $skipToIndex = $this->fixAssertNotSame($tokens, $index);
         if (null !== $skipToIndex) {
             $index = $skipToIndex;
         }
         $skipToIndex = $this->fixAssertSame($tokens, $index);
         if (null !== $skipToIndex) {
             $index = $skipToIndex;
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $count = $tokens->count();
     if (0 === $count) {
         return;
     }
     $token = $tokens[$count - 1];
     if ($token->isWhitespace() || $token->isGivenKind(T_INLINE_HTML)) {
         $token->setContent(rtrim($token->getContent()) . "\n");
     } else {
         $tokens->insertAt($count, new Token(array(T_WHITESPACE, "\n")));
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokensOrg)
 {
     $content = $tokensOrg->generateCode();
     // replace all <? with <?php to replace all short open tags even without short_open_tag option enabled
     $newContent = preg_replace('/<\\?(\\s|$)/', '<?php$1', $content, -1, $count);
     if (!$count) {
         return;
     }
     /* the following code is magic to revert previous replacements which should NOT be replaced, for example incorrectly replacing
      * > echo '<? ';
      * with
      * > echo '<?php ';
      */
     $tokens = Tokens::fromCode($newContent);
     $tokensOldContent = '';
     $tokensOldContentLength = 0;
     foreach ($tokens as $token) {
         if ($token->isGivenKind(T_OPEN_TAG)) {
             $tokenContent = $token->getContent();
             if ('<?php' !== substr($content, $tokensOldContentLength, 5)) {
                 $tokenContent = '<? ';
             }
             $tokensOldContent .= $tokenContent;
             $tokensOldContentLength += strlen($tokenContent);
             continue;
         }
         if ($token->isGivenKind(array(T_COMMENT, T_DOC_COMMENT, T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_STRING))) {
             $tokenContent = '';
             $tokenContentLength = 0;
             $parts = explode('<?php', $token->getContent());
             $iLast = count($parts) - 1;
             foreach ($parts as $i => $part) {
                 $tokenContent .= $part;
                 $tokenContentLength += strlen($part);
                 if ($i !== $iLast) {
                     if ('<?php' === substr($content, $tokensOldContentLength + $tokenContentLength, 5)) {
                         $tokenContent .= '<?php';
                         $tokenContentLength += 5;
                     } else {
                         $tokenContent .= '<?';
                         $tokenContentLength += 2;
                     }
                 }
             }
             $token->setContent($tokenContent);
         }
         $tokensOldContent .= $token->getContent();
         $tokensOldContentLength += strlen($token->getContent());
     }
     $tokensOrg->overrideRange(0, $tokensOrg->count() - 1, $tokens);
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     static $map = null;
     if (null === $map) {
         $token = array('true' => new Token(array(T_STRING, 'true')), 'null' => new Token(array(T_STRING, 'null')));
         $map = array('in_array' => array(null, null, $token['true']), 'base64_decode' => array(null, $token['true']), 'array_search' => array(null, null, $token['true']), 'array_keys' => array(null, null, $token['true']), 'mb_detect_encoding' => array(null, array(new Token(array(T_STRING, 'mb_detect_order')), new Token('('), new Token(')')), $token['true']));
     }
     for ($index = $tokens->count() - 1; 0 <= $index; --$index) {
         $token = $tokens[$index];
         if ($token->isGivenKind(T_STRING) && isset($map[$token->getContent()])) {
             $this->fixFunction($tokens, $index, $map[$token->getContent()]);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     for ($index = $tokens->count() - 1; $index >= 0; --$index) {
         $token = $tokens[$index];
         if ($token->equals('.')) {
             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) {
         if ($tokensAnalyzer->isUnarySuccessorOperator($index)) {
             $tokens->removeLeadingWhitespace($index);
             continue;
         }
         if ($tokensAnalyzer->isUnaryPredecessorOperator($index)) {
             $tokens->removeTrailingWhitespace($index);
             continue;
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     foreach ($this->configuration as $methodBefore => $methodAfter) {
         for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) {
             $sequence = $tokens->findSequence(array(array(T_VARIABLE, '$this'), array(T_OBJECT_OPERATOR, '->'), array(T_STRING, $methodBefore), '('), $index);
             if (null === $sequence) {
                 break;
             }
             $sequenceIndexes = array_keys($sequence);
             $tokens[$sequenceIndexes[2]]->setContent($methodAfter);
             $index = $sequenceIndexes[3];
         }
     }
 }
 /**
  * {@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)
 {
     for ($i = 0, $c = $tokens->count(); $i < $c; ++$i) {
         if (!$tokens[$i]->isClassy()) {
             continue;
         }
         $nameIndex = $tokens->getNextTokenOfKind($i, array(array(T_STRING)));
         $startIndex = $tokens->getNextTokenOfKind($nameIndex, array('{'));
         $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startIndex);
         $name = $tokens[$nameIndex]->getContent();
         $this->replaceNameOccurrences($tokens, $name, $startIndex, $endIndex);
         // continue after the class declaration
         $i = $endIndex;
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     static $castMap = array('boolean' => 'bool', 'integer' => 'int', 'double' => 'float', 'real' => 'float');
     for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) {
         if (!$tokens[$index]->isCast()) {
             continue;
         }
         $castFrom = trim(substr($tokens[$index]->getContent(), 1, -1));
         $castFromLowered = strtolower($castFrom);
         if (!array_key_exists($castFromLowered, $castMap)) {
             continue;
         }
         $tokens[$index]->setContent(str_replace($castFrom, $castMap[$castFromLowered], $tokens[$index]->getContent()));
     }
 }
 /**
  * {@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, ' ')));
         }
     }
 }