From 5cddc0efffc1a10298972bbc92dfc0c40ea89df1 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 3 May 2025 01:43:54 +0700 Subject: [PATCH 1/3] [PHPStan 2.1.14] Fix resolve __toString() parent non builtin method without return type --- .../NodeAnalyzer/ClassChildAnalyzer.php | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php b/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php index 50d48af63a8..f54ea2ac0ee 100644 --- a/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php +++ b/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php @@ -4,14 +4,22 @@ namespace Rector\FamilyTree\NodeAnalyzer; +use PhpParser\Node\Stmt\ClassLike; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Reflection\Php\PhpMethodReflection; use PHPStan\Type\MixedType; +use PHPStan\Type\StringType; use PHPStan\Type\Type; +use Rector\PhpParser\AstResolver; final readonly class ClassChildAnalyzer { + public function __construct( + private AstResolver $astResolver + ) { + } + /** * Look both parent class and interface, yes, all PHP interface methods are abstract */ @@ -42,8 +50,14 @@ public function resolveParentClassMethodReturnType(ClassReflection $classReflect } foreach ($parentClassMethods as $parentClassMethod) { - $parametersAcceptor = ParametersAcceptorSelector::combineAcceptors($parentClassMethod->getVariants()); - $nativeReturnType = $parametersAcceptor->getNativeReturnType(); + // for downgrade purpose on __toString + // @see https://3v4l.org/kdcEh#v7.4.33 + // @see https://github.com/phpstan/phpstan-src/commit/3854cbc5748a7cb51ee0b86ceffe29bd0564bc98 + if ($parentClassMethod->getDeclaringClass()->isBuiltIn() || $methodName !== '__toString') { + $nativeReturnType = $this->resolveNativeType($parentClassMethod); + } else { + $nativeReturnType = $this->resolveToStringNativeTypeFromAstResolver($parentClassMethod); + } if (! $nativeReturnType instanceof MixedType) { return $nativeReturnType; @@ -53,6 +67,27 @@ public function resolveParentClassMethodReturnType(ClassReflection $classReflect return new MixedType(); } + private function resolveNativeType(PhpMethodReflection $phpMethodReflection): Type + { + $extendedParametersAcceptor = ParametersAcceptorSelector::combineAcceptors($phpMethodReflection->getVariants()); + return $extendedParametersAcceptor->getNativeReturnType(); + } + + private function resolveToStringNativeTypeFromAstResolver(PhpMethodReflection $phpMethodReflection): Type + { + $classReflection = $phpMethodReflection->getDeclaringClass(); + $class = $this->astResolver->resolveClassFromClassReflection($classReflection); + + if ($class instanceof ClassLike) { + $classMethod = $class->getMethod($phpMethodReflection->getName()); + if ($classMethod->returnType === null) { + return new MixedType(); + } + } + + return new StringType(); + } + /** * @return PhpMethodReflection[] */ From fcae20d336f4a3b98a8c7f2cd37244fd78aea854 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 3 May 2025 01:52:00 +0700 Subject: [PATCH 2/3] fix phpstan --- src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php b/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php index f54ea2ac0ee..89533b9e72d 100644 --- a/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php +++ b/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php @@ -5,6 +5,7 @@ namespace Rector\FamilyTree\NodeAnalyzer; use PhpParser\Node\Stmt\ClassLike; +use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Reflection\Php\PhpMethodReflection; @@ -80,7 +81,7 @@ private function resolveToStringNativeTypeFromAstResolver(PhpMethodReflection $p if ($class instanceof ClassLike) { $classMethod = $class->getMethod($phpMethodReflection->getName()); - if ($classMethod->returnType === null) { + if ($classMethod instanceof ClassMethod && $classMethod->returnType === null) { return new MixedType(); } } From 6cd137d36cd8ec5247028e711bd654715732d141 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 2 May 2025 18:53:59 +0000 Subject: [PATCH 3/3] [ci-review] Rector Rectify --- src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php b/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php index 89533b9e72d..1dcdf9c5553 100644 --- a/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php +++ b/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php @@ -4,6 +4,7 @@ namespace Rector\FamilyTree\NodeAnalyzer; +use PhpParser\Node; use PhpParser\Node\Stmt\ClassLike; use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Reflection\ClassReflection; @@ -81,7 +82,7 @@ private function resolveToStringNativeTypeFromAstResolver(PhpMethodReflection $p if ($class instanceof ClassLike) { $classMethod = $class->getMethod($phpMethodReflection->getName()); - if ($classMethod instanceof ClassMethod && $classMethod->returnType === null) { + if ($classMethod instanceof ClassMethod && !$classMethod->returnType instanceof Node) { return new MixedType(); } }