CHANGE_Vendor : ps

This commit is contained in:
VE10-Sanjeev 2024-06-04 11:41:50 +00:00
parent ea5f27d800
commit de46426a31
307 changed files with 640 additions and 407 deletions

View File

View File

@ -40,7 +40,7 @@ final class LongToShorthandOperatorFixer extends AbstractShortOperatorFixer
];
/**
* @var string[]
* @var list<string>
*/
private array $operatorTypes;

View File

View File

View File

View File

View File

@ -40,7 +40,7 @@ final class OperatorLinebreakFixer extends AbstractFixer implements Configurable
private string $position = 'beginning';
/**
* @var list<list<int|string>|string>
* @var list<array{int}|string>
*/
private array $operators = [];
@ -144,7 +144,7 @@ function foo() {
}
/**
* @param int[] $operatorIndices
* @param non-empty-list<int> $operatorIndices
*/
private function fixOperatorLinebreak(Tokens $tokens, array $operatorIndices): void
{
@ -176,7 +176,7 @@ function foo() {
}
/**
* @param int[] $operatorIndices
* @param non-empty-list<int> $operatorIndices
*/
private function fixMoveToTheBeginning(Tokens $tokens, array $operatorIndices): void
{
@ -201,7 +201,7 @@ function foo() {
}
/**
* @param int[] $operatorIndices
* @param non-empty-list<int> $operatorIndices
*/
private function fixMoveToTheEnd(Tokens $tokens, array $operatorIndices): void
{
@ -226,9 +226,9 @@ function foo() {
}
/**
* @param int[] $indices
* @param list<int> $indices
*
* @return Token[]
* @return list<Token>
*/
private function getReplacementsAndClear(Tokens $tokens, array $indices, int $direction): array
{

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

@ -17,11 +17,13 @@ namespace PhpCsFixer\Fixer\PhpUnit;
use PhpCsFixer\DocBlock\Annotation;
use PhpCsFixer\DocBlock\DocBlock;
use PhpCsFixer\Fixer\AbstractPhpUnitFixer;
use PhpCsFixer\Fixer\AttributeNotation\OrderedAttributesFixer;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\FixerDefinition\VersionSpecification;
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
use PhpCsFixer\Preg;
use PhpCsFixer\Tokenizer\Analyzer\AttributeAnalyzer;
use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Processor\ImportProcessor;
use PhpCsFixer\Tokenizer\Token;
@ -120,6 +122,10 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
/** @phpstan-ignore-next-line */
$tokensToInsert = self::{$this->fixingMap[$annotationName]}($tokens, $index, $annotation);
if (self::isAttributeAlreadyPresent($tokens, $index, $tokensToInsert)) {
continue;
}
if ([] === $tokensToInsert) {
continue;
}
@ -196,6 +202,52 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
return true;
}
/**
* @param list<Token> $tokensToInsert
*/
private static function isAttributeAlreadyPresent(Tokens $tokens, int $index, array $tokensToInsert): bool
{
$attributeIndex = $tokens->getNextMeaningfulToken($index);
if (!$tokens[$attributeIndex]->isGivenKind(T_ATTRIBUTE)) {
return false;
}
$insertedClassName = '';
foreach (\array_slice($tokensToInsert, 3) as $token) {
if ($token->equals('(') || $token->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) {
break;
}
$insertedClassName .= $token->getContent();
}
// @TODO: refactor OrderedAttributesFixer::determineAttributeFullyQualifiedName to shared analyzer
static $determineAttributeFullyQualifiedName = null;
static $orderedAttributesFixer = null;
if (null === $determineAttributeFullyQualifiedName) {
$orderedAttributesFixer = new OrderedAttributesFixer();
$reflection = new \ReflectionObject($orderedAttributesFixer);
$determineAttributeFullyQualifiedName = $reflection->getMethod('determineAttributeFullyQualifiedName');
$determineAttributeFullyQualifiedName->setAccessible(true);
}
foreach (AttributeAnalyzer::collect($tokens, $attributeIndex) as $attributeAnalysis) {
foreach ($attributeAnalysis->getAttributes() as $attribute) {
$className = ltrim($determineAttributeFullyQualifiedName->invokeArgs(
$orderedAttributesFixer,
[$tokens,
$attribute['name'],
$attribute['start']],
), '\\');
if ($insertedClassName === $className) {
return true;
}
}
}
return false;
}
/**
* @return list<Token>
*/
@ -210,7 +262,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
private static function fixWithSingleStringValue(Tokens $tokens, int $index, Annotation $annotation): array
{
Preg::match(
sprintf('/@%s\s+(.*\S)(?:\R|\s*\*+\\/$)/', $annotation->getTag()->getName()),
sprintf('/@%s\s+(.*\S)(?:\R|\s*\*+\/$)/', $annotation->getTag()->getName()),
$annotation->getContent(),
$matches,
);
@ -375,11 +427,13 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
new Token([T_WHITESPACE, ' ']),
self::createEscapedStringToken($method),
];
} elseif ('RequiresPhp' === $attributeName && isset($matches[3])) {
$attributeTokens = [self::createEscapedStringToken($matches[2].' '.$matches[3])];
} else {
$attributeTokens = [self::createEscapedStringToken($matches[2])];
}
if (isset($matches[3])) {
if (isset($matches[3]) && 'RequiresPhp' !== $attributeName) {
$attributeTokens[] = new Token(',');
$attributeTokens[] = new Token([T_WHITESPACE, ' ']);
$attributeTokens[] = self::createEscapedStringToken($matches[3]);
@ -425,7 +479,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
if (str_starts_with($matches[1], '::')) {
$attributeName = 'UsesFunction';
$attributeTokens = [self::createEscapedStringToken(substr($matches[1], 2))];
} elseif (Preg::match('/^[a-zA-Z\d\\\\]+$/', $matches[1])) {
} elseif (Preg::match('/^[a-zA-Z\d\\\]+$/', $matches[1])) {
$attributeName = 'UsesClass';
$attributeTokens = self::toClassConstant($matches[1]);
} else {
@ -436,16 +490,18 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
}
/**
* @return array<string>
* @return list<string>
*/
private static function getMatches(Annotation $annotation): array
{
Preg::match(
sprintf('/@%s\s+(\S+)(?:\s+(\S+))?(?:\s+(.+\S))?\s*(?:\R|\*+\\/$)/', $annotation->getTag()->getName()),
sprintf('/@%s\s+(\S+)(?:\s+(\S+))?(?:\s+(.+\S))?\s*(?:\R|\*+\/$)/', $annotation->getTag()->getName()),
$annotation->getContent(),
$matches,
);
\assert(array_is_list($matches)); // preg_match matches is not well typed, it depends on used regex, let's assure the type to instruct SCA
return $matches;
}

View File

@ -32,16 +32,6 @@ use PhpCsFixer\Tokenizer\Tokens;
*/
final class PhpUnitConstructFixer extends AbstractPhpUnitFixer implements ConfigurableFixerInterface
{
/**
* @var array<string, string>
*/
private static array $assertionFixers = [
'assertSame' => 'fixAssertPositive',
'assertEquals' => 'fixAssertPositive',
'assertNotEquals' => 'fixAssertNegative',
'assertNotSame' => 'fixAssertNegative',
];
public function isRisky(): bool
{
return true;
@ -93,6 +83,10 @@ final class FooTest extends \PHPUnit_Framework_TestCase {
return -8;
}
/**
* @uses fixAssertNegative()
* @uses fixAssertPositive()
*/
protected function applyPhpUnitClassFix(Tokens $tokens, int $startIndex, int $endIndex): void
{
// no assertions to be fixed - fast return
@ -101,10 +95,13 @@ final class FooTest extends \PHPUnit_Framework_TestCase {
}
foreach ($this->configuration['assertions'] as $assertionMethod) {
$assertionFixer = self::$assertionFixers[$assertionMethod];
for ($index = $startIndex; $index < $endIndex; ++$index) {
$index = $this->{$assertionFixer}($tokens, $index, $assertionMethod);
$index = \call_user_func_array(
\in_array($assertionMethod, ['assertSame', 'assertEquals'], true)
? [$this, 'fixAssertPositive']
: [$this, 'fixAssertNegative'],
[$tokens, $index, $assertionMethod]
);
if (null === $index) {
break;
@ -115,16 +112,18 @@ final class FooTest extends \PHPUnit_Framework_TestCase {
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{
$assertMethods = [
'assertEquals',
'assertSame',
'assertNotEquals',
'assertNotSame',
];
return new FixerConfigurationResolver([
(new FixerOptionBuilder('assertions', 'List of assertion methods to fix.'))
->setAllowedTypes(['array'])
->setAllowedValues([new AllowedValueSubset(array_keys(self::$assertionFixers))])
->setDefault([
'assertEquals',
'assertSame',
'assertNotEquals',
'assertNotSame',
])
->setAllowedTypes(['string[]'])
->setAllowedValues([new AllowedValueSubset($assertMethods)])
->setDefault($assertMethods)
->getOption(),
]);
}

View File

@ -101,7 +101,17 @@ class FooTest extends TestCase {
);
}
public function getConfigurationDefinition(): FixerConfigurationResolverInterface
public function getPriority(): int
{
return 0;
}
public function isRisky(): bool
{
return true;
}
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('prefix', 'Prefix that replaces "test".'))
@ -115,16 +125,6 @@ class FooTest extends TestCase {
]);
}
public function getPriority(): int
{
return 0;
}
public function isRisky(): bool
{
return true;
}
protected function applyPhpUnitClassFix(Tokens $tokens, int $startIndex, int $endIndex): void
{
$dataProviderAnalyzer = new DataProviderAnalyzer();

View File

@ -117,6 +117,8 @@ class FooTest extends TestCase {
continue;
}
}
/** @var int $functionIndex */
$functionIndex = $tokens->getPrevTokenOfKind($dataProviderDefinitionIndex->getNameIndex(), [[T_FUNCTION]]);
$methodAttributes = $tokensAnalyzer->getMethodAttributes($functionIndex);

View File

@ -34,7 +34,7 @@ use PhpCsFixer\Tokenizer\Tokens;
final class PhpUnitDedicateAssertFixer extends AbstractPhpUnitFixer implements ConfigurableFixerInterface
{
/**
* @var array<string, array<string, bool|int|string>|true>
* @var array<string, array{positive: string, negative: false|string, argument_count?: int, swap_arguments?: true}|true>
*/
private static array $fixMap = [
'array_key_exists' => [
@ -109,7 +109,7 @@ final class PhpUnitDedicateAssertFixer extends AbstractPhpUnitFixer implements C
];
/**
* @var string[]
* @var list<string>
*/
private array $functions = [];

View File

View File

@ -77,7 +77,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
if ($tokens[$index]->isGivenKind(T_DOC_COMMENT)) {
$tokens[$index] = new Token([T_DOC_COMMENT, Preg::replace(
'~^(\s*\*\s*@(?:expectedException|covers|coversDefaultClass|uses)\h+)(?!(?:self|static)::)(\w.*)$~m',
'$1\\\\$2',
'$1\\\$2',
$tokens[$index]->getContent()
)]);
}

View File

@ -63,7 +63,7 @@ final class PhpUnitInternalClassFixer extends AbstractPhpUnitFixer implements Wh
return new FixerConfigurationResolver([
(new FixerOptionBuilder('types', 'What types of classes to mark as internal.'))
->setAllowedValues([new AllowedValueSubset($types)])
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setDefault(['normal', 'final'])
->getOption(),
]);

View File

@ -52,7 +52,7 @@ final class PhpUnitMethodCasingFixer extends AbstractPhpUnitFixer implements Con
[
new CodeSample(
'<?php
class MyTest extends \\PhpUnit\\FrameWork\\TestCase
class MyTest extends \PhpUnit\FrameWork\TestCase
{
public function test_my_code() {}
}
@ -60,7 +60,7 @@ class MyTest extends \\PhpUnit\\FrameWork\\TestCase
),
new CodeSample(
'<?php
class MyTest extends \\PhpUnit\\FrameWork\\TestCase
class MyTest extends \PhpUnit\FrameWork\TestCase
{
public function testMyCode() {}
}

View File

View File

View File

@ -77,7 +77,11 @@ final class PhpUnitSizeClassFixer extends AbstractPhpUnitFixer implements Whites
$classIndex,
$this->configuration['group'],
self::SIZES,
[],
[
'phpunit\framework\attributes\small',
'phpunit\framework\attributes\medium',
'phpunit\framework\attributes\large',
],
);
}

View File

@ -127,7 +127,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('assertions', 'List of assertion methods to fix.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setAllowedValues([new AllowedValueSubset(array_keys(self::$assertionMap))])
->setDefault([
'assertAttributeEquals',

View File

View File

@ -47,14 +47,14 @@ final class PhpUnitTestAnnotationFixer extends AbstractPhpUnitFixer implements C
'Adds or removes @test annotations from tests, following configuration.',
[
new CodeSample('<?php
class Test extends \\PhpUnit\\FrameWork\\TestCase
class Test extends \PhpUnit\FrameWork\TestCase
{
/**
* @test
*/
public function itDoesSomething() {} }'.$this->whitespacesConfig->getLineEnding()),
new CodeSample('<?php
class Test extends \\PhpUnit\\FrameWork\\TestCase
class Test extends \PhpUnit\FrameWork\TestCase
{
public function testItDoesSomething() {}}'.$this->whitespacesConfig->getLineEnding(), ['style' => 'annotation']),
],
@ -278,9 +278,9 @@ public function testItDoesSomething() {}}'.$this->whitespacesConfig->getLineEndi
/**
* Take a one line doc block, and turn it into a multi line doc block.
*
* @param Line[] $lines
* @param non-empty-list<Line> $lines
*
* @return Line[]
* @return list<Line>
*/
private function splitUpDocBlock(array $lines, Tokens $tokens, int $docBlockIndex): array
{
@ -298,7 +298,7 @@ public function testItDoesSomething() {}}'.$this->whitespacesConfig->getLineEndi
/**
* @todo check whether it's doable to use \PhpCsFixer\DocBlock\DocBlock::getSingleLineDocBlockEntry instead
*
* @param Line[] $lines
* @param non-empty-list<Line> $lines
*/
private function getSingleLineDocBlockEntry(array $lines): string
{
@ -377,9 +377,9 @@ public function testItDoesSomething() {}}'.$this->whitespacesConfig->getLineEndi
}
/**
* @param Line[] $lines
* @param list<Line> $lines
*
* @return Line[]
* @return list<Line>
*/
private function addTestAnnotation(array $lines, Tokens $tokens, int $docBlockIndex): array
{
@ -389,7 +389,8 @@ public function testItDoesSomething() {}}'.$this->whitespacesConfig->getLineEndi
$originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $docBlockIndex);
$lineEnd = $this->whitespacesConfig->getLineEnding();
array_splice($lines, -1, 0, $originalIndent.' *'.$lineEnd.$originalIndent.' * @test'.$lineEnd);
array_splice($lines, -1, 0, [new Line($originalIndent.' *'.$lineEnd.$originalIndent.' * @test'.$lineEnd)]);
\assert(array_is_list($lines)); // we know it's list, but we need to tell PHPStan
}
return $lines;

View File

@ -315,7 +315,7 @@ final class PhpUnitTestCaseStaticMethodCallsFixer extends AbstractPhpUnitFixer i
];
/**
* @var array<string, list<list<int|string>>>
* @var array<string, list<array{int, string}>>
*/
private array $conversionMap = [
self::CALL_TYPE_THIS => [[T_OBJECT_OPERATOR, '->'], [T_VARIABLE, '$this']],
@ -372,7 +372,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
->setDefault('static')
->getOption(),
(new FixerOptionBuilder('methods', 'Dictionary of `method` => `call_type` values that differ from the default strategy.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setAllowedValues([static function (array $option): bool {
foreach ($option as $method => $value) {
if (!isset(self::STATIC_METHODS[$method])) {

View File

@ -78,8 +78,8 @@ final class MyTest extends \PHPUnit_Framework_TestCase
'coversNothing',
],
[
'phpunit\\framework\\attributes\\coversclass',
'phpunit\\framework\\attributes\\coversnothing',
'phpunit\framework\attributes\coversclass',
'phpunit\framework\attributes\coversnothing',
],
);
}

View File

@ -34,7 +34,7 @@ use PhpCsFixer\Tokenizer\Tokens;
final class AlignMultilineCommentFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface
{
/**
* @var null|int[]
* @var null|list<int>
*/
private $tokenKinds;

View File

@ -127,7 +127,7 @@ function foo() {}
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('annotations', 'List of annotations to remove, e.g. `["author"]`.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setDefault([])
->getOption(),
(new FixerOptionBuilder('case_sensitive', 'Should annotations be case sensitive.'))

View File

@ -91,7 +91,7 @@ final class GeneralPhpdocTagRenameFixer extends AbstractFixer implements Configu
->setDefault(true)
->getOption(),
(new FixerOptionBuilder('replacements', 'A map of tags to replace.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setNormalizer(static function (Options $options, array $value): array {
$normalizedValue = [];

View File

View File

View File

@ -467,6 +467,8 @@ class Foo {
if (true === $this->configuration['allow_hidden_params']) {
$paramsString = $tokens->generatePartialCode($start, $end);
Preg::matchAll('|/\*[^$]*(\$\w+)[^*]*\*/|', $paramsString, $matches);
/** @var non-empty-string $match */
foreach ($matches[1] as $match) {
$argumentsInfo[$match] = self::NO_TYPE_INFO; // HINT: one could try to extract actual type for hidden param, for now we only indicate it's existence
}

View File

@ -230,7 +230,7 @@ final class PhpdocAlignFixer extends AbstractFixer implements ConfigurableFixerI
'The tags that should be aligned. Allowed values are tags with name (`\''.implode('\', \'', self::TAGS_WITH_NAME).'\'`), tags with method signature (`\''.implode('\', \'', self::TAGS_WITH_METHOD_SIGNATURE).'\'`) and any custom tag with description (e.g. `@tag <desc>`).'
);
$tags
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setDefault(self::DEFAULT_TAGS)
;

View File

View File

View File

@ -99,7 +99,7 @@ final class PhpdocInlineTagNormalizerFixer extends AbstractFixer implements Conf
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('tags', 'The list of tags to normalize.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setDefault(['example', 'id', 'internal', 'inheritdoc', 'inheritdocs', 'link', 'source', 'toc', 'tutorial'])
->getOption(),
]);

View File

View File

@ -65,6 +65,6 @@ final class PhpdocListTypeFixer extends AbstractPhpdocTypesFixer
protected function normalize(string $type): string
{
return Preg::replace('/array(?=<(?:[^,<]|<[^>]+>)+(>|{|\\())/i', 'list', $type);
return Preg::replace('/array(?=<(?:[^,<]|<[^>]+>)+(>|{|\())/i', 'list', $type);
}
}

View File

View File

@ -108,7 +108,7 @@ final class Example
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('replacements', 'Mapping between replaced annotations with new ones.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setDefault([
'property-read' => 'property',
'property-write' => 'property',

View File

View File

View File

View File

@ -188,9 +188,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
return new FixerConfigurationResolver([
(new FixerOptionBuilder('annotations', 'List of annotations to order, e.g. `["covers"]`.'))
->setAllowedTypes([
'array',
])
->setAllowedTypes(['string[]'])
->setAllowedValues([
new AllowedValueSubset($allowedValues),
])

View File

@ -102,6 +102,9 @@ final class PhpdocOrderFixer extends AbstractFixer implements ConfigurableFixerI
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
/** @var list<string> */
$order = $this->configuration['order'];
foreach ($tokens as $index => $token) {
if (!$token->isGivenKind(T_DOC_COMMENT)) {
continue;
@ -111,7 +114,7 @@ final class PhpdocOrderFixer extends AbstractFixer implements ConfigurableFixerI
$content = $token->getContent();
// sort annotations
$successors = $this->configuration['order'];
$successors = $order;
while (\count($successors) >= 3) {
$predecessor = array_shift($successors);
$content = $this->moveAnnotationsBefore($predecessor, $successors, $content);
@ -119,7 +122,7 @@ final class PhpdocOrderFixer extends AbstractFixer implements ConfigurableFixerI
// we're parsing the content last time to make sure the internal
// state of the docblock is correct after the modifications
$predecessors = $this->configuration['order'];
$predecessors = $order;
$last = array_pop($predecessors);
$content = $this->moveAnnotationsAfter($last, $predecessors, $content);
@ -131,8 +134,8 @@ final class PhpdocOrderFixer extends AbstractFixer implements ConfigurableFixerI
/**
* Move all given annotations in before given set of annotations.
*
* @param string $move Tag of annotations that should be moved
* @param string[] $before Tags of annotations that should moved annotations be placed before
* @param string $move Tag of annotations that should be moved
* @param list<string> $before Tags of annotations that should moved annotations be placed before
*/
private function moveAnnotationsBefore(string $move, array $before, string $content): string
{
@ -170,8 +173,8 @@ final class PhpdocOrderFixer extends AbstractFixer implements ConfigurableFixerI
/**
* Move all given annotations after given set of annotations.
*
* @param string $move Tag of annotations that should be moved
* @param string[] $after Tags of annotations that should moved annotations be placed after
* @param string $move Tag of annotations that should be moved
* @param list<string> $after Tags of annotations that should moved annotations be placed after
*/
private function moveAnnotationsAfter(string $move, array $after, string $content): string
{

View File

@ -103,7 +103,7 @@ function m($a, array $b, Foo $c) {}
}
/**
* @return Token[]
* @return list<Token>
*/
private function getFunctionParamNames(Tokens $tokens, int $paramBlockStart): array
{
@ -124,8 +124,8 @@ function m($a, array $b, Foo $c) {}
/**
* Overwrite the param annotations in order.
*
* @param Token[] $paramNames
* @param Annotation[] $paramAnnotations
* @param list<Token> $paramNames
* @param list<Annotation> $paramAnnotations
*/
private function rewriteDocBlock(DocBlock $doc, array $paramNames, array $paramAnnotations): DocBlock
{
@ -161,8 +161,8 @@ function m($a, array $b, Foo $c) {}
/**
* Sort the param annotations according to the function parameters.
*
* @param Token[] $funcParamNames
* @param Annotation[] $paramAnnotations
* @param list<Token> $funcParamNames
* @param list<Annotation> $paramAnnotations
*
* @return list<string>
*/
@ -181,9 +181,10 @@ function m($a, array $b, Foo $c) {}
}
// Detect superfluous annotations
/** @var Annotation[] $invalidParams */
$invalidParams = array_diff_key($paramAnnotations, $validParams);
$invalidParams = array_values($invalidParams);
/** @var list<Annotation> $invalidParams */
$invalidParams = array_values(
array_diff_key($paramAnnotations, $validParams)
);
// Append invalid parameters to the (ordered) valid ones
$orderedParams = array_values($validParams);
@ -197,7 +198,7 @@ function m($a, array $b, Foo $c) {}
/**
* Fetch all annotations except the param ones.
*
* @param Annotation[] $paramAnnotations
* @param list<Annotation> $paramAnnotations
*
* @return list<string>
*/
@ -227,7 +228,7 @@ function m($a, array $b, Foo $c) {}
/**
* Return the indices of the lines of a specific parameter annotation.
*
* @param Annotation[] $paramAnnotations
* @param list<Annotation> $paramAnnotations
*
* @return ?list<int>
*/

View File

@ -33,7 +33,7 @@ use Symfony\Component\OptionsResolver\Options;
final class PhpdocReturnSelfReferenceFixer extends AbstractFixer implements ConfigurableFixerInterface
{
/**
* @var string[]
* @var list<string>
*/
private static array $toTypes = [
'$this',
@ -135,7 +135,7 @@ class Sample
return new FixerConfigurationResolver([
(new FixerOptionBuilder('replacements', 'Mapping between replaced return types with new ones.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setNormalizer(static function (Options $options, array $value) use ($default): array {
$normalizedValue = [];

View File

View File

@ -38,7 +38,7 @@ final class PhpdocSeparationFixer extends AbstractFixer implements ConfigurableF
/**
* @internal
*
* @var string[][]
* @var list<list<string>>
*/
public const OPTION_GROUPS_DEFAULT = [
['author', 'copyright', 'license'],
@ -48,7 +48,7 @@ final class PhpdocSeparationFixer extends AbstractFixer implements ConfigurableF
];
/**
* @var string[][]
* @var list<list<string>>
*/
private array $groups;
@ -295,7 +295,7 @@ final class PhpdocSeparationFixer extends AbstractFixer implements ConfigurableF
private function tagName(Annotation $annotation): ?string
{
Preg::match('/@([a-zA-Z0-9_\\\\-]+(?=\s|$|\())/', $annotation->getContent(), $matches);
Preg::match('/@([a-zA-Z0-9_\\\-]+(?=\s|$|\())/', $annotation->getContent(), $matches);
return $matches[1] ?? null;
}

View File

View File

@ -84,7 +84,7 @@ final class PhpdocTagCasingFixer extends AbstractProxyFixer implements Configura
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('tags', 'List of tags to fix with their expected casing.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setDefault(['inheritDoc'])
->getOption(),
]);

View File

@ -135,7 +135,7 @@ final class PhpdocTagTypeFixer extends AbstractFixer implements ConfigurableFixe
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('tags', 'The list of tags to fix.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setAllowedValues([static function (array $value): bool {
foreach ($value as $type) {
if (!\in_array($type, ['annotation', 'inline'], true)) {
@ -182,7 +182,7 @@ final class PhpdocTagTypeFixer extends AbstractFixer implements ConfigurableFixe
}
/**
* @param list<string> $parts
* @param array<int,string> $parts
*/
private function tagIsSurroundedByText(array $parts, int $index): bool
{

View File

@ -127,7 +127,7 @@ function returnClassName() {
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('ignored_tags', 'List of ignored tags (matched case insensitively).'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setDefault([])
->getOption(),
(new FixerOptionBuilder('allow_before_return_statement', 'Whether to allow PHPDoc before return statement.'))
@ -158,7 +158,7 @@ function returnClassName() {
continue;
}
if (0 < Preg::matchAll('~\@([a-zA-Z0-9_\\\\-]+)\b~', $token->getContent(), $matches)) {
if (0 < Preg::matchAll('~\@([a-zA-Z0-9_\\\-]+)\b~', $token->getContent(), $matches)) {
foreach ($matches[1] as $match) {
if (\in_array(strtolower($match), $this->ignoredTags, true)) {
continue 2;

View File

@ -165,13 +165,16 @@ function fnc($foo) {}
private function findFirstAnnotationOrEnd(DocBlock $doc): int
{
$index = null;
foreach ($doc->getLines() as $index => $line) {
if ($line->containsATag()) {
return $index;
}
}
if (!isset($index)) {
throw new \LogicException('PHPDoc has empty lines collection.');
}
return $index; // no Annotation, return the last line
}

View File

View File

@ -148,7 +148,7 @@ final class PhpdocTypesFixer extends AbstractPhpdocTypesFixer implements Configu
return new FixerConfigurationResolver([
(new FixerOptionBuilder('groups', 'Type groups to fix.'))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setAllowedValues([new AllowedValueSubset($possibleGroups)])
->setDefault($possibleGroups)
->getOption(),

View File

View File

View File

View File

View File

@ -79,7 +79,7 @@ final class SimplifiedNullReturnFixer extends AbstractFixer
*/
private function clear(Tokens $tokens, int $index): void
{
while (!$tokens[++$index]->equals(';')) {
while (!$tokens[++$index]->equalsAny([';', [T_CLOSE_TAG]])) {
if ($this->shouldClearToken($tokens, $index)) {
$tokens->clearAt($index);
}
@ -96,13 +96,16 @@ final class SimplifiedNullReturnFixer extends AbstractFixer
}
$content = '';
while (!$tokens[$index]->equals(';')) {
while (!$tokens[$index]->equalsAny([';', [T_CLOSE_TAG]])) {
$index = $tokens->getNextMeaningfulToken($index);
$content .= $tokens[$index]->getContent();
}
$lastTokenContent = $tokens[$index]->getContent();
$content = substr($content, 0, -\strlen($lastTokenContent));
$content = ltrim($content, '(');
$content = rtrim($content, ');');
$content = rtrim($content, ')');
return 'null' === strtolower($content);
}
@ -137,13 +140,32 @@ final class SimplifiedNullReturnFixer extends AbstractFixer
/**
* Should we clear the specific token?
*
* If the token is a comment, or is whitespace that is immediately before a
* comment, then we'll leave it alone.
* We'll leave it alone if
* - token is a comment
* - token is whitespace that is immediately before a comment
* - token is whitespace that is immediately before the PHP close tag
* - token is whitespace that is immediately after a comment and before a semicolon
*/
private function shouldClearToken(Tokens $tokens, int $index): bool
{
$token = $tokens[$index];
return !$token->isComment() && !($token->isWhitespace() && $tokens[$index + 1]->isComment());
if ($token->isComment()) {
return false;
}
if (!$token->isWhitespace()) {
return true;
}
if (
$tokens[$index + 1]->isComment()
|| $tokens[$index + 1]->equals([T_CLOSE_TAG])
|| ($tokens[$index - 1]->isComment() && $tokens[$index + 1]->equals(';'))
) {
return false;
}
return true;
}
}

View File

View File

View File

View File

View File

View File

@ -42,8 +42,8 @@ final class ExplicitStringVariableFixer extends AbstractFixer
)],
'The reasoning behind this rule is the following:'
."\n".'- When there are two valid ways of doing the same thing, using both is confusing, there should be a coding standard to follow.'
."\n".'- PHP manual marks `"$var"` syntax as implicit and `"${var}"` syntax as explicit: explicit code should always be preferred.'
."\n".'- Explicit syntax allows word concatenation inside strings, e.g. `"${var}IsAVar"`, implicit doesn\'t.'
."\n".'- PHP manual marks `"$var"` syntax as implicit and `"{$var}"` syntax as explicit: explicit code should always be preferred.'
."\n".'- Explicit syntax allows word concatenation inside strings, e.g. `"{$var}IsAVar"`, implicit doesn\'t.'
."\n".'- Explicit syntax is easier to detect for IDE/editors and therefore has colors/highlight with higher contrast, which is easier to read.'
."\n".'Backtick operator is skipped because it is harder to handle; you can use `backtick_to_shell_exec` fixer to normalize backticks to strings.'
);

View File

@ -104,7 +104,7 @@ final class HeredocClosingMarkerFixer extends AbstractFixer implements Configura
'reserved_closing_markers',
'Reserved closing markers to be kept unchanged.'
))
->setAllowedTypes(['array'])
->setAllowedTypes(['string[]'])
->setDefault(self::RESERVED_CLOSING_MARKERS)
->getOption(),
(new FixerOptionBuilder(

View File

@ -81,12 +81,12 @@ final class HeredocToNowdocFixer extends AbstractFixer
$content = $tokens[$index + 1]->getContent();
// regex: odd number of backslashes, not followed by dollar
if (Preg::match('/(?<!\\\\)(?:\\\\{2})*\\\\(?![$\\\\])/', $content)) {
if (Preg::match('/(?<!\\\)(?:\\\{2})*\\\(?![$\\\])/', $content)) {
continue;
}
$tokens[$index] = $this->convertToNowdoc($token);
$content = str_replace(['\\\\', '\\$'], ['\\', '$'], $content);
$content = str_replace(['\\\\', '\$'], ['\\', '$'], $content);
$tokens[$index + 1] = new Token([
$tokens[$index + 1]->getId(),
$content,

View File

@ -108,9 +108,9 @@ final class MultilineStringToHeredocFixer extends AbstractFixer
$content = substr($content, 1, -1);
if ($isSingleQuoted) {
$content = Preg::replace('~\\\\([\\\\\'])~', '$1', $content);
$content = Preg::replace('~\\\([\\\\\'])~', '$1', $content);
} else {
$content = Preg::replace('~(\\\\\\\\)|\\\\(")~', '$1$2', $content);
$content = Preg::replace('~(\\\\\\\)|\\\(")~', '$1$2', $content);
}
$constantStringToken = new Token([T_ENCAPSED_AND_WHITESPACE, $content."\n"]);
@ -143,7 +143,7 @@ final class MultilineStringToHeredocFixer extends AbstractFixer
if ($tokens[$i]->isGivenKind(T_ENCAPSED_AND_WHITESPACE)) {
$tokens[$i] = new Token([
$tokens[$i]->getId(),
Preg::replace('~(\\\\\\\\)|\\\\(")~', '$1$2', $tokens[$i]->getContent()),
Preg::replace('~(\\\\\\\)|\\\(")~', '$1$2', $tokens[$i]->getContent()),
]);
}
}

View File

View File

@ -94,8 +94,8 @@ final class SimpleToComplexStringVariableFixer extends AbstractFixer
$tokenOfStringBeforeToken = $tokens[$index - 1];
$stringContent = $tokenOfStringBeforeToken->getContent();
if (str_ends_with($stringContent, '$') && !str_ends_with($stringContent, '\\$')) {
$newContent = substr($stringContent, 0, -1).'\\$';
if (str_ends_with($stringContent, '$') && !str_ends_with($stringContent, '\$')) {
$newContent = substr($stringContent, 0, -1).'\$';
$tokenOfStringBeforeToken = new Token([T_ENCAPSED_AND_WHITESPACE, $newContent]);
}

View File

@ -88,10 +88,10 @@ final class SingleQuoteFixer extends AbstractFixer implements ConfigurableFixerI
'"' === $content[0]
&& (true === $this->configuration['strings_containing_single_quote_chars'] || !str_contains($content, "'"))
// regex: odd number of backslashes, not followed by double quote or dollar
&& !Preg::match('/(?<!\\\\)(?:\\\\{2})*\\\\(?!["$\\\\])/', $content)
&& !Preg::match('/(?<!\\\)(?:\\\{2})*\\\(?!["$\\\])/', $content)
) {
$content = substr($content, 1, -1);
$content = str_replace(['\\"', '\\$', '\''], ['"', '$', '\\\''], $content);
$content = str_replace(['\"', '\$', '\''], ['"', '$', '\\\''], $content);
$tokens[$index] = new Token([T_CONSTANT_ENCAPSED_STRING, $prefix.'\''.$content.'\'']);
}
}

Some files were not shown because too many files have changed in this diff Show More