private function fixUseStatements(Tokens $tokens) { $classIndexes = array_keys($tokens->findGivenKind(T_CLASS)); if ($tokens->findSequence([[T_STRING, 'OptionsResolverInterface']], array_pop($classIndexes))) { return $this->addUseStatement($tokens, ['Symfony', 'Component', 'OptionsResolver', 'OptionsResolver']); } $this->renameUseStatements($tokens, ['Symfony', 'Component', 'OptionsResolver', 'OptionsResolverInterface'], 'OptionsResolver'); }
protected function getUseStatements(Tokens $tokens, array $fqcn) { $sequence = [[T_USE]]; foreach ($fqcn as $component) { $sequence = array_merge($sequence, [[T_STRING, $component], [T_NS_SEPARATOR]]); } $sequence[count($sequence) - 1] = ';'; return $tokens->findSequence($sequence); }
protected function renameConstants(Tokens $tokens, $className, $old, $new) { $matchedTokens = $tokens->findSequence([[T_STRING, $className], [T_DOUBLE_COLON], [T_STRING, $old]]); if (null === $matchedTokens) { return; } $matchedTokensIndexes = array_keys($matchedTokens); $matchedTokens[$matchedTokensIndexes[count($matchedTokensIndexes) - 1]]->setContent($new); $this->renameConstants($tokens, $className, $old, $new); }
/** * @param Tokens $tokens * @param string[]|string $fqcn * * @return null|array */ protected function getUseStatements(Tokens $tokens, $fqcn) { if (false === is_array($fqcn)) { $fqcn = explode('\\', $fqcn); } $sequence = array(array(T_USE)); foreach ($fqcn as $component) { $sequence = array_merge($sequence, array(array(T_STRING, $component), array(T_NS_SEPARATOR))); } $sequence[count($sequence) - 1] = ';'; return $tokens->findSequence($sequence); }
/** * {@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) { $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]); } } }
private function fixAssertSame(Tokens $tokens, $index) { static $map = array('false' => 'assertFalse', 'null' => 'assertNull', 'true' => 'assertTrue'); $sequence = $tokens->findSequence(array(array(T_VARIABLE, '$this'), array(T_OBJECT_OPERATOR, '->'), array(T_STRING, 'assertSame'), '('), $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->getNextNonWhitespace($sequenceIndexes[4]); $tokens[$sequenceIndexes[2]]->setContent($map[$firstParameterToken->getContent()]); $tokens->clearRange($sequenceIndexes[4], $tokens->getNextNonWhitespace($sequenceIndexes[5]) - 1); return $sequenceIndexes[5]; }
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]); 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]; }
private function fixOptionNames(Tokens $tokens, $fieldNameTokens, $oldName, $newName, $start = 0) { $matchedTokens = $tokens->findSequence(array_merge([[T_OBJECT_OPERATOR], [T_STRING, 'add'], '(', [T_CONSTANT_ENCAPSED_STRING], ','], $fieldNameTokens, [',']), $start); if (null === $matchedTokens) { return; } $matchedTokenIndexes = array_keys($matchedTokens); $isArray = $tokens->isArray($index = $tokens->getNextMeaningfulToken(end($matchedTokenIndexes))); if (!$isArray) { return; } do { $index = $tokens->getNextMeaningfulToken($index); $token = $tokens[$index]; if (!$token->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) { continue; } if ("'{$oldName}'" === $token->getContent()) { $token->setContent("'{$newName}'"); } } while (!in_array($token->getContent(), [')', ']'])); $this->fixOptionNames($tokens, $fieldNameTokens, $oldName, $newName, $index); }
private function matchTypeName(Tokens $tokens, $name) { return $tokens->findSequence([[T_OBJECT_OPERATOR], [T_STRING, 'add'], '(', [T_CONSTANT_ENCAPSED_STRING], ',', [T_CONSTANT_ENCAPSED_STRING, sprintf("'%s'", strtolower($name))]]); }
private function getGetRequestSequence(Tokens $tokens, $start, $end) { return $tokens->findSequence([[T_VARIABLE, '$this'], [T_OBJECT_OPERATOR], [T_STRING, 'getRequest'], '(', ')'], $start, $end); }
/** * 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); }
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; } $function = array_keys($function); $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])) { $bodyStart = null; $funcEnd = $tokens->getNextTokenOfKind($function[2], array(';')); } else { $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, ); }
private function matchGetNameMethod(Tokens $tokens) { return $tokens->findSequence([[T_PUBLIC, 'public'], [T_FUNCTION], [T_STRING, 'getName'], '(', ')']); }
private function matchGetParentMethod(Tokens $tokens, $name) { return $tokens->findSequence([[T_PUBLIC, 'public'], [T_FUNCTION], [T_STRING, 'getParent'], '(', ')', '{', [T_RETURN], [T_CONSTANT_ENCAPSED_STRING, sprintf("'%s'", strtolower($name))], ';', '}']); }