diff --git a/packages/FamilyTree/Reflection/FamilyRelationsAnalyzer.php b/packages/FamilyTree/Reflection/FamilyRelationsAnalyzer.php index 1732d805bfd..099c534f4e7 100644 --- a/packages/FamilyTree/Reflection/FamilyRelationsAnalyzer.php +++ b/packages/FamilyTree/Reflection/FamilyRelationsAnalyzer.php @@ -9,7 +9,6 @@ use PhpParser\Node\Stmt\Interface_; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ReflectionProvider; -use Rector\Core\PhpParser\AstResolver; use Rector\Core\Util\Reflection\PrivatesAccessor; use Rector\NodeNameResolver\NodeNameResolver; @@ -19,7 +18,6 @@ public function __construct( private readonly ReflectionProvider $reflectionProvider, private readonly PrivatesAccessor $privatesAccessor, private readonly NodeNameResolver $nodeNameResolver, - private readonly AstResolver $astResolver, ) { } @@ -58,25 +56,29 @@ public function getClassLikeAncestorNames(Class_ | Interface_ | Name $classOrNam if ($classOrName instanceof Name) { $fullName = $this->nodeNameResolver->getName($classOrName); - $classLike = $this->astResolver->resolveClassFromName($fullName); - } else { - $classLike = $classOrName; + $classReflection = $this->reflectionProvider->getClass($fullName); + $ancestors = array_merge($classReflection->getParents(), $classReflection->getInterfaces()); + + return array_map( + static fn (ClassReflection $classReflection): string => $classReflection->getName(), + $ancestors + ); } - if ($classLike instanceof Interface_) { - foreach ($classLike->extends as $extendInterfaceName) { + if ($classOrName instanceof Interface_) { + foreach ($classOrName->extends as $extendInterfaceName) { $ancestorNames[] = $this->nodeNameResolver->getName($extendInterfaceName); $ancestorNames = array_merge($ancestorNames, $this->getClassLikeAncestorNames($extendInterfaceName)); } } - if ($classLike instanceof Class_) { - if ($classLike->extends instanceof Name) { - $ancestorNames[] = $this->nodeNameResolver->getName($classLike->extends); - $ancestorNames = array_merge($ancestorNames, $this->getClassLikeAncestorNames($classLike->extends)); + if ($classOrName instanceof Class_) { + if ($classOrName->extends instanceof Name) { + $ancestorNames[] = $this->nodeNameResolver->getName($classOrName->extends); + $ancestorNames = array_merge($ancestorNames, $this->getClassLikeAncestorNames($classOrName->extends)); } - foreach ($classLike->implements as $implement) { + foreach ($classOrName->implements as $implement) { $ancestorNames[] = $this->nodeNameResolver->getName($implement); $ancestorNames = array_merge($ancestorNames, $this->getClassLikeAncestorNames($implement)); } diff --git a/rules-tests/Php80/Rector/Class_/StringableForToStringRector/Fixture/extends_with_interface.php.inc b/rules-tests/Php80/Rector/Class_/StringableForToStringRector/Fixture/extends_with_interface.php.inc new file mode 100644 index 00000000000..84198383e37 --- /dev/null +++ b/rules-tests/Php80/Rector/Class_/StringableForToStringRector/Fixture/extends_with_interface.php.inc @@ -0,0 +1,31 @@ + +----- + \ No newline at end of file diff --git a/rules-tests/Php80/Rector/Class_/StringableForToStringRector/Fixture/parent_child_return_string.php.inc b/rules-tests/Php80/Rector/Class_/StringableForToStringRector/Fixture/parent_child_return_string.php.inc new file mode 100644 index 00000000000..560a4bb50f2 --- /dev/null +++ b/rules-tests/Php80/Rector/Class_/StringableForToStringRector/Fixture/parent_child_return_string.php.inc @@ -0,0 +1,43 @@ + +----- + diff --git a/rules-tests/Php80/Rector/Class_/StringableForToStringRector/Fixture/skip_extends_with_interface.php.inc b/rules-tests/Php80/Rector/Class_/StringableForToStringRector/Fixture/skip_extends_with_interface.php.inc deleted file mode 100644 index c5c672647a6..00000000000 --- a/rules-tests/Php80/Rector/Class_/StringableForToStringRector/Fixture/skip_extends_with_interface.php.inc +++ /dev/null @@ -1,13 +0,0 @@ -familyRelationsAnalyzer->getClassLikeAncestorNames($node); - - if (in_array(self::STRINGABLE, $classLikeAncestorNames, true)) { - return null; - } + $isAncestorHasStringable = in_array(self::STRINGABLE, $classLikeAncestorNames, true); $returnType = $this->returnTypeInferer->inferFunctionLike($toStringClassMethod); if (! $returnType->isString()->yes()) { $this->processNotStringType($toStringClassMethod); } - // add interface - $node->implements[] = new FullyQualified(self::STRINGABLE); + if (! $isAncestorHasStringable) { + // add interface + $node->implements[] = new FullyQualified(self::STRINGABLE); + } // add return type if ($toStringClassMethod->returnType === null) { diff --git a/src/PhpParser/AstResolver.php b/src/PhpParser/AstResolver.php index 3885ea07c6a..545b43ab272 100644 --- a/src/PhpParser/AstResolver.php +++ b/src/PhpParser/AstResolver.php @@ -62,6 +62,9 @@ public function __construct( ) { } + /** + * @api downgrade + */ public function resolveClassFromName(string $className): Class_ | Trait_ | Interface_ | Enum_ | null { if (! $this->reflectionProvider->hasClass($className)) {