Skip to content

Commit 8921fd6

Browse files
committed
Updated Rector to commit 8a226613efca078f0dc3629e94c3463f4125b18f
rectorphp/rector-src@8a22661 fix: skip StaticCallToMethodCallRector when parent declares final __construct (#8001)
1 parent 5b9649f commit 8921fd6

8 files changed

Lines changed: 53 additions & 14 deletions

File tree

rules/CodeQuality/Rector/CallLike/AddNameToBooleanArgumentRector.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
declare (strict_types=1);
44
namespace Rector\CodeQuality\Rector\CallLike;
55

6+
use PhpParser\Node\Expr;
67
use PhpParser\Node;
78
use PhpParser\Node\Expr\CallLike;
89
use Rector\NodeAnalyzer\CallLikeArgumentNameAdder;
@@ -52,7 +53,7 @@ public function getNodeTypes(): array
5253
*/
5354
public function refactor(Node $node): ?Node
5455
{
55-
return $this->callLikeArgumentNameAdder->addNamesToArgs($node, fn($expr): bool => $this->valueResolver->isTrueOrFalse($expr));
56+
return $this->callLikeArgumentNameAdder->addNamesToArgs($node, fn(Expr $expr): bool => $this->valueResolver->isTrueOrFalse($expr));
5657
}
5758
public function provideMinPhpVersion(): int
5859
{

rules/CodeQuality/Rector/CallLike/AddNameToNullArgumentRector.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
declare (strict_types=1);
44
namespace Rector\CodeQuality\Rector\CallLike;
55

6+
use PhpParser\Node\Expr;
67
use PhpParser\Node;
78
use PhpParser\Node\Expr\CallLike;
89
use Rector\NodeAnalyzer\CallLikeArgumentNameAdder;
@@ -52,7 +53,7 @@ public function getNodeTypes(): array
5253
*/
5354
public function refactor(Node $node): ?Node
5455
{
55-
return $this->callLikeArgumentNameAdder->addNamesToArgs($node, fn($expr): bool => $this->valueResolver->isNull($expr));
56+
return $this->callLikeArgumentNameAdder->addNamesToArgs($node, fn(Expr $expr): bool => $this->valueResolver->isNull($expr));
5657
}
5758
public function provideMinPhpVersion(): int
5859
{

rules/Transform/NodeAnalyzer/FuncCallStaticCallToMethodCallAnalyzer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public function __construct(TypeProvidingExprFromClassResolver $typeProvidingExp
5454
$this->classDependencyManipulator = $classDependencyManipulator;
5555
}
5656
/**
57-
* @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\Variable
57+
* @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\Variable|null
5858
*/
5959
public function matchTypeProvidingExpr(Class_ $class, ClassMethod $classMethod, ObjectType $objectType)
6060
{
@@ -65,6 +65,10 @@ public function matchTypeProvidingExpr(Class_ $class, ClassMethod $classMethod,
6565
}
6666
return $expr;
6767
}
68+
// Cannot add constructor dependency when nearest parent constructor is final
69+
if ($this->classDependencyManipulator->hasFinalParentConstructor($class)) {
70+
return null;
71+
}
6872
$propertyName = $this->propertyNaming->fqnToVariableName($objectType);
6973
$this->classDependencyManipulator->addConstructorDependency($class, new PropertyMetadata($propertyName, $objectType));
7074
return $this->propertyFetchFactory->createFromType($objectType);

rules/Transform/Rector/FuncCall/FuncCallToMethodCallRector.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ public function refactor(Node $node): ?Node
9292
continue;
9393
}
9494
$expr = $this->funcCallStaticCallToMethodCallAnalyzer->matchTypeProvidingExpr($class, $classMethod, $funcNameToMethodCallName->getNewObjectType());
95+
if ($expr === null) {
96+
return null;
97+
}
9598
$hasChanged = \true;
9699
return $this->nodeFactory->createMethodCall($expr, $funcNameToMethodCallName->getNewMethodName(), $node->args);
97100
}

rules/Transform/Rector/StaticCall/StaticCallToMethodCallRector.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ public function refactor(Node $node): ?Node
9999
return $this->refactorToInstanceCall($node, $staticCallToMethodCall);
100100
}
101101
$expr = $this->funcCallStaticCallToMethodCallAnalyzer->matchTypeProvidingExpr($class, $classMethod, $staticCallToMethodCall->getClassObjectType());
102+
if ($expr === null) {
103+
return null;
104+
}
102105
$methodName = $this->getMethodName($node, $staticCallToMethodCall);
103106
$hasChanged = \true;
104107
return new MethodCall($expr, $methodName, $node->args);

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 = '749a17546633e5ce82c9b4b15ea0cd4d7acb8ec7';
22+
public const PACKAGE_VERSION = '8a226613efca078f0dc3629e94c3463f4125b18f';
2323
/**
2424
* @api
2525
* @var string
2626
*/
27-
public const RELEASE_DATE = '2026-05-21 10:44:14';
27+
public const RELEASE_DATE = '2026-05-21 20:22:41';
2828
/**
2929
* @var int
3030
*/

src/NodeAnalyzer/CallLikeArgumentNameAdder.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
declare (strict_types=1);
44
namespace Rector\NodeAnalyzer;
55

6+
use PhpParser\Node\Expr;
67
use PhpParser\Node\Arg;
78
use PhpParser\Node\Expr\CallLike;
89
use PhpParser\Node\Identifier;
@@ -27,20 +28,20 @@ public function __construct(ReflectionResolver $reflectionResolver)
2728
* argument whose value satisfies $shouldNameArgValue. All subsequent positional
2829
* arguments receive names too (required by PHP named-arg semantics).
2930
*
30-
* @param callable(\PhpParser\Node\Expr): bool $shouldNameArgValue
31+
* @param callable(Expr):bool $shouldNameArgValue
3132
*/
32-
public function addNamesToArgs(CallLike $node, callable $shouldNameArgValue): ?CallLike
33+
public function addNamesToArgs(CallLike $callLike, callable $shouldNameArgValue): ?CallLike
3334
{
34-
if ($this->shouldSkip($node)) {
35+
if ($this->shouldSkip($callLike)) {
3536
return null;
3637
}
37-
$reflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node);
38+
$reflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($callLike);
3839
if (!$reflection instanceof FunctionReflection && !$reflection instanceof MethodReflection) {
3940
return null;
4041
}
41-
$scope = ScopeFetcher::fetch($node);
42-
$args = $node->getArgs();
43-
$parameters = ParametersAcceptorSelectorVariantsWrapper::select($reflection, $node, $scope)->getParameters();
42+
$scope = ScopeFetcher::fetch($callLike);
43+
$args = $callLike->getArgs();
44+
$parameters = ParametersAcceptorSelectorVariantsWrapper::select($reflection, $callLike, $scope)->getParameters();
4445
$position = $this->resolveFirstPositionToName($args, $parameters, $shouldNameArgValue);
4546
if ($position === null) {
4647
return null;
@@ -62,7 +63,7 @@ public function addNamesToArgs(CallLike $node, callable $shouldNameArgValue): ?C
6263
if (!$wasChanged) {
6364
return null;
6465
}
65-
return $node;
66+
return $callLike;
6667
}
6768
private function shouldSkip(CallLike $callLike): bool
6869
{
@@ -83,7 +84,7 @@ private function shouldSkip(CallLike $callLike): bool
8384
/**
8485
* @param Arg[] $args
8586
* @param ParameterReflection[] $parameters
86-
* @param callable(\PhpParser\Node\Expr): bool $shouldNameArgValue
87+
* @param callable(Expr):bool $shouldNameArgValue
8788
*/
8889
private function resolveFirstPositionToName(array $args, array $parameters, callable $shouldNameArgValue): ?int
8990
{

src/NodeManipulator/ClassDependencyManipulator.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,32 @@ public function addStmtsToConstructorIfNotThereYet(Class_ $class, array $stmts):
161161
}
162162
$classMethod->stmts = array_merge($stmts, (array) $classMethod->stmts);
163163
}
164+
public function hasFinalParentConstructor(Class_ $class): bool
165+
{
166+
if ($class->getMethod(MethodName::CONSTRUCT) instanceof ClassMethod) {
167+
return \false;
168+
}
169+
$classReflection = $this->reflectionResolver->resolveClassReflection($class);
170+
if (!$classReflection instanceof ClassReflection) {
171+
return \false;
172+
}
173+
$ancestors = array_filter($classReflection->getAncestors(), static fn(ClassReflection $ancestor): bool => $ancestor->getName() !== $classReflection->getName());
174+
foreach ($ancestors as $ancestor) {
175+
if (!$ancestor->hasNativeMethod(MethodName::CONSTRUCT)) {
176+
continue;
177+
}
178+
$parentClass = $this->astResolver->resolveClassFromClassReflection($ancestor);
179+
if (!$parentClass instanceof ClassLike) {
180+
continue;
181+
}
182+
$parentConstructorMethod = $parentClass->getMethod(MethodName::CONSTRUCT);
183+
if (!$parentConstructorMethod instanceof ClassMethod) {
184+
continue;
185+
}
186+
return $parentConstructorMethod->isFinal();
187+
}
188+
return \false;
189+
}
164190
private function resolveConstruct(Class_ $class): ?ClassMethod
165191
{
166192
$constructorMethod = $class->getMethod(MethodName::CONSTRUCT);

0 commit comments

Comments
 (0)