Fix bin/publish: use correct .env path for rspade_system Fix bin/publish script: prevent grep exit code 1 from terminating script 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
205 lines
6.8 KiB
PHP
Executable File
205 lines
6.8 KiB
PHP
Executable File
<?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;
|
|
|
|
use PhpCsFixer\Tokenizer\Tokens;
|
|
|
|
abstract class AbstractNoUselessElseFixer extends AbstractFixer
|
|
{
|
|
public function getPriority(): int
|
|
{
|
|
// should be run before NoWhitespaceInBlankLineFixer, NoExtraBlankLinesFixer, BracesFixer and after NoEmptyStatementFixer.
|
|
return 39;
|
|
}
|
|
|
|
protected function isSuperfluousElse(Tokens $tokens, int $index): bool
|
|
{
|
|
$previousBlockStart = $index;
|
|
|
|
do {
|
|
// Check if all 'if', 'else if ' and 'elseif' blocks above this 'else' always end,
|
|
// if so this 'else' is overcomplete.
|
|
[$previousBlockStart, $previousBlockEnd] = $this->getPreviousBlock($tokens, $previousBlockStart);
|
|
|
|
// short 'if' detection
|
|
$previous = $previousBlockEnd;
|
|
if ($tokens[$previous]->equals('}')) {
|
|
$previous = $tokens->getPrevMeaningfulToken($previous);
|
|
}
|
|
|
|
if (
|
|
!$tokens[$previous]->equals(';') // 'if' block doesn't end with semicolon, keep 'else'
|
|
|| $tokens[$tokens->getPrevMeaningfulToken($previous)]->equals('{') // empty 'if' block, keep 'else'
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
$candidateIndex = $tokens->getPrevTokenOfKind(
|
|
$previous,
|
|
[
|
|
';',
|
|
[\T_BREAK],
|
|
[\T_CLOSE_TAG],
|
|
[\T_CONTINUE],
|
|
[\T_EXIT],
|
|
[\T_GOTO],
|
|
[\T_IF],
|
|
[\T_RETURN],
|
|
[\T_THROW],
|
|
]
|
|
);
|
|
|
|
if (null === $candidateIndex || $tokens[$candidateIndex]->equalsAny([';', [\T_CLOSE_TAG], [\T_IF]])) {
|
|
return false;
|
|
}
|
|
|
|
if ($tokens[$candidateIndex]->isGivenKind(\T_THROW)) {
|
|
$previousIndex = $tokens->getPrevMeaningfulToken($candidateIndex);
|
|
|
|
if (!$tokens[$previousIndex]->equalsAny([';', '{'])) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ($this->isInConditional($tokens, $candidateIndex, $previousBlockStart)
|
|
|| $this->isInConditionWithoutBraces($tokens, $candidateIndex, $previousBlockStart)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
// implicit continue, i.e. delete candidate
|
|
} while (!$tokens[$previousBlockStart]->isGivenKind(\T_IF));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Return the first and last token index of the previous block.
|
|
*
|
|
* [0] First is either T_IF, T_ELSE or T_ELSEIF
|
|
* [1] Last is either '}' or ';' / T_CLOSE_TAG for short notation blocks
|
|
*
|
|
* @param int $index T_IF, T_ELSE, T_ELSEIF
|
|
*
|
|
* @return array{int, int}
|
|
*/
|
|
private function getPreviousBlock(Tokens $tokens, int $index): array
|
|
{
|
|
$close = $previous = $tokens->getPrevMeaningfulToken($index);
|
|
// short 'if' detection
|
|
if ($tokens[$close]->equals('}')) {
|
|
$previous = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $close);
|
|
}
|
|
|
|
$open = $tokens->getPrevTokenOfKind($previous, [[\T_IF], [\T_ELSE], [\T_ELSEIF]]);
|
|
if ($tokens[$open]->isGivenKind(\T_IF)) {
|
|
$elseCandidate = $tokens->getPrevMeaningfulToken($open);
|
|
if ($tokens[$elseCandidate]->isGivenKind(\T_ELSE)) {
|
|
$open = $elseCandidate;
|
|
}
|
|
}
|
|
|
|
return [$open, $close];
|
|
}
|
|
|
|
/**
|
|
* @param int $index Index of the token to check
|
|
* @param int $lowerLimitIndex Lower limit index. Since the token to check will always be in a conditional we must stop checking at this index
|
|
*/
|
|
private function isInConditional(Tokens $tokens, int $index, int $lowerLimitIndex): bool
|
|
{
|
|
$candidateIndex = $tokens->getPrevTokenOfKind($index, [')', ';', ':']);
|
|
if ($tokens[$candidateIndex]->equals(':')) {
|
|
return true;
|
|
}
|
|
|
|
if (!$tokens[$candidateIndex]->equals(')')) {
|
|
return false; // token is ';' or close tag
|
|
}
|
|
|
|
// token is always ')' here.
|
|
// If it is part of the condition the token is always in, return false.
|
|
// If it is not it is a nested condition so return true
|
|
$open = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $candidateIndex);
|
|
|
|
return $tokens->getPrevMeaningfulToken($open) > $lowerLimitIndex;
|
|
}
|
|
|
|
/**
|
|
* For internal use only, as it is not perfect.
|
|
*
|
|
* Returns if the token at given index is part of an if/elseif/else statement
|
|
* without {}. Assumes not passing the last `;`/close tag of the statement, not
|
|
* out of range index, etc.
|
|
*
|
|
* @param int $index Index of the token to check
|
|
*/
|
|
private function isInConditionWithoutBraces(Tokens $tokens, int $index, int $lowerLimitIndex): bool
|
|
{
|
|
do {
|
|
if ($tokens[$index]->isComment() || $tokens[$index]->isWhitespace()) {
|
|
$index = $tokens->getPrevMeaningfulToken($index);
|
|
}
|
|
|
|
$token = $tokens[$index];
|
|
if ($token->isGivenKind([\T_IF, \T_ELSEIF, \T_ELSE])) {
|
|
return true;
|
|
}
|
|
|
|
if ($token->equals(';')) {
|
|
return false;
|
|
}
|
|
|
|
if ($token->equals('{')) {
|
|
$index = $tokens->getPrevMeaningfulToken($index);
|
|
|
|
// OK if belongs to: for, do, while, foreach
|
|
// Not OK if belongs to: if, else, elseif
|
|
if ($tokens[$index]->isGivenKind(\T_DO)) {
|
|
--$index;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (!$tokens[$index]->equals(')')) {
|
|
return false; // like `else {`
|
|
}
|
|
|
|
$index = $tokens->findBlockStart(
|
|
Tokens::BLOCK_TYPE_PARENTHESIS_BRACE,
|
|
$index
|
|
);
|
|
|
|
$index = $tokens->getPrevMeaningfulToken($index);
|
|
if ($tokens[$index]->isGivenKind([\T_IF, \T_ELSEIF])) {
|
|
return false;
|
|
}
|
|
} elseif ($token->equals(')')) {
|
|
$type = Tokens::detectBlockType($token);
|
|
$index = $tokens->findBlockStart(
|
|
$type['type'],
|
|
$index
|
|
);
|
|
|
|
$index = $tokens->getPrevMeaningfulToken($index);
|
|
} else {
|
|
--$index;
|
|
}
|
|
} while ($index > $lowerLimitIndex);
|
|
|
|
return false;
|
|
}
|
|
}
|