8000 [PHPStan 2.1.14] Fix resolve __toString() parent non builtin method w… · rectorphp/rector-src@394eb49 · GitHub
[go: up one dir, main page]

Skip to content

Commit 394eb49

Browse files
[PHPStan 2.1.14] Fix resolve __toString() parent non builtin method without return type (#6879)
* [PHPStan 2.1.14] Fix resolve __toString() parent non builtin method without return type * fix phpstan * [ci-review] Rector Rectify --------- Co-authored-by: GitHub Action <actions@github.com>
1 parent 788aef9 commit 394eb49

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,24 @@
44

55
namespace Rector\FamilyTree\NodeAnalyzer;
66

7+
use PhpParser\Node;
8+
use PhpParser\Node\Stmt\ClassLike;
9+
use PhpParser\Node\Stmt\ClassMethod;
710
use PHPStan\Reflection\ClassReflection;
811
use PHPStan\Reflection\ParametersAcceptorSelector;
912
use PHPStan\Reflection\Php\PhpMethodReflection;
1013
use PHPStan\Type\MixedType;
14+
use PHPStan\Type\StringType;
1115
use PHPStan\Type\Type;
16+
use Rector\PhpParser\AstResolver;
1217

1318
final readonly class ClassChildAnalyzer
1419
{
20+
public function __construct(
21+
private AstResolver $astResolver
22+
) {
23+
}
24+
1525
/**
1626
* Look both parent class and interface, yes, all PHP interface methods are abstract
1727
*/
@@ -42,8 +52,14 @@ public function resolveParentClassMethodReturnType(ClassReflection $classReflect
4252
}
4353

4454
foreach ($parentClassMethods as $parentClassMethod) {
45-
$parametersAcceptor = ParametersAcceptorSelector::combineAcceptors($parentClassMethod->getVariants());
46-
$nativeReturnType = $parametersAcceptor->getNativeReturnType();
55+
// for downgrade purpose on __toString
56+
// @see https://3v4l.org/kdcEh#v7.4.33
57+
// @see https://github.com/phpstan/phpstan-src/commit/3854cbc5748a7cb51ee0b86ceffe29bd0564bc98
58+
if ($parentClassMethod->getDeclaringClass()->isBuiltIn() || $methodName !== '__toString') {
59+
$nativeReturnType = $this->resolveNativeType($parentClassMethod);
60+
} else {
61+
$nativeReturnType = $this->resolveToStringNativeTypeFromAstResolver($parentClassMethod);
62+
}
4763

4864
if (! $nativeReturnType instanceof MixedType) {
4965
return $nativeReturnType;
@@ -53,6 +69,27 @@ public function resolveParentClassMethodReturnType(ClassReflection $classReflect
5369
return new MixedType();
5470
}
5571

72+
private function resolveNativeType(PhpMethodReflection $phpMethodReflection): Type
73+
{
74+
$extendedParametersAcceptor = ParametersAcceptorSelector::combineAcceptors($phpMethodReflection->getVariants());
75+
return $extendedParametersAcceptor->getNativeReturnType();
76+
}
77+
78+
private function resolveToStringNativeTypeFromAstResolver(PhpMethodReflection $phpMethodReflection): Type
79+
{
80+
$classReflection = $phpMethodReflection->getDeclaringClass();
81+
$class = $this->astResolver->resolveClassFromClassReflection($classReflection);
82+
83+
if ($class instanceof ClassLike) {
84+
$classMethod = $class->getMethod($phpMethodReflection->getName());
85+
if ($classMethod instanceof ClassMethod && !$classMethod->returnType instanceof Node) {
86+
return new MixedType();
87+
}
88+
}
89+
90+
return new StringType();
91+
}
92+
5693
/**
5794
* @return PhpMethodReflection[]
5895
*/

0 commit comments

Comments
 (0)
0