mirror of
https://github.com/rectorphp/rector.git
synced 2025-03-13 20:12:07 +01:00
Updated Rector to commit 3b14af26db9eef322f21a9c783e6f9109e087c67
3b14af26db
Type hint array reduce closure (#6725)
This commit is contained in:
parent
d79d9689ab
commit
a29172639c
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\TypeDeclaration\Rector\FunctionLike;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Param;
|
||||
use PHPStan\Reflection\Native\NativeFunctionReflection;
|
||||
use PHPStan\Type\ClosureType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\UnionType;
|
||||
use PHPStan\Type\UnionTypeHelper;
|
||||
use Rector\NodeTypeResolver\TypeComparator\TypeComparator;
|
||||
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Reflection\ReflectionResolver;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
/**
|
||||
* @see \Rector\Tests\TypeDeclaration\Rector\FunctionLike\AddClosureParamTypeForArrayReduceRector\AddClosureParamTypeForArrayReduceRectorTest
|
||||
*/
|
||||
final class AddClosureParamTypeForArrayReduceRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @readonly
|
||||
*/
|
||||
private TypeComparator $typeComparator;
|
||||
/**
|
||||
* @readonly
|
||||
*/
|
||||
private StaticTypeMapper $staticTypeMapper;
|
||||
/**
|
||||
* @readonly
|
||||
*/
|
||||
private ReflectionResolver $reflectionResolver;
|
||||
public function __construct(TypeComparator $typeComparator, StaticTypeMapper $staticTypeMapper, ReflectionResolver $reflectionResolver)
|
||||
{
|
||||
$this->typeComparator = $typeComparator;
|
||||
$this->staticTypeMapper = $staticTypeMapper;
|
||||
$this->reflectionResolver = $reflectionResolver;
|
||||
}
|
||||
public function getRuleDefinition() : RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Applies type hints to array_map closures', [new CodeSample(<<<'CODE_SAMPLE'
|
||||
array_reduce($strings, function ($carry, $value, $key): string {
|
||||
return $carry . $value;
|
||||
}, $initialString);
|
||||
CODE_SAMPLE
|
||||
, <<<'CODE_SAMPLE'
|
||||
array_reduce($strings, function (string $carry, string $value): string {
|
||||
return $carry . $value;
|
||||
}, $initialString);
|
||||
CODE_SAMPLE
|
||||
)]);
|
||||
}
|
||||
public function getNodeTypes() : array
|
||||
{
|
||||
return [FuncCall::class];
|
||||
}
|
||||
/**
|
||||
* @param FuncCall $node
|
||||
*/
|
||||
public function refactor(Node $node) : ?Node
|
||||
{
|
||||
if ($node->isFirstClassCallable()) {
|
||||
return null;
|
||||
}
|
||||
if (!$this->isName($node, 'array_reduce')) {
|
||||
return null;
|
||||
}
|
||||
$funcReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node);
|
||||
if (!$funcReflection instanceof NativeFunctionReflection) {
|
||||
return null;
|
||||
}
|
||||
$args = $node->getArgs();
|
||||
if (!isset($args[1]) || !$args[1]->value instanceof Closure) {
|
||||
return null;
|
||||
}
|
||||
$closureType = $this->getType($args[1]->value);
|
||||
if (!$closureType instanceof ClosureType) {
|
||||
return null;
|
||||
}
|
||||
$carryType = $closureType->getReturnType();
|
||||
if (isset($args[2])) {
|
||||
$carryType = $this->combineTypes([$this->getType($args[2]->value), $carryType]);
|
||||
}
|
||||
$type = $this->getType($args[0]->value);
|
||||
$valueType = $type->getIterableValueType();
|
||||
if ($this->updateClosureWithTypes($args[1]->value, $valueType, $carryType)) {
|
||||
return $node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private function updateClosureWithTypes(Closure $closure, ?Type $valueType, ?Type $carryType) : bool
|
||||
{
|
||||
$changes = \false;
|
||||
$carryParam = $closure->params[0] ?? null;
|
||||
$valueParam = $closure->params[1] ?? null;
|
||||
if ($valueParam instanceof Param && $valueType instanceof Type && $this->refactorParameter($valueParam, $valueType)) {
|
||||
$changes = \true;
|
||||
}
|
||||
if ($carryParam instanceof Param && $carryType instanceof Type && $this->refactorParameter($carryParam, $carryType)) {
|
||||
return \true;
|
||||
}
|
||||
return $changes;
|
||||
}
|
||||
private function refactorParameter(Param $param, Type $type) : bool
|
||||
{
|
||||
if ($type instanceof MixedType) {
|
||||
return \false;
|
||||
}
|
||||
// already set → no change
|
||||
if ($param->type instanceof Node) {
|
||||
$currentParamType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($param->type);
|
||||
if ($this->typeComparator->areTypesEqual($currentParamType, $type)) {
|
||||
return \false;
|
||||
}
|
||||
}
|
||||
$paramTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($type, TypeKind::PARAM);
|
||||
if (!$paramTypeNode instanceof Node) {
|
||||
return \false;
|
||||
}
|
||||
$param->type = $paramTypeNode;
|
||||
return \true;
|
||||
}
|
||||
/**
|
||||
* @param Type[] $types
|
||||
*/
|
||||
private function combineTypes(array $types) : ?Type
|
||||
{
|
||||
if ($types === []) {
|
||||
return null;
|
||||
}
|
||||
$types = \array_reduce($types, function (array $types, Type $type) : array {
|
||||
foreach ($types as $previousType) {
|
||||
if ($this->typeComparator->areTypesEqual($type, $previousType)) {
|
||||
return $types;
|
||||
}
|
||||
}
|
||||
$types[] = $type;
|
||||
return $types;
|
||||
}, []);
|
||||
if (\count($types) === 1) {
|
||||
return $types[0];
|
||||
}
|
||||
return new UnionType(UnionTypeHelper::sortTypes($types));
|
||||
}
|
||||
}
|
@ -19,12 +19,12 @@ final class VersionResolver
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PACKAGE_VERSION = '3569d162bf6cb3730c091db0898798e59c93b4f4';
|
||||
public const PACKAGE_VERSION = '3b14af26db9eef322f21a9c783e6f9109e087c67';
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const RELEASE_DATE = '2025-02-08 12:36:53';
|
||||
public const RELEASE_DATE = '2025-02-09 17:27:26';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
@ -48,6 +48,8 @@ use Rector\TypeDeclaration\Rector\Closure\AddClosureVoidReturnTypeWhereNoReturnR
|
||||
use Rector\TypeDeclaration\Rector\Closure\ClosureReturnTypeRector;
|
||||
use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector;
|
||||
use Rector\TypeDeclaration\Rector\Function_\AddFunctionVoidReturnTypeWhereNoReturnRector;
|
||||
use Rector\TypeDeclaration\Rector\FunctionLike\AddClosureParamTypeForArrayMapRector;
|
||||
use Rector\TypeDeclaration\Rector\FunctionLike\AddClosureParamTypeForArrayReduceRector;
|
||||
use Rector\TypeDeclaration\Rector\FunctionLike\AddParamTypeSplFixedArrayRector;
|
||||
use Rector\TypeDeclaration\Rector\FunctionLike\AddReturnTypeDeclarationFromYieldsRector;
|
||||
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector;
|
||||
@ -106,6 +108,8 @@ final class TypeDeclarationLevel
|
||||
// closures
|
||||
AddClosureNeverReturnTypeRector::class,
|
||||
ClosureReturnTypeRector::class,
|
||||
AddClosureParamTypeForArrayReduceRector::class,
|
||||
AddClosureParamTypeForArrayMapRector::class,
|
||||
// more risky rules
|
||||
ReturnTypeFromStrictParamRector::class,
|
||||
AddParamTypeFromPropertyTypeRector::class,
|
||||
|
2
vendor/composer/autoload_classmap.php
vendored
2
vendor/composer/autoload_classmap.php
vendored
@ -1790,6 +1790,7 @@ return array(
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCompareOnCountableWithMethodToAssertCountRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCompareOnCountableWithMethodToAssertCountRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCompareToSpecificMethodRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCompareToSpecificMethodRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertComparisonToSpecificMethodRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertComparisonToSpecificMethodRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCountWithZeroToAssertEmptyRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCountWithZeroToAssertEmptyRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEmptyNullableObjectToAssertInstanceofRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEmptyNullableObjectToAssertInstanceofRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEqualsOrAssertSameFloatParameterToSpecificMethodsTypeRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEqualsOrAssertSameFloatParameterToSpecificMethodsTypeRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEqualsToSameRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEqualsToSameRector.php',
|
||||
@ -2547,6 +2548,7 @@ return array(
|
||||
'Rector\\TypeDeclaration\\Rector\\Empty_\\EmptyOnNullableObjectToInstanceOfRector' => $baseDir . '/rules/TypeDeclaration/Rector/Empty_/EmptyOnNullableObjectToInstanceOfRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\Expression\\InlineVarDocTagToAssertRector' => $baseDir . '/rules/TypeDeclaration/Rector/Expression/InlineVarDocTagToAssertRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeForArrayMapRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeForArrayMapRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeForArrayReduceRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeForArrayReduceRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromArgRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromArgRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromIterableMethodCallRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromIterableMethodCallRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromObjectRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromObjectRector.php',
|
||||
|
2
vendor/composer/autoload_static.php
vendored
2
vendor/composer/autoload_static.php
vendored
@ -2009,6 +2009,7 @@ class ComposerStaticInita9ca9624b9ec3b7183135fb9d7d95d23
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCompareOnCountableWithMethodToAssertCountRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCompareOnCountableWithMethodToAssertCountRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCompareToSpecificMethodRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCompareToSpecificMethodRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertComparisonToSpecificMethodRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertComparisonToSpecificMethodRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCountWithZeroToAssertEmptyRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCountWithZeroToAssertEmptyRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEmptyNullableObjectToAssertInstanceofRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEmptyNullableObjectToAssertInstanceofRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEqualsOrAssertSameFloatParameterToSpecificMethodsTypeRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEqualsOrAssertSameFloatParameterToSpecificMethodsTypeRector.php',
|
||||
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEqualsToSameRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEqualsToSameRector.php',
|
||||
@ -2766,6 +2767,7 @@ class ComposerStaticInita9ca9624b9ec3b7183135fb9d7d95d23
|
||||
'Rector\\TypeDeclaration\\Rector\\Empty_\\EmptyOnNullableObjectToInstanceOfRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Empty_/EmptyOnNullableObjectToInstanceOfRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\Expression\\InlineVarDocTagToAssertRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Expression/InlineVarDocTagToAssertRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeForArrayMapRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeForArrayMapRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeForArrayReduceRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeForArrayReduceRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromArgRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromArgRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromIterableMethodCallRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromIterableMethodCallRector.php',
|
||||
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromObjectRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromObjectRector.php',
|
||||
|
8
vendor/composer/installed.json
vendored
8
vendor/composer/installed.json
vendored
@ -1804,12 +1804,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https:\/\/github.com\/rectorphp\/rector-phpunit.git",
|
||||
"reference": "03e2418e0107b33496c0f7bb99520ac8606a3d7a"
|
||||
"reference": "45b0f6bfc11edec5aa9cf85314d26a6f48220c60"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/03e2418e0107b33496c0f7bb99520ac8606a3d7a",
|
||||
"reference": "03e2418e0107b33496c0f7bb99520ac8606a3d7a",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/45b0f6bfc11edec5aa9cf85314d26a6f48220c60",
|
||||
"reference": "45b0f6bfc11edec5aa9cf85314d26a6f48220c60",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1830,7 +1830,7 @@
|
||||
"tomasvotruba\/class-leak": "^1.2",
|
||||
"tracy\/tracy": "^2.10"
|
||||
},
|
||||
"time": "2025-02-02T01:09:12+00:00",
|
||||
"time": "2025-02-09T14:37:12+00:00",
|
||||
"default-branch": true,
|
||||
"type": "rector-extension",
|
||||
"extra": {
|
||||
|
2
vendor/composer/installed.php
vendored
2
vendor/composer/installed.php
vendored
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
|
||||
*/
|
||||
final class GeneratedConfig
|
||||
{
|
||||
public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => NULL, 'version' => 'dev-main ceda7a4'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => NULL, 'version' => 'dev-main 6dba109'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => NULL, 'version' => 'dev-main 03e2418'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => NULL, 'version' => 'dev-main 4661c01'));
|
||||
public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => NULL, 'version' => 'dev-main ceda7a4'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => NULL, 'version' => 'dev-main 6dba109'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => NULL, 'version' => 'dev-main 45b0f6b'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => NULL, 'version' => 'dev-main 4661c01'));
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ use Rector\PHPUnit\CodeQuality\Rector\ClassMethod\ReplaceTestAnnotationWithPrefi
|
||||
use Rector\PHPUnit\CodeQuality\Rector\Foreach_\SimplifyForeachInstanceOfRector;
|
||||
use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertCompareOnCountableWithMethodToAssertCountRector;
|
||||
use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertComparisonToSpecificMethodRector;
|
||||
use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertCountWithZeroToAssertEmptyRector;
|
||||
use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertEmptyNullableObjectToAssertInstanceofRector;
|
||||
use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertEqualsOrAssertSameFloatParameterToSpecificMethodsTypeRector;
|
||||
use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertEqualsToSameRector;
|
||||
@ -68,6 +69,7 @@ return static function (RectorConfig $rectorConfig) : void {
|
||||
UseSpecificWillMethodRector::class,
|
||||
UseSpecificWithMethodRector::class,
|
||||
AssertEmptyNullableObjectToAssertInstanceofRector::class,
|
||||
AssertCountWithZeroToAssertEmptyRector::class,
|
||||
/**
|
||||
* Improve direct testing of your code, without mock creep. Make it simple, clear and easy to maintain:
|
||||
*
|
||||
|
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\PHPUnit\CodeQuality\Rector\MethodCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Name;
|
||||
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
/**
|
||||
* @see \Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\AssertCountWithZeroToAssertEmptyRector\AssertCountWithZeroToAssertEmptyRectorTest
|
||||
*/
|
||||
final class AssertCountWithZeroToAssertEmptyRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @readonly
|
||||
*/
|
||||
private TestsNodeAnalyzer $testsNodeAnalyzer;
|
||||
public function __construct(TestsNodeAnalyzer $testsNodeAnalyzer)
|
||||
{
|
||||
$this->testsNodeAnalyzer = $testsNodeAnalyzer;
|
||||
}
|
||||
public function getRuleDefinition() : RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Change $this->assertCount(0, ...) to $this->assertEmpty(...)', [new CodeSample(<<<'CODE_SAMPLE'
|
||||
$this->assertCount(0, $countable);
|
||||
$this->assertNotCount(0, $countable);
|
||||
CODE_SAMPLE
|
||||
, <<<'CODE_SAMPLE'
|
||||
$this->assertEmpty($countable);
|
||||
$this->assertNotEmpty($countable);
|
||||
CODE_SAMPLE
|
||||
)]);
|
||||
}
|
||||
/**
|
||||
* @return array<class-string<MethodCall|StaticCall>>
|
||||
*/
|
||||
public function getNodeTypes() : array
|
||||
{
|
||||
return [MethodCall::class, StaticCall::class];
|
||||
}
|
||||
/**
|
||||
* @param MethodCall|StaticCall $node
|
||||
* @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|null
|
||||
*/
|
||||
public function refactor(Node $node)
|
||||
{
|
||||
if (!$this->testsNodeAnalyzer->isPHPUnitMethodCallNames($node, ['assertCount', 'assertNotCount'])) {
|
||||
return null;
|
||||
}
|
||||
if ($node->isFirstClassCallable()) {
|
||||
return null;
|
||||
}
|
||||
if (\count($node->getArgs()) < 2) {
|
||||
return null;
|
||||
}
|
||||
$type = $this->getType($node->getArgs()[0]->value);
|
||||
$value = $type->getConstantScalarValues()[0] ?? null;
|
||||
if ($value === 0) {
|
||||
$args = $node->getArgs();
|
||||
if ($this->isName($node->name, 'assertNotCount')) {
|
||||
$node->name = new Name('assertNotEmpty');
|
||||
} else {
|
||||
$node->name = new Name('assertEmpty');
|
||||
}
|
||||
\array_shift($args);
|
||||
$node->args = $args;
|
||||
return $node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user