8000 [PHPStan 2.1.14] Fix resolve __toString() parent non builtin method without return type by samsonasik · Pull Request #6879 · rectorphp/rector-src · GitHub
[go: up one dir, main page]

Skip to content

[PHPStan 2.1.14] Fix resolve __toString() parent non builtin method without return type #6879

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 2, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[PHPStan 2.1.14] Fix resolve __toString() parent non builtin method w…
…ithout return type
  • Loading branch information
samsonasik committed May 2, 2025
commit 5cddc0efffc1a10298972bbc92dfc0c40ea89df1
39 changes: 37 additions & 2 deletions src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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;
Expand All @@ -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[]
*/
Expand Down
Loading
0