Skip to content

Commit a291726

Browse files
committed
Updated Rector to commit 3b14af26db9eef322f21a9c783e6f9109e087c67
rectorphp/rector-src@3b14af2 Type hint array reduce closure (#6725)
1 parent d79d968 commit a291726

File tree

10 files changed

+246
-8
lines changed

10 files changed

+246
-8
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
3+
declare (strict_types=1);
4+
namespace Rector\TypeDeclaration\Rector\FunctionLike;
5+
6+
use PhpParser\Node;
7+
use PhpParser\Node\Expr\Closure;
8+
use PhpParser\Node\Expr\FuncCall;
9+
use PhpParser\Node\Param;
10+
use PHPStan\Reflection\Native\NativeFunctionReflection;
11+
use PHPStan\Type\ClosureType;
12+
use PHPStan\Type\MixedType;
13+
use PHPStan\Type\Type;
14+
use PHPStan\Type\UnionType;
15+
use PHPStan\Type\UnionTypeHelper;
16+
use Rector\NodeTypeResolver\TypeComparator\TypeComparator;
17+
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
18+
use Rector\Rector\AbstractRector;
19+
use Rector\Reflection\ReflectionResolver;
20+
use Rector\StaticTypeMapper\StaticTypeMapper;
21+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
22+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
23+
/**
24+
* @see \Rector\Tests\TypeDeclaration\Rector\FunctionLike\AddClosureParamTypeForArrayReduceRector\AddClosureParamTypeForArrayReduceRectorTest
25+
*/
26+
final class AddClosureParamTypeForArrayReduceRector extends AbstractRector
27+
{
28+
/**
29+
* @readonly
30+
*/
31+
private TypeComparator $typeComparator;
32+
/**
33+
* @readonly
34+
*/
35+
private StaticTypeMapper $staticTypeMapper;
36+
/**
37+
* @readonly
38+
*/
39+
private ReflectionResolver $reflectionResolver;
40+
public function __construct(TypeComparator $typeComparator, StaticTypeMapper $staticTypeMapper, ReflectionResolver $reflectionResolver)
41+
{
42+
$this->typeComparator = $typeComparator;
43+
$this->staticTypeMapper = $staticTypeMapper;
44+
$this->reflectionResolver = $reflectionResolver;
45+
}
46+
public function getRuleDefinition() : RuleDefinition
47+
{
48+
return new RuleDefinition('Applies type hints to array_map closures', [new CodeSample(<<<'CODE_SAMPLE'
49+
array_reduce($strings, function ($carry, $value, $key): string {
50+
return $carry . $value;
51+
}, $initialString);
52+
CODE_SAMPLE
53+
, <<<'CODE_SAMPLE'
54+
array_reduce($strings, function (string $carry, string $value): string {
55+
return $carry . $value;
56+
}, $initialString);
57+
CODE_SAMPLE
58+
)]);
59+
}
60+
public function getNodeTypes() : array
61+
{
62+
return [FuncCall::class];
63+
}
64+
/**
65+
* @param FuncCall $node
66+
*/
67+
public function refactor(Node $node) : ?Node
68+
{
69+
if ($node->isFirstClassCallable()) {
70+
return null;
71+
}
72+
if (!$this->isName($node, 'array_reduce')) {
73+
return null;
74+
}
75+
$funcReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node);
76+
if (!$funcReflection instanceof NativeFunctionReflection) {
77+
return null;
78+
}
79+
$args = $node->getArgs();
80+
if (!isset($args[1]) || !$args[1]->value instanceof Closure) {
81+
return null;
82+
}
83+
$closureType = $this->getType($args[1]->value);
84+
if (!$closureType instanceof ClosureType) {
85+
return null;
86+
}
87+
$carryType = $closureType->getReturnType();
88+
if (isset($args[2])) {
89+
$carryType = $this->combineTypes([$this->getType($args[2]->value), $carryType]);
90+
}
91+
$type = $this->getType($args[0]->value);
92+
$valueType = $type->getIterableValueType();
93+
if ($this->updateClosureWithTypes($args[1]->value, $valueType, $carryType)) {
94+
return $node;
95+
}
96+
return null;
97+
}
98+
private function updateClosureWithTypes(Closure $closure, ?Type $valueType, ?Type $carryType) : bool
99+
{
100+
$changes = \false;
101+
$carryParam = $closure->params[0] ?? null;
102+
$valueParam = $closure->params[1] ?? null;
103+
if ($valueParam instanceof Param && $valueType instanceof Type && $this->refactorParameter($valueParam, $valueType)) {
104+
$changes = \true;
105+
}
106+
if ($carryParam instanceof Param && $carryType instanceof Type && $this->refactorParameter($carryParam, $carryType)) {
107+
return \true;
108+
}
109+
return $changes;
110+
}
111+
private function refactorParameter(Param $param, Type $type) : bool
112+
{
113+
if ($type instanceof MixedType) {
114+
return \false;
115+
}
116+
// already set → no change
117+
if ($param->type instanceof Node) {
118+
$currentParamType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($param->type);
119+
if ($this->typeComparator->areTypesEqual($currentParamType, $type)) {
120+
return \false;
121+
}
122+
}
123+
$paramTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($type, TypeKind::PARAM);
124+
if (!$paramTypeNode instanceof Node) {
125+
return \false;
126+
}
127+
$param->type = $paramTypeNode;
128+
return \true;
129+
}
130+
/**
131+
* @param Type[] $types
132+
*/
133+
private function combineTypes(array $types) : ?Type
134+
{
135+
if ($types === []) {
136+
return null;
137+
}
138+
$types = \array_reduce($types, function (array $types, Type $type) : array {
139+
foreach ($types as $previousType) {
140+
if ($this->typeComparator->areTypesEqual($type, $previousType)) {
141+
return $types;
142+
}
143+
}
144+
$types[] = $type;
145+
return $types;
146+
}, []);
147+
if (\count($types) === 1) {
148+
return $types[0];
149+
}
150+
return new UnionType(UnionTypeHelper::sortTypes($types));
151+
}
152+
}

src/Application/VersionResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ final class VersionResolver
1919
* @api
2020
* @var string
2121
*/
22-
public const PACKAGE_VERSION = '3569d162bf6cb3730c091db0898798e59c93b4f4';
22+
public const PACKAGE_VERSION = '3b14af26db9eef322f21a9c783e6f9109e087c67';
2323
/**
2424
* @api
2525
* @var string
2626
*/
27-
public const RELEASE_DATE = '2025-02-08 12:36:53';
27+
public const RELEASE_DATE = '2025-02-09 17:27:26';
2828
/**
2929
* @var int
3030
*/

src/Config/Level/TypeDeclarationLevel.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
use Rector\TypeDeclaration\Rector\Closure\ClosureReturnTypeRector;
4949
use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector;
5050
use Rector\TypeDeclaration\Rector\Function_\AddFunctionVoidReturnTypeWhereNoReturnRector;
51+
use Rector\TypeDeclaration\Rector\FunctionLike\AddClosureParamTypeForArrayMapRector;
52+
use Rector\TypeDeclaration\Rector\FunctionLike\AddClosureParamTypeForArrayReduceRector;
5153
use Rector\TypeDeclaration\Rector\FunctionLike\AddParamTypeSplFixedArrayRector;
5254
use Rector\TypeDeclaration\Rector\FunctionLike\AddReturnTypeDeclarationFromYieldsRector;
5355
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector;
@@ -106,6 +108,8 @@ final class TypeDeclarationLevel
106108
// closures
107109
AddClosureNeverReturnTypeRector::class,
108110
ClosureReturnTypeRector::class,
111+
AddClosureParamTypeForArrayReduceRector::class,
112+
AddClosureParamTypeForArrayMapRector::class,
109113
// more risky rules
110114
ReturnTypeFromStrictParamRector::class,
111115
AddParamTypeFromPropertyTypeRector::class,

vendor/composer/autoload_classmap.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,6 +1790,7 @@
17901790
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCompareOnCountableWithMethodToAssertCountRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCompareOnCountableWithMethodToAssertCountRector.php',
17911791
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCompareToSpecificMethodRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCompareToSpecificMethodRector.php',
17921792
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertComparisonToSpecificMethodRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertComparisonToSpecificMethodRector.php',
1793+
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCountWithZeroToAssertEmptyRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCountWithZeroToAssertEmptyRector.php',
17931794
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEmptyNullableObjectToAssertInstanceofRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEmptyNullableObjectToAssertInstanceofRector.php',
17941795
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEqualsOrAssertSameFloatParameterToSpecificMethodsTypeRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEqualsOrAssertSameFloatParameterToSpecificMethodsTypeRector.php',
17951796
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEqualsToSameRector' => $vendorDir . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEqualsToSameRector.php',
@@ -2547,6 +2548,7 @@
25472548
'Rector\\TypeDeclaration\\Rector\\Empty_\\EmptyOnNullableObjectToInstanceOfRector' => $baseDir . '/rules/TypeDeclaration/Rector/Empty_/EmptyOnNullableObjectToInstanceOfRector.php',
25482549
'Rector\\TypeDeclaration\\Rector\\Expression\\InlineVarDocTagToAssertRector' => $baseDir . '/rules/TypeDeclaration/Rector/Expression/InlineVarDocTagToAssertRector.php',
25492550
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeForArrayMapRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeForArrayMapRector.php',
2551+
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeForArrayReduceRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeForArrayReduceRector.php',
25502552
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromArgRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromArgRector.php',
25512553
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromIterableMethodCallRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromIterableMethodCallRector.php',
25522554
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromObjectRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromObjectRector.php',

vendor/composer/autoload_static.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,6 +2009,7 @@ class ComposerStaticInita9ca9624b9ec3b7183135fb9d7d95d23
20092009
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCompareOnCountableWithMethodToAssertCountRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCompareOnCountableWithMethodToAssertCountRector.php',
20102010
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCompareToSpecificMethodRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCompareToSpecificMethodRector.php',
20112011
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertComparisonToSpecificMethodRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertComparisonToSpecificMethodRector.php',
2012+
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertCountWithZeroToAssertEmptyRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertCountWithZeroToAssertEmptyRector.php',
20122013
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEmptyNullableObjectToAssertInstanceofRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEmptyNullableObjectToAssertInstanceofRector.php',
20132014
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEqualsOrAssertSameFloatParameterToSpecificMethodsTypeRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEqualsOrAssertSameFloatParameterToSpecificMethodsTypeRector.php',
20142015
'Rector\\PHPUnit\\CodeQuality\\Rector\\MethodCall\\AssertEqualsToSameRector' => __DIR__ . '/..' . '/rector/rector-phpunit/rules/CodeQuality/Rector/MethodCall/AssertEqualsToSameRector.php',
@@ -2766,6 +2767,7 @@ class ComposerStaticInita9ca9624b9ec3b7183135fb9d7d95d23
27662767
'Rector\\TypeDeclaration\\Rector\\Empty_\\EmptyOnNullableObjectToInstanceOfRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Empty_/EmptyOnNullableObjectToInstanceOfRector.php',
27672768
'Rector\\TypeDeclaration\\Rector\\Expression\\InlineVarDocTagToAssertRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Expression/InlineVarDocTagToAssertRector.php',
27682769
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeForArrayMapRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeForArrayMapRector.php',
2770+
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeForArrayReduceRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeForArrayReduceRector.php',
27692771
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromArgRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromArgRector.php',
27702772
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromIterableMethodCallRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromIterableMethodCallRector.php',
27712773
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddClosureParamTypeFromObjectRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromObjectRector.php',

vendor/composer/installed.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,12 +1804,12 @@
18041804
"source": {
18051805
"type": "git",
18061806
"url": "https:\/\/github.com\/rectorphp\/rector-phpunit.git",
1807-
"reference": "03e2418e0107b33496c0f7bb99520ac8606a3d7a"
1807+
"reference": "45b0f6bfc11edec5aa9cf85314d26a6f48220c60"
18081808
},
18091809
"dist": {
18101810
"type": "zip",
1811-
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/03e2418e0107b33496c0f7bb99520ac8606a3d7a",
1812-
"reference": "03e2418e0107b33496c0f7bb99520ac8606a3d7a",
1811+
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/45b0f6bfc11edec5aa9cf85314d26a6f48220c60",
1812+
"reference": "45b0f6bfc11edec5aa9cf85314d26a6f48220c60",
18131813
"shasum": ""
18141814
},
18151815
"require": {
@@ -1830,7 +1830,7 @@
18301830
"tomasvotruba\/class-leak": "^1.2",
18311831
"tracy\/tracy": "^2.10"
18321832
},
1833-
"time": "2025-02-02T01:09:12+00:00",
1833+
"time": "2025-02-09T14:37:12+00:00",
18341834
"default-branch": true,
18351835
"type": "rector-extension",
18361836
"extra": {

0 commit comments

Comments
 (0)