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>
247 lines
8.9 KiB
PHP
Executable File
247 lines
8.9 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\Fixer\ControlStructure;
|
|
|
|
use PhpCsFixer\AbstractFixer;
|
|
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
|
|
use PhpCsFixer\Fixer\ConfigurableFixerTrait;
|
|
use PhpCsFixer\FixerConfiguration\AllowedValueSubset;
|
|
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
|
|
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
|
|
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
|
|
use PhpCsFixer\FixerDefinition\CodeSample;
|
|
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
|
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
|
use PhpCsFixer\FixerDefinition\VersionSpecification;
|
|
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
|
|
use PhpCsFixer\Tokenizer\CT;
|
|
use PhpCsFixer\Tokenizer\Token;
|
|
use PhpCsFixer\Tokenizer\Tokens;
|
|
use PhpCsFixer\Tokenizer\TokensAnalyzer;
|
|
|
|
/**
|
|
* @phpstan-type _AutogeneratedInputConfiguration array{
|
|
* after_heredoc?: bool,
|
|
* elements?: list<'arguments'|'array_destructuring'|'arrays'|'match'|'parameters'>,
|
|
* }
|
|
* @phpstan-type _AutogeneratedComputedConfiguration array{
|
|
* after_heredoc: bool,
|
|
* elements: list<'arguments'|'array_destructuring'|'arrays'|'match'|'parameters'>,
|
|
* }
|
|
*
|
|
* @implements ConfigurableFixerInterface<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration>
|
|
*
|
|
* @author Sebastiaan Stok <s.stok@rollerscapes.net>
|
|
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
|
* @author Kuba Werłos <werlos@gmail.com>
|
|
*/
|
|
final class TrailingCommaInMultilineFixer extends AbstractFixer implements ConfigurableFixerInterface
|
|
{
|
|
/** @use ConfigurableFixerTrait<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration> */
|
|
use ConfigurableFixerTrait;
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
public const ELEMENTS_ARRAYS = 'arrays';
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
public const ELEMENTS_ARGUMENTS = 'arguments';
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
public const ELEMENTS_PARAMETERS = 'parameters';
|
|
|
|
private const MATCH_EXPRESSIONS = 'match';
|
|
|
|
private const ARRAY_DESTRUCTURING = 'array_destructuring';
|
|
|
|
public function getDefinition(): FixerDefinitionInterface
|
|
{
|
|
return new FixerDefinition(
|
|
'Arguments lists, array destructuring lists, arrays that are multi-line, `match`-lines and parameters lists must have a trailing comma.',
|
|
[
|
|
new CodeSample("<?php\narray(\n 1,\n 2\n);\n"),
|
|
new CodeSample(
|
|
<<<'SAMPLE'
|
|
<?php
|
|
$x = [
|
|
'foo',
|
|
<<<EOD
|
|
bar
|
|
EOD
|
|
];
|
|
|
|
SAMPLE,
|
|
['after_heredoc' => true]
|
|
),
|
|
new CodeSample("<?php\nfoo(\n 1,\n 2\n);\n", ['elements' => [self::ELEMENTS_ARGUMENTS]]),
|
|
new VersionSpecificCodeSample("<?php\nfunction foo(\n \$x,\n \$y\n)\n{\n}\n", new VersionSpecification(8_00_00), ['elements' => [self::ELEMENTS_PARAMETERS]]),
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*
|
|
* Must run after MultilinePromotedPropertiesFixer.
|
|
*/
|
|
public function getPriority(): int
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
public function isCandidate(Tokens $tokens): bool
|
|
{
|
|
return $tokens->isAnyTokenKindsFound([\T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN, '(', CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN]);
|
|
}
|
|
|
|
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
|
|
{
|
|
return new FixerConfigurationResolver([
|
|
(new FixerOptionBuilder('after_heredoc', 'Whether a trailing comma should also be placed after heredoc end.'))
|
|
->setAllowedTypes(['bool'])
|
|
->setDefault(false) // @TODO 4.0: set to true
|
|
->getOption(),
|
|
(new FixerOptionBuilder('elements', \sprintf('Where to fix multiline trailing comma (PHP >= 8.0 for `%s` and `%s`).', self::ELEMENTS_PARAMETERS, self::MATCH_EXPRESSIONS))) // @TODO: remove text when PHP 8.0+ is required
|
|
->setAllowedTypes(['string[]'])
|
|
->setAllowedValues([
|
|
new AllowedValueSubset([
|
|
self::ARRAY_DESTRUCTURING,
|
|
self::ELEMENTS_ARGUMENTS,
|
|
self::ELEMENTS_ARRAYS,
|
|
self::ELEMENTS_PARAMETERS,
|
|
self::MATCH_EXPRESSIONS,
|
|
]),
|
|
])
|
|
->setDefault([self::ELEMENTS_ARRAYS])
|
|
->getOption(),
|
|
]);
|
|
}
|
|
|
|
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
|
{
|
|
$configuredElements = $this->configuration['elements'];
|
|
$fixArrays = \in_array(self::ELEMENTS_ARRAYS, $configuredElements, true);
|
|
$fixArguments = \in_array(self::ELEMENTS_ARGUMENTS, $configuredElements, true);
|
|
$fixParameters = \PHP_VERSION_ID >= 8_00_00 && \in_array(self::ELEMENTS_PARAMETERS, $configuredElements, true); // @TODO: drop condition when PHP 8.0+ is required
|
|
$fixMatch = \PHP_VERSION_ID >= 8_00_00 && \in_array(self::MATCH_EXPRESSIONS, $configuredElements, true); // @TODO: drop condition when PHP 8.0+ is required
|
|
$fixDestructuring = \in_array(self::ARRAY_DESTRUCTURING, $configuredElements, true);
|
|
|
|
for ($index = $tokens->count() - 1; $index >= 0; --$index) {
|
|
if ($tokens[$index]->isGivenKind(CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN)) {
|
|
if ($fixDestructuring) { // array destructing short syntax
|
|
$this->fixBlock($tokens, $index);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if ($tokens[$index]->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) {
|
|
if ($fixArrays) { // array short syntax
|
|
$this->fixBlock($tokens, $index);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (!$tokens[$index]->equals('(')) {
|
|
continue;
|
|
}
|
|
|
|
$prevIndex = $tokens->getPrevMeaningfulToken($index);
|
|
|
|
if ($tokens[$prevIndex]->isGivenKind(\T_ARRAY)) {
|
|
if ($fixArrays) { // array long syntax
|
|
$this->fixBlock($tokens, $index);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if ($tokens[$prevIndex]->isGivenKind(\T_LIST)) {
|
|
if ($fixDestructuring || $fixArguments) { // array destructing long syntax
|
|
$this->fixBlock($tokens, $index);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if ($fixMatch && $tokens[$prevIndex]->isGivenKind(\T_MATCH)) {
|
|
$this->fixBlock($tokens, $tokens->getNextTokenOfKind($index, ['{']));
|
|
|
|
continue;
|
|
}
|
|
|
|
$prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex);
|
|
|
|
if ($fixArguments
|
|
&& $tokens[$prevIndex]->equalsAny([']', [\T_CLASS], [\T_STRING], [\T_VARIABLE], [\T_STATIC], [\T_ISSET], [\T_UNSET], [\T_LIST]])
|
|
&& !$tokens[$prevPrevIndex]->isGivenKind(\T_FUNCTION)
|
|
) {
|
|
$this->fixBlock($tokens, $index);
|
|
|
|
continue;
|
|
}
|
|
|
|
if (
|
|
$fixParameters
|
|
&& (
|
|
$tokens[$prevIndex]->isGivenKind(\T_STRING)
|
|
&& $tokens[$prevPrevIndex]->isGivenKind(\T_FUNCTION)
|
|
|| $tokens[$prevIndex]->isGivenKind([\T_FN, \T_FUNCTION])
|
|
)
|
|
) {
|
|
$this->fixBlock($tokens, $index);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function fixBlock(Tokens $tokens, int $startIndex): void
|
|
{
|
|
$tokensAnalyzer = new TokensAnalyzer($tokens);
|
|
|
|
if (!$tokensAnalyzer->isBlockMultiline($tokens, $startIndex)) {
|
|
return;
|
|
}
|
|
|
|
$blockType = Tokens::detectBlockType($tokens[$startIndex]);
|
|
$endIndex = $tokens->findBlockEnd($blockType['type'], $startIndex);
|
|
|
|
$beforeEndIndex = $tokens->getPrevMeaningfulToken($endIndex);
|
|
if (!$tokens->isPartialCodeMultiline($beforeEndIndex, $endIndex)) {
|
|
return;
|
|
}
|
|
$beforeEndToken = $tokens[$beforeEndIndex];
|
|
|
|
// if there is some item between braces then add `,` after it
|
|
if (
|
|
$startIndex !== $beforeEndIndex && !$beforeEndToken->equals(',')
|
|
&& (true === $this->configuration['after_heredoc'] || !$beforeEndToken->isGivenKind(\T_END_HEREDOC))
|
|
) {
|
|
$tokens->insertAt($beforeEndIndex + 1, new Token(','));
|
|
|
|
$endToken = $tokens[$endIndex];
|
|
|
|
if (!$endToken->isComment() && !$endToken->isWhitespace()) {
|
|
$tokens->ensureWhitespaceAtIndex($endIndex, 1, ' ');
|
|
}
|
|
}
|
|
}
|
|
}
|