File "CombineConsecutiveIssetsFixer.php"
Full Path: /var/www/html/back/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/CombineConsecutiveIssetsFixer.php
File size: 5.55 KB
MIME-type: text/x-php
Charset: utf-8
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz RumiĆski <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Fixer\LanguageConstruct;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise.
*/
final class CombineConsecutiveIssetsFixer extends AbstractFixer
{
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Using `isset($var) &&` multiple times should be done in one call.',
[new CodeSample("<?php\n\$a = isset(\$a) && isset(\$b);\n")],
);
}
/**
* {@inheritdoc}
*
* Must run before MultilineWhitespaceBeforeSemicolonsFixer, NoSinglelineWhitespaceBeforeSemicolonsFixer, NoSpacesInsideParenthesisFixer, NoTrailingWhitespaceFixer, NoWhitespaceInBlankLineFixer, SpacesInsideParenthesesFixer.
*/
public function getPriority(): int
{
return 4;
}
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isAllTokenKindsFound([\T_ISSET, \T_BOOLEAN_AND]);
}
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
$tokenCount = $tokens->count();
for ($index = 1; $index < $tokenCount; ++$index) {
if (!$tokens[$index]->isGivenKind(\T_ISSET)
|| !$tokens[$tokens->getPrevMeaningfulToken($index)]->equalsAny(['(', '{', ';', '=', [\T_OPEN_TAG], [\T_BOOLEAN_AND], [\T_BOOLEAN_OR]])) {
continue;
}
$issetInfo = $this->getIssetInfo($tokens, $index);
$issetCloseBraceIndex = end($issetInfo); // ')' token
$insertLocation = (int) prev($issetInfo) + 1; // one index after the previous meaningful of ')'
$booleanAndTokenIndex = $tokens->getNextMeaningfulToken($issetCloseBraceIndex);
while ($tokens[$booleanAndTokenIndex]->isGivenKind(\T_BOOLEAN_AND)) {
$issetIndex = $tokens->getNextMeaningfulToken($booleanAndTokenIndex);
if (!$tokens[$issetIndex]->isGivenKind(\T_ISSET)) {
$index = $issetIndex;
break;
}
// fetch info about the 'isset' statement that we're merging
$nextIssetInfo = $this->getIssetInfo($tokens, $issetIndex);
$nextMeaningfulTokenIndex = $tokens->getNextMeaningfulToken(end($nextIssetInfo));
$nextMeaningfulToken = $tokens[$nextMeaningfulTokenIndex];
if (!$nextMeaningfulToken->equalsAny([')', '}', ';', [\T_CLOSE_TAG], [\T_BOOLEAN_AND], [\T_BOOLEAN_OR]])) {
$index = $nextMeaningfulTokenIndex;
break;
}
// clone what we want to move, do not clone '(' and ')' of the 'isset' statement we're merging
$clones = $this->getTokenClones($tokens, \array_slice($nextIssetInfo, 1, -1));
// clean up now the tokens of the 'isset' statement we're merging
$this->clearTokens($tokens, array_merge($nextIssetInfo, [$issetIndex, $booleanAndTokenIndex]));
// insert the tokens to create the new statement
array_unshift($clones, new Token(','), new Token([\T_WHITESPACE, ' ']));
$tokens->insertAt($insertLocation, $clones);
// correct some counts and offset based on # of tokens inserted
$numberOfTokensInserted = \count($clones);
$tokenCount += $numberOfTokensInserted;
$issetCloseBraceIndex += $numberOfTokensInserted;
$insertLocation += $numberOfTokensInserted;
$booleanAndTokenIndex = $tokens->getNextMeaningfulToken($issetCloseBraceIndex);
}
}
}
/**
* @param list<int> $indices
*/
private function clearTokens(Tokens $tokens, array $indices): void
{
foreach ($indices as $index) {
$tokens->clearTokenAndMergeSurroundingWhitespace($index);
}
}
/**
* @param int $index of T_ISSET
*
* @return non-empty-list<int> indices of meaningful tokens belonging to the isset statement
*/
private function getIssetInfo(Tokens $tokens, int $index): array
{
$openIndex = $tokens->getNextMeaningfulToken($index);
$braceOpenCount = 1;
$meaningfulTokenIndices = [$openIndex];
for ($i = $openIndex + 1;; ++$i) {
if ($tokens[$i]->isWhitespace() || $tokens[$i]->isComment()) {
continue;
}
$meaningfulTokenIndices[] = $i;
if ($tokens[$i]->equals(')')) {
--$braceOpenCount;
if (0 === $braceOpenCount) {
break;
}
} elseif ($tokens[$i]->equals('(')) {
++$braceOpenCount;
}
}
return $meaningfulTokenIndices;
}
/**
* @param list<int> $indices
*
* @return list<Token>
*/
private function getTokenClones(Tokens $tokens, array $indices): array
{
$clones = [];
foreach ($indices as $i) {
$clones[] = clone $tokens[$i];
}
return $clones;
}
}