Missing dependancies

This commit is contained in:
tokslaw7
2023-06-21 12:19:22 +00:00
parent fbf3f180c2
commit 421f25c80d
2356 changed files with 342670 additions and 4743 deletions
@@ -0,0 +1,295 @@
<?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\Semicolon;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
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\Preg;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
/**
* @author Graham Campbell <hello@gjcampbell.co.uk>
* @author Egidijus Girčys <e.gircys@gmail.com>
*/
final class MultilineWhitespaceBeforeSemicolonsFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface
{
/**
* @internal
*/
public const STRATEGY_NO_MULTI_LINE = 'no_multi_line';
/**
* @internal
*/
public const STRATEGY_NEW_LINE_FOR_CHAINED_CALLS = 'new_line_for_chained_calls';
/**
* {@inheritdoc}
*/
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Forbid multi-line whitespace before the closing semicolon or move the semicolon to the new line for chained calls.',
[
new CodeSample(
'<?php
function foo () {
return 1 + 2
;
}
'
),
new CodeSample(
'<?php
$this->method1()
->method2()
->method(3);
?>
',
['strategy' => self::STRATEGY_NEW_LINE_FOR_CHAINED_CALLS]
),
]
);
}
/**
* {@inheritdoc}
*
* Must run before SpaceAfterSemicolonFixer.
* Must run after CombineConsecutiveIssetsFixer, GetClassToClassKeywordFixer, NoEmptyStatementFixer, SimplifiedIfReturnFixer, SingleImportPerStatementFixer.
*/
public function getPriority(): int
{
return 0;
}
/**
* {@inheritdoc}
*/
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(';');
}
/**
* {@inheritdoc}
*/
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder(
'strategy',
'Forbid multi-line whitespace or move the semicolon to the new line for chained calls.'
))
->setAllowedValues([self::STRATEGY_NO_MULTI_LINE, self::STRATEGY_NEW_LINE_FOR_CHAINED_CALLS])
->setDefault(self::STRATEGY_NO_MULTI_LINE)
->getOption(),
]);
}
/**
* {@inheritdoc}
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
if (self::STRATEGY_NEW_LINE_FOR_CHAINED_CALLS === $this->configuration['strategy']) {
$this->applyChainedCallsFix($tokens);
return;
}
if (self::STRATEGY_NO_MULTI_LINE === $this->configuration['strategy']) {
$this->applyNoMultiLineFix($tokens);
}
}
private function applyNoMultiLineFix(Tokens $tokens): void
{
$lineEnding = $this->whitespacesConfig->getLineEnding();
foreach ($tokens as $index => $token) {
if (!$token->equals(';')) {
continue;
}
$previousIndex = $index - 1;
$previous = $tokens[$previousIndex];
if (!$previous->isWhitespace() || !str_contains($previous->getContent(), "\n")) {
continue;
}
$content = $previous->getContent();
if (str_starts_with($content, $lineEnding) && $tokens[$index - 2]->isComment()) {
$tokens->ensureWhitespaceAtIndex($previousIndex, 0, $lineEnding);
} else {
$tokens->clearAt($previousIndex);
}
}
}
private function applyChainedCallsFix(Tokens $tokens): void
{
for ($index = \count($tokens) - 1; $index >= 0; --$index) {
// continue if token is not a semicolon
if (!$tokens[$index]->equals(';')) {
continue;
}
// get the indent of the chained call, null in case it's not a chained call
$indent = $this->findWhitespaceBeforeFirstCall($index - 1, $tokens);
if (null === $indent) {
continue;
}
// unset semicolon
$tokens->clearAt($index);
// find the line ending token index after the semicolon
$index = $this->getNewLineIndex($index, $tokens);
// line ending string of the last method call
$lineEnding = $this->whitespacesConfig->getLineEnding();
// appended new line to the last method call
$newline = new Token([T_WHITESPACE, $lineEnding.$indent]);
// insert the new line with indented semicolon
$tokens->insertAt($index, [$newline, new Token(';')]);
}
}
/**
* Find the index for the new line. Return the given index when there's no new line.
*/
private function getNewLineIndex(int $index, Tokens $tokens): int
{
$lineEnding = $this->whitespacesConfig->getLineEnding();
for ($index, $count = \count($tokens); $index < $count; ++$index) {
if (false !== strstr($tokens[$index]->getContent(), $lineEnding)) {
return $index;
}
}
return $index;
}
/**
* Checks if the semicolon closes a chained call and returns the whitespace of the first call at $index.
* i.e. it will return the whitespace marked with '____' in the example underneath.
*
* ..
* ____$this->methodCall()
* ->anotherCall();
* ..
*/
private function findWhitespaceBeforeFirstCall(int $index, Tokens $tokens): ?string
{
// semicolon followed by a closing bracket?
if (!$tokens[$index]->equals(')')) {
return null;
}
// find opening bracket
$openingBrackets = 1;
for (--$index; $index > 0; --$index) {
if ($tokens[$index]->equals(')')) {
++$openingBrackets;
continue;
}
if ($tokens[$index]->equals('(')) {
if (1 === $openingBrackets) {
break;
}
--$openingBrackets;
}
}
// method name
if (!$tokens[--$index]->isGivenKind(T_STRING)) {
return null;
}
// ->, ?-> or ::
if (!$tokens[--$index]->isObjectOperator() && !$tokens[$index]->isGivenKind(T_DOUBLE_COLON)) {
return null;
}
// white space
if (!$tokens[--$index]->isGivenKind(T_WHITESPACE)) {
return null;
}
$closingBrackets = 0;
for ($index; $index >= 0; --$index) {
if ($tokens[$index]->equals(')')) {
++$closingBrackets;
}
if ($tokens[$index]->equals('(')) {
--$closingBrackets;
}
// must be the variable of the first call in the chain
if ($tokens[$index]->isGivenKind([T_VARIABLE, T_RETURN, T_STRING]) && 0 === $closingBrackets) {
if ($tokens[--$index]->isGivenKind(T_WHITESPACE)
|| $tokens[$index]->isGivenKind(T_OPEN_TAG)) {
return $this->getIndentAt($tokens, $index);
}
}
}
return null;
}
private function getIndentAt(Tokens $tokens, int $index): ?string
{
$content = '';
$lineEnding = $this->whitespacesConfig->getLineEnding();
// find line ending token
for ($index; $index > 0; --$index) {
if (false !== strstr($tokens[$index]->getContent(), $lineEnding)) {
break;
}
}
if ($tokens[$index]->isWhitespace()) {
$content = $tokens[$index]->getContent();
--$index;
}
if ($tokens[$index]->isGivenKind(T_OPEN_TAG)) {
$content = $tokens[$index]->getContent().$content;
}
if (1 === Preg::match('/\R{1}(\h*)$/', $content, $matches)) {
return $matches[1];
}
return null;
}
}
@@ -0,0 +1,195 @@
<?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\Semicolon;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixer\Tokenizer\TokensAnalyzer;
/**
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
*/
final class NoEmptyStatementFixer extends AbstractFixer
{
/**
* {@inheritdoc}
*/
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Remove useless (semicolon) statements.',
[
new CodeSample("<?php \$a = 1;;\n"),
new CodeSample("<?php echo 1;2;\n"),
new CodeSample("<?php while(foo()){\n continue 1;\n}\n"),
]
);
}
/**
* {@inheritdoc}
*
* Must run before BracesFixer, CombineConsecutiveUnsetsFixer, EmptyLoopBodyFixer, MultilineWhitespaceBeforeSemicolonsFixer, NoExtraBlankLinesFixer, NoMultipleStatementsPerLineFixer, NoSinglelineWhitespaceBeforeSemicolonsFixer, NoTrailingWhitespaceFixer, NoUselessElseFixer, NoUselessReturnFixer, NoWhitespaceInBlankLineFixer, ReturnAssignmentFixer, SpaceAfterSemicolonFixer, SwitchCaseSemicolonToColonFixer.
* Must run after NoUselessSprintfFixer.
*/
public function getPriority(): int
{
return 40;
}
/**
* {@inheritdoc}
*/
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(';');
}
/**
* {@inheritdoc}
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) {
if ($tokens[$index]->isGivenKind([T_BREAK, T_CONTINUE])) {
$index = $tokens->getNextMeaningfulToken($index);
if ($tokens[$index]->equals([T_LNUMBER, '1'])) {
$tokens->clearTokenAndMergeSurroundingWhitespace($index);
}
continue;
}
// skip T_FOR parenthesis to ignore double `;` like `for ($i = 1; ; ++$i) {...}`
if ($tokens[$index]->isGivenKind(T_FOR)) {
$index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextMeaningfulToken($index)) + 1;
continue;
}
if (!$tokens[$index]->equals(';')) {
continue;
}
$previousMeaningfulIndex = $tokens->getPrevMeaningfulToken($index);
// A semicolon can always be removed if it follows a semicolon, '{' or opening tag.
if ($tokens[$previousMeaningfulIndex]->equalsAny(['{', ';', [T_OPEN_TAG]])) {
$tokens->clearTokenAndMergeSurroundingWhitespace($index);
continue;
}
// A semicolon might be removed if it follows a '}' but only if the brace is part of certain structures.
if ($tokens[$previousMeaningfulIndex]->equals('}')) {
$this->fixSemicolonAfterCurlyBraceClose($tokens, $index, $previousMeaningfulIndex);
continue;
}
// A semicolon might be removed together with its noop statement, for example "<?php 1;"
$prePreviousMeaningfulIndex = $tokens->getPrevMeaningfulToken($previousMeaningfulIndex);
if (
$tokens[$prePreviousMeaningfulIndex]->equalsAny([';', '{', '}', [T_OPEN_TAG]])
&& $tokens[$previousMeaningfulIndex]->isGivenKind([T_CONSTANT_ENCAPSED_STRING, T_DNUMBER, T_LNUMBER, T_STRING, T_VARIABLE])
) {
$tokens->clearTokenAndMergeSurroundingWhitespace($index);
$tokens->clearTokenAndMergeSurroundingWhitespace($previousMeaningfulIndex);
}
}
}
/**
* Fix semicolon after closing curly brace if needed.
*
* Test for the following cases
* - just '{' '}' block (following open tag or ';')
* - if, else, elseif
* - interface, trait, class (but not anonymous)
* - catch, finally (but not try)
* - for, foreach, while (but not 'do - while')
* - switch
* - function (declaration, but not lambda)
* - declare (with '{' '}')
* - namespace (with '{' '}')
*
* @param int $index Semicolon index
*/
private function fixSemicolonAfterCurlyBraceClose(Tokens $tokens, int $index, int $curlyCloseIndex): void
{
static $beforeCurlyOpeningKinds = null;
if (null === $beforeCurlyOpeningKinds) {
$beforeCurlyOpeningKinds = [T_ELSE, T_FINALLY, T_NAMESPACE, T_OPEN_TAG];
}
$curlyOpeningIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $curlyCloseIndex);
$beforeCurlyOpeningIndex = $tokens->getPrevMeaningfulToken($curlyOpeningIndex);
if ($tokens[$beforeCurlyOpeningIndex]->isGivenKind($beforeCurlyOpeningKinds) || $tokens[$beforeCurlyOpeningIndex]->equalsAny([';', '{', '}'])) {
$tokens->clearTokenAndMergeSurroundingWhitespace($index);
return;
}
// check for namespaces and class, interface and trait definitions
if ($tokens[$beforeCurlyOpeningIndex]->isGivenKind(T_STRING)) {
$classyTestIndex = $tokens->getPrevMeaningfulToken($beforeCurlyOpeningIndex);
while ($tokens[$classyTestIndex]->equals(',') || $tokens[$classyTestIndex]->isGivenKind([T_STRING, T_NS_SEPARATOR, T_EXTENDS, T_IMPLEMENTS])) {
$classyTestIndex = $tokens->getPrevMeaningfulToken($classyTestIndex);
}
$tokensAnalyzer = new TokensAnalyzer($tokens);
if (
$tokens[$classyTestIndex]->isGivenKind(T_NAMESPACE)
|| ($tokens[$classyTestIndex]->isClassy() && !$tokensAnalyzer->isAnonymousClass($classyTestIndex))
) {
$tokens->clearTokenAndMergeSurroundingWhitespace($index);
}
return;
}
// early return check, below only control structures with conditions are fixed
if (!$tokens[$beforeCurlyOpeningIndex]->equals(')')) {
return;
}
$openingBraceIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $beforeCurlyOpeningIndex);
$beforeOpeningBraceIndex = $tokens->getPrevMeaningfulToken($openingBraceIndex);
if ($tokens[$beforeOpeningBraceIndex]->isGivenKind([T_IF, T_ELSEIF, T_FOR, T_FOREACH, T_WHILE, T_SWITCH, T_CATCH, T_DECLARE])) {
$tokens->clearTokenAndMergeSurroundingWhitespace($index);
return;
}
// check for function definition
if ($tokens[$beforeOpeningBraceIndex]->isGivenKind(T_STRING)) {
$beforeStringIndex = $tokens->getPrevMeaningfulToken($beforeOpeningBraceIndex);
if ($tokens[$beforeStringIndex]->isGivenKind(T_FUNCTION)) {
$tokens->clearTokenAndMergeSurroundingWhitespace($index); // implicit return
}
}
}
}
@@ -0,0 +1,75 @@
<?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\Semicolon;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\Tokens;
/**
* @author Graham Campbell <hello@gjcampbell.co.uk>
*/
final class NoSinglelineWhitespaceBeforeSemicolonsFixer extends AbstractFixer
{
/**
* {@inheritdoc}
*/
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Single-line whitespace before closing semicolon are prohibited.',
[new CodeSample("<?php \$this->foo() ;\n")]
);
}
/**
* {@inheritdoc}
*
* Must run after CombineConsecutiveIssetsFixer, FunctionToConstantFixer, NoEmptyStatementFixer, NoUnneededImportAliasFixer, SimplifiedIfReturnFixer, SingleImportPerStatementFixer.
*/
public function getPriority(): int
{
return 0;
}
/**
* {@inheritdoc}
*/
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(';');
}
/**
* {@inheritdoc}
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
foreach ($tokens as $index => $token) {
if (!$token->equals(';') || !$tokens[$index - 1]->isWhitespace(" \t")) {
continue;
}
if ($tokens[$index - 2]->equals(';')) {
// do not remove all whitespace before the semicolon because it is also whitespace after another semicolon
$tokens->ensureWhitespaceAtIndex($index - 1, 0, ' ');
} elseif (!$tokens[$index - 2]->isComment()) {
$tokens->clearAt($index - 1);
}
}
}
}
@@ -0,0 +1,73 @@
<?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\Semicolon;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
final class SemicolonAfterInstructionFixer extends AbstractFixer
{
/**
* {@inheritdoc}
*/
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Instructions must be terminated with a semicolon.',
[new CodeSample("<?php echo 1 ?>\n")]
);
}
/**
* {@inheritdoc}
*
* Must run before SimplifiedIfReturnFixer.
*/
public function getPriority(): int
{
return 2;
}
/**
* {@inheritdoc}
*/
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(T_CLOSE_TAG);
}
/**
* {@inheritdoc}
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
for ($index = \count($tokens) - 1; $index > 1; --$index) {
if (!$tokens[$index]->isGivenKind(T_CLOSE_TAG)) {
continue;
}
$prev = $tokens->getPrevMeaningfulToken($index);
if ($tokens[$prev]->equalsAny([';', '{', '}', ':', [T_OPEN_TAG]])) {
continue;
}
$tokens->insertAt($prev + 1, new Token(';'));
}
}
}
@@ -0,0 +1,146 @@
<?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\Semicolon;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
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\Preg;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
final class SpaceAfterSemicolonFixer extends AbstractFixer implements ConfigurableFixerInterface
{
/**
* {@inheritdoc}
*/
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Fix whitespace after a semicolon.',
[
new CodeSample(
"<?php
sample(); \$test = 1;
sample();\$test = 2;
for ( ;;++\$sample) {
}\n"
),
new CodeSample("<?php\nfor (\$i = 0; ; ++\$i) {\n}\n", [
'remove_in_empty_for_expressions' => true,
]),
]
);
}
/**
* {@inheritdoc}
*
* Must run after CombineConsecutiveUnsetsFixer, MultilineWhitespaceBeforeSemicolonsFixer, NoEmptyStatementFixer, OrderedClassElementsFixer, SingleImportPerStatementFixer, SingleTraitInsertPerStatementFixer.
*/
public function getPriority(): int
{
return -1;
}
/**
* {@inheritdoc}
*/
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(';');
}
/**
* {@inheritdoc}
*/
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('remove_in_empty_for_expressions', 'Whether spaces should be removed for empty `for` expressions.'))
->setAllowedTypes(['bool'])
->setDefault(false)
->getOption(),
]);
}
/**
* {@inheritdoc}
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
$insideForParenthesesUntil = null;
for ($index = 0, $max = \count($tokens) - 1; $index < $max; ++$index) {
if (true === $this->configuration['remove_in_empty_for_expressions']) {
if ($tokens[$index]->isGivenKind(T_FOR)) {
$index = $tokens->getNextMeaningfulToken($index);
$insideForParenthesesUntil = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index);
continue;
}
if ($index === $insideForParenthesesUntil) {
$insideForParenthesesUntil = null;
continue;
}
}
if (!$tokens[$index]->equals(';')) {
continue;
}
if (!$tokens[$index + 1]->isWhitespace()) {
if (
!$tokens[$index + 1]->equalsAny([')', [T_INLINE_HTML]]) && (
false === $this->configuration['remove_in_empty_for_expressions']
|| !$tokens[$index + 1]->equals(';')
)
) {
$tokens->insertAt($index + 1, new Token([T_WHITESPACE, ' ']));
++$max;
}
continue;
}
if (
null !== $insideForParenthesesUntil
&& ($tokens[$index + 2]->equals(';') || $index + 2 === $insideForParenthesesUntil)
&& !Preg::match('/\R/', $tokens[$index + 1]->getContent())
) {
$tokens->clearAt($index + 1);
continue;
}
if (
isset($tokens[$index + 2])
&& !$tokens[$index + 1]->equals([T_WHITESPACE, ' '])
&& $tokens[$index + 1]->isWhitespace(" \t")
&& !$tokens[$index + 2]->isComment()
&& !$tokens[$index + 2]->equals(')')
) {
$tokens[$index + 1] = new Token([T_WHITESPACE, ' ']);
}
}
}
}