findSequence() public method

Find a sequence of meaningful tokens and returns the array of their locations.
public findSequence ( array $sequence, integer $start, integer $end = null, boolean | array $caseSensitive = true ) : array | null
$sequence array an array of tokens (same format used by getNextTokenOfKind)
$start integer start index, defaulting to the start of the file
$end integer end index, defaulting to the end of the file
$caseSensitive boolean | array global case sensitiveness or an array of booleans, whose keys should match the ones used in $others. If any is missing, the default case-sensitive comparison is used
return array | null an array containing the tokens matching the sequence elements, indexed by their position
 /**
  * Looks up Tokens sequence for suitable candidates and delivers boundaries information,
  * which can be supplied by other methods in this abstract class.
  *
  * @param string   $functionNameToSearch
  * @param Tokens   $tokens
  * @param int      $start
  * @param int|null $end
  *
  * @return int[]|null returns $functionName, $openParenthesis, $closeParenthesis packed into array
  */
 protected function find($functionNameToSearch, Tokens $tokens, $start = 0, $end = null)
 {
     // make interface consistent with findSequence
     $end = null === $end ? $tokens->count() : $end;
     // find raw sequence which we can analyse for context
     $candidateSequence = array(array(T_STRING, $functionNameToSearch), '(');
     $matches = $tokens->findSequence($candidateSequence, $start, $end, false);
     if (null === $matches) {
         // not found, simply return without further attempts
         return;
     }
     // translate results for humans
     list($functionName, $openParenthesis) = array_keys($matches);
     // first criteria check: shall look like function call
     $functionNamePrefix = $tokens->getPrevMeaningfulToken($functionName);
     $functionNamePrecedingToken = $tokens[$functionNamePrefix];
     if ($functionNamePrecedingToken->isGivenKind(array(T_DOUBLE_COLON, T_NEW, T_OBJECT_OPERATOR, T_FUNCTION))) {
         // this expression is differs from expected, resume
         return $this->find($functionNameToSearch, $tokens, $openParenthesis, $end);
     }
     // second criteria check: ensure namespace is the root one
     if ($functionNamePrecedingToken->isGivenKind(T_NS_SEPARATOR)) {
         $namespaceCandidate = $tokens->getPrevMeaningfulToken($functionNamePrefix);
         $namespaceCandidateToken = $tokens[$namespaceCandidate];
         if ($namespaceCandidateToken->isGivenKind(array(T_NEW, T_STRING, CT::T_NAMESPACE_OPERATOR))) {
             // here can be added complete namespace scan
             // this expression is differs from expected, resume
             return $this->find($functionNameToSearch, $tokens, $openParenthesis, $end);
         }
     }
     // final step: find closing parenthesis
     $closeParenthesis = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis);
     return array($functionName, $openParenthesis, $closeParenthesis);
 }
Ejemplo n.º 2
0
 /**
  * {@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)
 {
     static $searchSequence = array(array(T_VARIABLE, '$this'), array(T_OBJECT_OPERATOR, '->'), array(T_STRING));
     $index = 1;
     $candidate = $tokens->findSequence($searchSequence, $index);
     while (null !== $candidate) {
         end($candidate);
         $index = $this->getAssertCandidate($tokens, key($candidate));
         if (is_array($index)) {
             $index = $this->fixAssert($tokens, $index);
         }
         ++$index;
         $candidate = $tokens->findSequence($searchSequence, $index);
     }
 }
 /**
  * {@inheritdoc}
  */
 public function fix(\SplFileInfo $file, Tokens $tokens)
 {
     $end = $tokens->count() - 1;
     foreach (self::$functions as $map) {
         // the sequence is the function name, followed by "(" and a quoted string
         $seq = array(array(T_STRING, $map[0]), '(', array(T_CONSTANT_ENCAPSED_STRING));
         $currIndex = 0;
         while (null !== $currIndex) {
             $match = $tokens->findSequence($seq, $currIndex, $end, false);
             // did we find a match?
             if (null === $match) {
                 break;
             }
             // findSequence also returns the tokens, but we're only interested in the indexes, i.e.:
             // 0 => function name,
             // 1 => bracket "("
             // 2 => quoted string passed as 1st parameter
             $match = array_keys($match);
             // advance tokenizer cursor
             $currIndex = $match[2];
             // ensure it's a function call (not a method / static call)
             $prev = $tokens->getPrevMeaningfulToken($match[0]);
             if (null === $prev || $tokens[$prev]->isGivenKind(array(T_OBJECT_OPERATOR, T_DOUBLE_COLON))) {
                 continue;
             }
             // ensure the first parameter is just a string (e.g. has nothing appended)
             $next = $tokens->getNextMeaningfulToken($match[2]);
             if (null === $next || !$tokens[$next]->equalsAny(array(',', ')'))) {
                 continue;
             }
             // convert to PCRE
             $string = substr($tokens[$match[2]]->getContent(), 1, -1);
             $quote = substr($tokens[$match[2]]->getContent(), 0, 1);
             $delim = $this->getBestDelimiter($string);
             $preg = $delim . addcslashes($string, $delim) . $delim . 'D' . $map[2];
             // check if the preg is valid
             if (!$this->checkPreg($preg)) {
                 continue;
             }
             // modify function and argument
             $tokens[$match[2]]->setContent($quote . $preg . $quote);
             $tokens[$match[0]]->setContent($map[1]);
         }
     }
 }
 /**
  * Find a function or method matching a given name within certain bounds.
  *
  * @param Tokens $tokens     the Tokens instance
  * @param string $name       the function/Method name
  * @param int    $startIndex the search start index
  * @param int    $endIndex   the search end index
  *
  * @return array|null An associative array, if a match is found:
  *
  *     - nameIndex (int): The index of the function/method name.
  *     - startIndex (int): The index of the function/method start.
  *     - endIndex (int): The index of the function/method end.
  *     - bodyIndex (int): The index of the function/method body.
  *     - modifiers (array): The modifiers as array keys and their index as
  *       the values, e.g. array(T_PUBLIC => 10).
  */
 private function findFunction(Tokens $tokens, $name, $startIndex, $endIndex)
 {
     $function = $tokens->findSequence(array(array(T_FUNCTION), array(T_STRING, $name), '('), $startIndex, $endIndex, false);
     if (null === $function) {
         return;
     }
     // keep only the indexes
     $function = array_keys($function);
     // find previous block, saving method modifiers for later use
     $possibleModifiers = array(T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_ABSTRACT, T_FINAL);
     $modifiers = array();
     $prevBlock = $tokens->getPrevMeaningfulToken($function[0]);
     while (null !== $prevBlock && $tokens[$prevBlock]->isGivenKind($possibleModifiers)) {
         $modifiers[$tokens[$prevBlock]->getId()] = $prevBlock;
         $prevBlock = $tokens->getPrevMeaningfulToken($prevBlock);
     }
     if (isset($modifiers[T_ABSTRACT])) {
         // abstract methods have no body
         $bodyStart = null;
         $funcEnd = $tokens->getNextTokenOfKind($function[2], array(';'));
     } else {
         // find method body start and the end of the function definition
         $bodyStart = $tokens->getNextTokenOfKind($function[2], array('{'));
         $funcEnd = $bodyStart !== null ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $bodyStart) : null;
     }
     return array('nameIndex' => $function[1], 'startIndex' => $prevBlock + 1, 'endIndex' => $funcEnd, 'bodyIndex' => $bodyStart, 'modifiers' => $modifiers);
 }
 /**
  * @param array<string, string> $map
  * @param Tokens                $tokens
  * @param int                   $index
  * @param string                $method
  *
  * @return int|null
  */
 private function fixAssert(array $map, Tokens $tokens, $index, $method)
 {
     $sequence = $tokens->findSequence(array(array(T_VARIABLE, '$this'), array(T_OBJECT_OPERATOR, '->'), array(T_STRING, $method), '('), $index);
     if (null === $sequence) {
         return;
     }
     $sequenceIndexes = array_keys($sequence);
     $sequenceIndexes[4] = $tokens->getNextMeaningfulToken($sequenceIndexes[3]);
     $firstParameterToken = $tokens[$sequenceIndexes[4]];
     if (!$firstParameterToken->isNativeConstant()) {
         return;
     }
     $sequenceIndexes[5] = $tokens->getNextMeaningfulToken($sequenceIndexes[4]);
     // return if first method argument is an expression, not value
     if (!$tokens[$sequenceIndexes[5]]->equals(',')) {
         return;
     }
     $tokens[$sequenceIndexes[2]]->setContent($map[$firstParameterToken->getContent()]);
     $tokens->clearRange($sequenceIndexes[4], $tokens->getNextNonWhitespace($sequenceIndexes[5]) - 1);
     return $sequenceIndexes[5];
 }