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; 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'; private string $position = 'beginning';
/** /**
* @var list<list<int|string>|string> * @var list<array{int}|string>
*/ */
private array $operators = []; 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 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 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 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 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\Annotation;
use PhpCsFixer\DocBlock\DocBlock; use PhpCsFixer\DocBlock\DocBlock;
use PhpCsFixer\Fixer\AbstractPhpUnitFixer; use PhpCsFixer\Fixer\AbstractPhpUnitFixer;
use PhpCsFixer\Fixer\AttributeNotation\OrderedAttributesFixer;
use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\FixerDefinition\VersionSpecification; use PhpCsFixer\FixerDefinition\VersionSpecification;
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
use PhpCsFixer\Preg; use PhpCsFixer\Preg;
use PhpCsFixer\Tokenizer\Analyzer\AttributeAnalyzer;
use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Processor\ImportProcessor; use PhpCsFixer\Tokenizer\Processor\ImportProcessor;
use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Token;
@ -120,6 +122,10 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
/** @phpstan-ignore-next-line */ /** @phpstan-ignore-next-line */
$tokensToInsert = self::{$this->fixingMap[$annotationName]}($tokens, $index, $annotation); $tokensToInsert = self::{$this->fixingMap[$annotationName]}($tokens, $index, $annotation);
if (self::isAttributeAlreadyPresent($tokens, $index, $tokensToInsert)) {
continue;
}
if ([] === $tokensToInsert) { if ([] === $tokensToInsert) {
continue; continue;
} }
@ -196,6 +202,52 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
return true; 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> * @return list<Token>
*/ */
@ -210,7 +262,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
private static function fixWithSingleStringValue(Tokens $tokens, int $index, Annotation $annotation): array private static function fixWithSingleStringValue(Tokens $tokens, int $index, Annotation $annotation): array
{ {
Preg::match( Preg::match(
sprintf('/@%s\s+(.*\S)(?:\R|\s*\*+\\/$)/', $annotation->getTag()->getName()), sprintf('/@%s\s+(.*\S)(?:\R|\s*\*+\/$)/', $annotation->getTag()->getName()),
$annotation->getContent(), $annotation->getContent(),
$matches, $matches,
); );
@ -375,11 +427,13 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
new Token([T_WHITESPACE, ' ']), new Token([T_WHITESPACE, ' ']),
self::createEscapedStringToken($method), self::createEscapedStringToken($method),
]; ];
} elseif ('RequiresPhp' === $attributeName && isset($matches[3])) {
$attributeTokens = [self::createEscapedStringToken($matches[2].' '.$matches[3])];
} else { } else {
$attributeTokens = [self::createEscapedStringToken($matches[2])]; $attributeTokens = [self::createEscapedStringToken($matches[2])];
} }
if (isset($matches[3])) { if (isset($matches[3]) && 'RequiresPhp' !== $attributeName) {
$attributeTokens[] = new Token(','); $attributeTokens[] = new Token(',');
$attributeTokens[] = new Token([T_WHITESPACE, ' ']); $attributeTokens[] = new Token([T_WHITESPACE, ' ']);
$attributeTokens[] = self::createEscapedStringToken($matches[3]); $attributeTokens[] = self::createEscapedStringToken($matches[3]);
@ -425,7 +479,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
if (str_starts_with($matches[1], '::')) { if (str_starts_with($matches[1], '::')) {
$attributeName = 'UsesFunction'; $attributeName = 'UsesFunction';
$attributeTokens = [self::createEscapedStringToken(substr($matches[1], 2))]; $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'; $attributeName = 'UsesClass';
$attributeTokens = self::toClassConstant($matches[1]); $attributeTokens = self::toClassConstant($matches[1]);
} else { } else {
@ -436,16 +490,18 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
} }
/** /**
* @return array<string> * @return list<string>
*/ */
private static function getMatches(Annotation $annotation): array private static function getMatches(Annotation $annotation): array
{ {
Preg::match( 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(), $annotation->getContent(),
$matches, $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; return $matches;
} }

View File

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

View File

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

View File

@ -34,7 +34,7 @@ use PhpCsFixer\Tokenizer\Tokens;
final class PhpUnitDedicateAssertFixer extends AbstractPhpUnitFixer implements ConfigurableFixerInterface 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 = [ private static array $fixMap = [
'array_key_exists' => [ 'array_key_exists' => [
@ -109,7 +109,7 @@ final class PhpUnitDedicateAssertFixer extends AbstractPhpUnitFixer implements C
]; ];
/** /**
* @var string[] * @var list<string>
*/ */
private array $functions = []; 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)) { if ($tokens[$index]->isGivenKind(T_DOC_COMMENT)) {
$tokens[$index] = new Token([T_DOC_COMMENT, Preg::replace( $tokens[$index] = new Token([T_DOC_COMMENT, Preg::replace(
'~^(\s*\*\s*@(?:expectedException|covers|coversDefaultClass|uses)\h+)(?!(?:self|static)::)(\w.*)$~m', '~^(\s*\*\s*@(?:expectedException|covers|coversDefaultClass|uses)\h+)(?!(?:self|static)::)(\w.*)$~m',
'$1\\\\$2', '$1\\\$2',
$tokens[$index]->getContent() $tokens[$index]->getContent()
)]); )]);
} }

View File

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

View File

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

View File

View File

View File

@ -77,7 +77,11 @@ final class PhpUnitSizeClassFixer extends AbstractPhpUnitFixer implements Whites
$classIndex, $classIndex,
$this->configuration['group'], $this->configuration['group'],
self::SIZES, 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([ return new FixerConfigurationResolver([
(new FixerOptionBuilder('assertions', 'List of assertion methods to fix.')) (new FixerOptionBuilder('assertions', 'List of assertion methods to fix.'))
->setAllowedTypes(['array']) ->setAllowedTypes(['string[]'])
->setAllowedValues([new AllowedValueSubset(array_keys(self::$assertionMap))]) ->setAllowedValues([new AllowedValueSubset(array_keys(self::$assertionMap))])
->setDefault([ ->setDefault([
'assertAttributeEquals', '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.', 'Adds or removes @test annotations from tests, following configuration.',
[ [
new CodeSample('<?php new CodeSample('<?php
class Test extends \\PhpUnit\\FrameWork\\TestCase class Test extends \PhpUnit\FrameWork\TestCase
{ {
/** /**
* @test * @test
*/ */
public function itDoesSomething() {} }'.$this->whitespacesConfig->getLineEnding()), public function itDoesSomething() {} }'.$this->whitespacesConfig->getLineEnding()),
new CodeSample('<?php new CodeSample('<?php
class Test extends \\PhpUnit\\FrameWork\\TestCase class Test extends \PhpUnit\FrameWork\TestCase
{ {
public function testItDoesSomething() {}}'.$this->whitespacesConfig->getLineEnding(), ['style' => 'annotation']), 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. * 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 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 * @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 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 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); $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $docBlockIndex);
$lineEnd = $this->whitespacesConfig->getLineEnding(); $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; 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 = [ private array $conversionMap = [
self::CALL_TYPE_THIS => [[T_OBJECT_OPERATOR, '->'], [T_VARIABLE, '$this']], self::CALL_TYPE_THIS => [[T_OBJECT_OPERATOR, '->'], [T_VARIABLE, '$this']],
@ -372,7 +372,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
->setDefault('static') ->setDefault('static')
->getOption(), ->getOption(),
(new FixerOptionBuilder('methods', 'Dictionary of `method` => `call_type` values that differ from the default strategy.')) (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 { ->setAllowedValues([static function (array $option): bool {
foreach ($option as $method => $value) { foreach ($option as $method => $value) {
if (!isset(self::STATIC_METHODS[$method])) { if (!isset(self::STATIC_METHODS[$method])) {

View File

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

View File

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

View File

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

View File

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

View File

View File

View File

@ -467,6 +467,8 @@ class Foo {
if (true === $this->configuration['allow_hidden_params']) { if (true === $this->configuration['allow_hidden_params']) {
$paramsString = $tokens->generatePartialCode($start, $end); $paramsString = $tokens->generatePartialCode($start, $end);
Preg::matchAll('|/\*[^$]*(\$\w+)[^*]*\*/|', $paramsString, $matches); Preg::matchAll('|/\*[^$]*(\$\w+)[^*]*\*/|', $paramsString, $matches);
/** @var non-empty-string $match */
foreach ($matches[1] as $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 $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>`).' '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 $tags
->setAllowedTypes(['array']) ->setAllowedTypes(['string[]'])
->setDefault(self::DEFAULT_TAGS) ->setDefault(self::DEFAULT_TAGS)
; ;

View File

View File

View File

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

View File

View File

@ -65,6 +65,6 @@ final class PhpdocListTypeFixer extends AbstractPhpdocTypesFixer
protected function normalize(string $type): string 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([ return new FixerConfigurationResolver([
(new FixerOptionBuilder('replacements', 'Mapping between replaced annotations with new ones.')) (new FixerOptionBuilder('replacements', 'Mapping between replaced annotations with new ones.'))
->setAllowedTypes(['array']) ->setAllowedTypes(['string[]'])
->setDefault([ ->setDefault([
'property-read' => 'property', 'property-read' => 'property',
'property-write' => '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([ return new FixerConfigurationResolver([
(new FixerOptionBuilder('annotations', 'List of annotations to order, e.g. `["covers"]`.')) (new FixerOptionBuilder('annotations', 'List of annotations to order, e.g. `["covers"]`.'))
->setAllowedTypes([ ->setAllowedTypes(['string[]'])
'array',
])
->setAllowedValues([ ->setAllowedValues([
new AllowedValueSubset($allowedValues), new AllowedValueSubset($allowedValues),
]) ])

View File

@ -102,6 +102,9 @@ final class PhpdocOrderFixer extends AbstractFixer implements ConfigurableFixerI
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{ {
/** @var list<string> */
$order = $this->configuration['order'];
foreach ($tokens as $index => $token) { foreach ($tokens as $index => $token) {
if (!$token->isGivenKind(T_DOC_COMMENT)) { if (!$token->isGivenKind(T_DOC_COMMENT)) {
continue; continue;
@ -111,7 +114,7 @@ final class PhpdocOrderFixer extends AbstractFixer implements ConfigurableFixerI
$content = $token->getContent(); $content = $token->getContent();
// sort annotations // sort annotations
$successors = $this->configuration['order']; $successors = $order;
while (\count($successors) >= 3) { while (\count($successors) >= 3) {
$predecessor = array_shift($successors); $predecessor = array_shift($successors);
$content = $this->moveAnnotationsBefore($predecessor, $successors, $content); $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 // we're parsing the content last time to make sure the internal
// state of the docblock is correct after the modifications // state of the docblock is correct after the modifications
$predecessors = $this->configuration['order']; $predecessors = $order;
$last = array_pop($predecessors); $last = array_pop($predecessors);
$content = $this->moveAnnotationsAfter($last, $predecessors, $content); $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. * Move all given annotations in before given set of annotations.
* *
* @param string $move Tag of annotations that should be moved * @param string $move Tag of annotations that should be moved
* @param string[] $before Tags of annotations that should moved annotations be placed before * @param list<string> $before Tags of annotations that should moved annotations be placed before
*/ */
private function moveAnnotationsBefore(string $move, array $before, string $content): string 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. * Move all given annotations after given set of annotations.
* *
* @param string $move Tag of annotations that should be moved * @param string $move Tag of annotations that should be moved
* @param string[] $after Tags of annotations that should moved annotations be placed after * @param list<string> $after Tags of annotations that should moved annotations be placed after
*/ */
private function moveAnnotationsAfter(string $move, array $after, string $content): string 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 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. * Overwrite the param annotations in order.
* *
* @param Token[] $paramNames * @param list<Token> $paramNames
* @param Annotation[] $paramAnnotations * @param list<Annotation> $paramAnnotations
*/ */
private function rewriteDocBlock(DocBlock $doc, array $paramNames, array $paramAnnotations): DocBlock 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. * Sort the param annotations according to the function parameters.
* *
* @param Token[] $funcParamNames * @param list<Token> $funcParamNames
* @param Annotation[] $paramAnnotations * @param list<Annotation> $paramAnnotations
* *
* @return list<string> * @return list<string>
*/ */
@ -181,9 +181,10 @@ function m($a, array $b, Foo $c) {}
} }
// Detect superfluous annotations // Detect superfluous annotations
/** @var Annotation[] $invalidParams */ /** @var list<Annotation> $invalidParams */
$invalidParams = array_diff_key($paramAnnotations, $validParams); $invalidParams = array_values(
$invalidParams = array_values($invalidParams); array_diff_key($paramAnnotations, $validParams)
);
// Append invalid parameters to the (ordered) valid ones // Append invalid parameters to the (ordered) valid ones
$orderedParams = array_values($validParams); $orderedParams = array_values($validParams);
@ -197,7 +198,7 @@ function m($a, array $b, Foo $c) {}
/** /**
* Fetch all annotations except the param ones. * Fetch all annotations except the param ones.
* *
* @param Annotation[] $paramAnnotations * @param list<Annotation> $paramAnnotations
* *
* @return list<string> * @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. * Return the indices of the lines of a specific parameter annotation.
* *
* @param Annotation[] $paramAnnotations * @param list<Annotation> $paramAnnotations
* *
* @return ?list<int> * @return ?list<int>
*/ */

View File

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

View File

View File

@ -38,7 +38,7 @@ final class PhpdocSeparationFixer extends AbstractFixer implements ConfigurableF
/** /**
* @internal * @internal
* *
* @var string[][] * @var list<list<string>>
*/ */
public const OPTION_GROUPS_DEFAULT = [ public const OPTION_GROUPS_DEFAULT = [
['author', 'copyright', 'license'], ['author', 'copyright', 'license'],
@ -48,7 +48,7 @@ final class PhpdocSeparationFixer extends AbstractFixer implements ConfigurableF
]; ];
/** /**
* @var string[][] * @var list<list<string>>
*/ */
private array $groups; private array $groups;
@ -295,7 +295,7 @@ final class PhpdocSeparationFixer extends AbstractFixer implements ConfigurableF
private function tagName(Annotation $annotation): ?string 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; return $matches[1] ?? null;
} }

View File

View File

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

View File

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

View File

@ -127,7 +127,7 @@ function returnClassName() {
{ {
return new FixerConfigurationResolver([ return new FixerConfigurationResolver([
(new FixerOptionBuilder('ignored_tags', 'List of ignored tags (matched case insensitively).')) (new FixerOptionBuilder('ignored_tags', 'List of ignored tags (matched case insensitively).'))
->setAllowedTypes(['array']) ->setAllowedTypes(['string[]'])
->setDefault([]) ->setDefault([])
->getOption(), ->getOption(),
(new FixerOptionBuilder('allow_before_return_statement', 'Whether to allow PHPDoc before return statement.')) (new FixerOptionBuilder('allow_before_return_statement', 'Whether to allow PHPDoc before return statement.'))
@ -158,7 +158,7 @@ function returnClassName() {
continue; 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) { foreach ($matches[1] as $match) {
if (\in_array(strtolower($match), $this->ignoredTags, true)) { if (\in_array(strtolower($match), $this->ignoredTags, true)) {
continue 2; continue 2;

View File

@ -165,13 +165,16 @@ function fnc($foo) {}
private function findFirstAnnotationOrEnd(DocBlock $doc): int private function findFirstAnnotationOrEnd(DocBlock $doc): int
{ {
$index = null;
foreach ($doc->getLines() as $index => $line) { foreach ($doc->getLines() as $index => $line) {
if ($line->containsATag()) { if ($line->containsATag()) {
return $index; return $index;
} }
} }
if (!isset($index)) {
throw new \LogicException('PHPDoc has empty lines collection.');
}
return $index; // no Annotation, return the last line 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([ return new FixerConfigurationResolver([
(new FixerOptionBuilder('groups', 'Type groups to fix.')) (new FixerOptionBuilder('groups', 'Type groups to fix.'))
->setAllowedTypes(['array']) ->setAllowedTypes(['string[]'])
->setAllowedValues([new AllowedValueSubset($possibleGroups)]) ->setAllowedValues([new AllowedValueSubset($possibleGroups)])
->setDefault($possibleGroups) ->setDefault($possibleGroups)
->getOption(), ->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 private function clear(Tokens $tokens, int $index): void
{ {
while (!$tokens[++$index]->equals(';')) { while (!$tokens[++$index]->equalsAny([';', [T_CLOSE_TAG]])) {
if ($this->shouldClearToken($tokens, $index)) { if ($this->shouldClearToken($tokens, $index)) {
$tokens->clearAt($index); $tokens->clearAt($index);
} }
@ -96,13 +96,16 @@ final class SimplifiedNullReturnFixer extends AbstractFixer
} }
$content = ''; $content = '';
while (!$tokens[$index]->equals(';')) { while (!$tokens[$index]->equalsAny([';', [T_CLOSE_TAG]])) {
$index = $tokens->getNextMeaningfulToken($index); $index = $tokens->getNextMeaningfulToken($index);
$content .= $tokens[$index]->getContent(); $content .= $tokens[$index]->getContent();
} }
$lastTokenContent = $tokens[$index]->getContent();
$content = substr($content, 0, -\strlen($lastTokenContent));
$content = ltrim($content, '('); $content = ltrim($content, '(');
$content = rtrim($content, ');'); $content = rtrim($content, ')');
return 'null' === strtolower($content); return 'null' === strtolower($content);
} }
@ -137,13 +140,32 @@ final class SimplifiedNullReturnFixer extends AbstractFixer
/** /**
* Should we clear the specific token? * Should we clear the specific token?
* *
* If the token is a comment, or is whitespace that is immediately before a * We'll leave it alone if
* comment, then we'll leave it alone. * - 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 private function shouldClearToken(Tokens $tokens, int $index): bool
{ {
$token = $tokens[$index]; $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:' '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".'- 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".'- 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 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".'- 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.' ."\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',
'Reserved closing markers to be kept unchanged.' 'Reserved closing markers to be kept unchanged.'
)) ))
->setAllowedTypes(['array']) ->setAllowedTypes(['string[]'])
->setDefault(self::RESERVED_CLOSING_MARKERS) ->setDefault(self::RESERVED_CLOSING_MARKERS)
->getOption(), ->getOption(),
(new FixerOptionBuilder( (new FixerOptionBuilder(

View File

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

View File

@ -108,9 +108,9 @@ final class MultilineStringToHeredocFixer extends AbstractFixer
$content = substr($content, 1, -1); $content = substr($content, 1, -1);
if ($isSingleQuoted) { if ($isSingleQuoted) {
$content = Preg::replace('~\\\\([\\\\\'])~', '$1', $content); $content = Preg::replace('~\\\([\\\\\'])~', '$1', $content);
} else { } else {
$content = Preg::replace('~(\\\\\\\\)|\\\\(")~', '$1$2', $content); $content = Preg::replace('~(\\\\\\\)|\\\(")~', '$1$2', $content);
} }
$constantStringToken = new Token([T_ENCAPSED_AND_WHITESPACE, $content."\n"]); $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)) { if ($tokens[$i]->isGivenKind(T_ENCAPSED_AND_WHITESPACE)) {
$tokens[$i] = new Token([ $tokens[$i] = new Token([
$tokens[$i]->getId(), $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]; $tokenOfStringBeforeToken = $tokens[$index - 1];
$stringContent = $tokenOfStringBeforeToken->getContent(); $stringContent = $tokenOfStringBeforeToken->getContent();
if (str_ends_with($stringContent, '$') && !str_ends_with($stringContent, '\\$')) { if (str_ends_with($stringContent, '$') && !str_ends_with($stringContent, '\$')) {
$newContent = substr($stringContent, 0, -1).'\\$'; $newContent = substr($stringContent, 0, -1).'\$';
$tokenOfStringBeforeToken = new Token([T_ENCAPSED_AND_WHITESPACE, $newContent]); $tokenOfStringBeforeToken = new Token([T_ENCAPSED_AND_WHITESPACE, $newContent]);
} }

View File

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