From df24aba2c193d0498336f7cbf38e29f119c28095 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 21 Aug 2025 11:42:24 +0700 Subject: [PATCH 1/3] [CodeQuality] Handle crash on native "object" type on TypeWillReturnCallableArrowFunctionRector --- .../fill_known_param_type_object.php.inc | 37 +++++++++++++++++++ .../Source/SomeMockedClass.php | 5 +++ 2 files changed, 42 insertions(+) create mode 100644 rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Fixture/fill_known_param_type_object.php.inc diff --git a/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Fixture/fill_known_param_type_object.php.inc b/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Fixture/fill_known_param_type_object.php.inc new file mode 100644 index 00000000..49a61ea6 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Fixture/fill_known_param_type_object.php.inc @@ -0,0 +1,37 @@ +createMock(SomeMockedClass::class) + ->method('nativeObject') + ->willReturnCallback(fn (object $object) => $value); + } +} + +?> +----- +createMock(SomeMockedClass::class) + ->method('nativeObject') + ->willReturnCallback(fn (object $name): object => $value); + } +} + +?> diff --git a/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Source/SomeMockedClass.php b/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Source/SomeMockedClass.php index 456fea95..87d34dcb 100644 --- a/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Source/SomeMockedClass.php +++ b/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Source/SomeMockedClass.php @@ -9,4 +9,9 @@ public function someMethod(string $name): int { return 100; } + + public function nativeObject(object $object): object + { + return $object; + } } From 29b09b99e1153dbc58260b2f7e8057dd0c26154e Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 21 Aug 2025 11:43:48 +0700 Subject: [PATCH 2/3] [CodeQuality] Handle crash on native "object" type on TypeWillReturnCallableArrowFunctionRector --- .../Reflection/MethodParametersAndReturnTypesResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php b/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php index 9b4f5ea0..b501405a 100644 --- a/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php +++ b/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php @@ -85,7 +85,7 @@ private function resolveReturnType( $returnType = $extendedParametersAcceptor->getNativeReturnType(); - if ($returnType->isObject()->yes() && $currentClassReflection->getName() !== $returnType->getClassReflection()->getName()) { + if ($returnType->isObject()->yes() && $currentClassReflection->getName() !== $returnType?->getClassReflection()?->getName()) { return new MixedType(); } From 0553b6f5b116db90390fca97b7b2d23fbbc60f51 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 21 Aug 2025 11:48:50 +0700 Subject: [PATCH 3/3] Fix --- phpstan.neon | 2 +- .../fill_known_param_type_object.php.inc | 2 +- ...MethodParametersAndReturnTypesResolver.php | 22 +++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index b1199e35..c1858e07 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -59,5 +59,5 @@ parameters: - '#::provideMinPhpVersion\(\) never returns \d+ so it can be removed from the return type#' - - message: '#Call to an undefined method PHPStan\\Type\\Type\:\:getClassReflection\(\)#' + message: '#Cannot call method getName\(\) on PHPStan\\Reflection\\ClassReflection\|null#' path: rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php diff --git a/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Fixture/fill_known_param_type_object.php.inc b/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Fixture/fill_known_param_type_object.php.inc index 49a61ea6..0d0c991e 100644 --- a/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Fixture/fill_known_param_type_object.php.inc +++ b/rules-tests/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector/Fixture/fill_known_param_type_object.php.inc @@ -30,7 +30,7 @@ final class FillKnownParamTypeObject extends TestCase { $this->createMock(SomeMockedClass::class) ->method('nativeObject') - ->willReturnCallback(fn (object $name): object => $value); + ->willReturnCallback(fn (object $object): object => $value); } } diff --git a/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php b/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php index b501405a..9efac0e5 100644 --- a/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php +++ b/rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php @@ -10,6 +10,7 @@ use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; +use PHPStan\Type\StaticType; use PHPStan\Type\Type; use Rector\Enum\ClassName; use Rector\PHPUnit\CodeQuality\ValueObject\ParamTypesAndReturnType; @@ -63,9 +64,9 @@ private function resolveParameterTypes( $parameterTypes = []; foreach ($extendedParametersAcceptor->getParameters() as $parameterReflection) { - $parameterType = $parameterReflection->getNativeType(); + $parameterType = $this->resolveObjectType($parameterReflection->getNativeType()); - if ($parameterType->isObject()->yes() && $currentClassReflection->getName() !== $parameterType->getClassReflection()->getName()) { + if ($parameterType instanceof ObjectType && $currentClassReflection->getName() !== $parameterType->getClassReflection()->getName()) { return []; } @@ -75,6 +76,19 @@ private function resolveParameterTypes( return $parameterTypes; } + private function resolveObjectType(Type $type): ObjectType|Type + { + if ($type instanceof ObjectType) { + return $type; + } + + if ($type instanceof StaticType) { + return $type->getStaticObjectType(); + } + + return $type; + } + private function resolveReturnType( ExtendedMethodReflection $extendedMethodReflection, ClassReflection $currentClassReflection @@ -83,9 +97,9 @@ private function resolveReturnType( $extendedMethodReflection->getVariants() ); - $returnType = $extendedParametersAcceptor->getNativeReturnType(); + $returnType = $this->resolveObjectType($extendedParametersAcceptor->getNativeReturnType()); - if ($returnType->isObject()->yes() && $currentClassReflection->getName() !== $returnType?->getClassReflection()?->getName()) { + if ($returnType instanceof ObjectType && $currentClassReflection->getName() !== $returnType->getClassReflection()->getName()) { return new MixedType(); }