diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveParentDelegatingConstructorRector/Fixture/skip_different_default_param_value.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveParentDelegatingConstructorRector/Fixture/skip_different_default_param_value.php.inc new file mode 100644 index 00000000000..be4d4591186 --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveParentDelegatingConstructorRector/Fixture/skip_different_default_param_value.php.inc @@ -0,0 +1,11 @@ + +----- + diff --git a/rules/DeadCode/Rector/ClassMethod/RemoveParentDelegatingConstructorRector.php b/rules/DeadCode/Rector/ClassMethod/RemoveParentDelegatingConstructorRector.php index 8f9e6bee211..c5d610c23ad 100644 --- a/rules/DeadCode/Rector/ClassMethod/RemoveParentDelegatingConstructorRector.php +++ b/rules/DeadCode/Rector/ClassMethod/RemoveParentDelegatingConstructorRector.php @@ -6,15 +6,18 @@ use PhpParser\Node; use PhpParser\Node\Arg; +use PhpParser\Node\Expr; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Expression; use PhpParser\NodeVisitor; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; use Rector\Enum\ObjectReference; +use Rector\PhpParser\Node\Value\ValueResolver; use Rector\PHPStan\ScopeFetcher; use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; use Rector\Rector\AbstractRector; @@ -30,6 +33,7 @@ final class RemoveParentDelegatingConstructorRector extends AbstractRector { public function __construct( private readonly StaticTypeMapper $staticTypeMapper, + private readonly ValueResolver $valueResolver ) { } @@ -230,9 +234,43 @@ private function areConstructorAndParentParameterTypesMatching( if (! $this->nodeComparator->areNodesEqual($parameterType, $parentParameterType)) { return false; } + + if (! $param->default instanceof Expr) { + continue; + } + + if ($this->isDifferentDefaultValue($param->default, $extendedMethodReflection, $index)) { + return false; + } } } return true; } + + private function isDifferentDefaultValue( + Expr $defaultExpr, + ExtendedMethodReflection $extendedMethodReflection, + int $index + ): bool { + $methodName = $extendedMethodReflection->getName(); + // native reflection is needed to get exact default value + if ($extendedMethodReflection->getDeclaringClass()->getNativeReflection()->hasMethod($methodName)) { + $parentMethod = $extendedMethodReflection->getDeclaringClass() + ->getNativeReflection() + ->getMethod($methodName); + $nativeParentParameterReflection = $parentMethod->getParameters()[$index] ?? null; + + if (! $nativeParentParameterReflection instanceof ReflectionParameter) { + return false; + } + + $parentDefault = $nativeParentParameterReflection->getDefaultValue(); + if (! $this->valueResolver->isValue($defaultExpr, $parentDefault)) { + return true; + } + } + + return false; + } }