Skip to content

Commit

Permalink
[FamilyTree] Remove AstResolver on FamilyRelationsAnalyzer (#5117)
Browse files Browse the repository at this point in the history
* [FamilyTree] Remove AstResolver on FamilyRelationsAnalyzer

* add return

* add return

* fix @api
  • Loading branch information
samsonasik authored Oct 5, 2023
1 parent a0f2f32 commit a6732a5
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 31 deletions.
26 changes: 14 additions & 12 deletions packages/FamilyTree/Reflection/FamilyRelationsAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -19,7 +18,6 @@ public function __construct(
private readonly ReflectionProvider $reflectionProvider,
private readonly PrivatesAccessor $privatesAccessor,
private readonly NodeNameResolver $nodeNameResolver,
private readonly AstResolver $astResolver,
) {
}

Expand Down Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Rector\Tests\Php80\Rector\Class_\StringableForToStringRector\Fixture;

use Rector\Tests\Php80\Rector\Class_\StringableForToStringRector\Source\ParentInterfaceWithStringable;

final class ExtendsWithInterface implements ParentInterfaceWithStringable
{
public function __toString()
{
return 'I can stringz';
}
}

?>
-----
<?php

namespace Rector\Tests\Php80\Rector\Class_\StringableForToStringRector\Fixture;

use Rector\Tests\Php80\Rector\Class_\StringableForToStringRector\Source\ParentInterfaceWithStringable;

final class ExtendsWithInterface implements ParentInterfaceWithStringable
{
public function __toString(): string
{
return 'I can stringz';
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Rector\Tests\Php80\Rector\Class_\StringableForToStringRector\Fixture;

class ParentChildReturnString
{
public function __toString()
{
return 'I can stringz';
}
}

class SomeChildReturnParentChildReturnString extends ParentChildReturnString
{
public function __toString()
{
return 'I can stringz';
}
}

?>
-----
<?php

namespace Rector\Tests\Php80\Rector\Class_\StringableForToStringRector\Fixture;

class ParentChildReturnString implements \Stringable
{
public function __toString(): string
{
return 'I can stringz';
}
}

class SomeChildReturnParentChildReturnString extends ParentChildReturnString
{
public function __toString(): string
{
return 'I can stringz';
}
}

?>

This file was deleted.

11 changes: 5 additions & 6 deletions rules/Php80/Rector/Class_/StringableForToStringRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,17 @@ public function refactor(Node $node): ?Node
// warning, classes that implements __toString() will return Stringable interface even if they don't implemen it
// reflection cannot be used for real detection
$classLikeAncestorNames = $this->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) {
Expand Down
3 changes: 3 additions & 0 deletions src/PhpParser/AstResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ public function __construct(
) {
}

/**
* @api downgrade
*/
public function resolveClassFromName(string $className): Class_ | Trait_ | Interface_ | Enum_ | null
{
if (! $this->reflectionProvider->hasClass($className)) {
Expand Down

0 comments on commit a6732a5

Please sign in to comment.