mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-19 14:27:14 +01:00
Turn InterfaceTypeResolver to PHPStan reflection
This commit is contained in:
parent
13e2ed9fac
commit
915fec0ff8
@ -4,6 +4,7 @@ namespace Rector\NodeTypeResolver;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use PhpParser\NodeVisitor\NameResolver;
|
||||
use PHPStan\Analyser\NodeScopeResolver;
|
||||
use PHPStan\Analyser\Scope;
|
||||
@ -103,7 +104,7 @@ final class PHPStanNodeScopeResolver
|
||||
function (Node $node, Scope $scope): void {
|
||||
// the class reflection is resolved AFTER entering to class node
|
||||
// so we need to get it from the first after this one
|
||||
if ($node instanceof Class_) {
|
||||
if ($node instanceof Class_ || $node instanceof Interface_) {
|
||||
if (isset($node->namespacedName)) {
|
||||
$scope = $scope->enterClass($this->phpstanBroker->getClass((string) $node->namespacedName));
|
||||
} else {
|
||||
|
@ -1,121 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\PerNodeTypeResolver;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use PhpParser\Node\Stmt\Trait_;
|
||||
use PhpParser\Node\Stmt\TraitUse;
|
||||
use Rector\BetterReflection\Reflector\SmartClassReflector;
|
||||
use Rector\Node\Attribute;
|
||||
|
||||
abstract class AbstractClassLikeTypeResolver
|
||||
{
|
||||
/**
|
||||
* @var SmartClassReflector
|
||||
*/
|
||||
private $smartClassReflector;
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function setSmartClassReflector(SmartClassReflector $smartClassReflector): void
|
||||
{
|
||||
$this->smartClassReflector = $smartClassReflector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Name|ClassLike $node
|
||||
*/
|
||||
protected function resolveNameNode(Node $node): string
|
||||
{
|
||||
$name = (string) $node->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($name) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
$namespacedName = $node->getAttribute(Attribute::NAMESPACED_NAME);
|
||||
if ($namespacedName instanceof FullyQualified) {
|
||||
return $namespacedName->toString();
|
||||
}
|
||||
|
||||
$nameNode = $node->getAttribute(Attribute::RESOLVED_NAME);
|
||||
if ($nameNode instanceof Name) {
|
||||
return $nameNode->toString();
|
||||
}
|
||||
|
||||
if ($node instanceof Name) {
|
||||
return $node->toString();
|
||||
}
|
||||
|
||||
return (string) $node->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Class_|Interface_ $classLikeNode
|
||||
* @return string[]
|
||||
*/
|
||||
protected function resolveExtendsTypes(ClassLike $classLikeNode, ?string $className = null): array
|
||||
{
|
||||
if (! $classLikeNode->extends) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($classLikeNode instanceof Interface_ && $className) {
|
||||
return $this->smartClassReflector->getInterfaceParents($className);
|
||||
}
|
||||
|
||||
return $this->smartClassReflector->getClassParents($className, $classLikeNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Class_|Trait_ $classOrTraitNode
|
||||
* @return string[]
|
||||
*/
|
||||
protected function resolveUsedTraitTypes(ClassLike $classOrTraitNode): array
|
||||
{
|
||||
foreach ($classOrTraitNode->stmts as $stmt) {
|
||||
if (! $stmt instanceof TraitUse) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $this->resolveTraitNamesFromTraitUse($stmt);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function resolveImplementsTypes(Class_ $classNode): array
|
||||
{
|
||||
return array_map(function (Name $interface): string {
|
||||
if ($interface->hasAttribute(Attribute::RESOLVED_NAME)) {
|
||||
return (string) $interface->getAttribute(Attribute::RESOLVED_NAME);
|
||||
}
|
||||
|
||||
return $interface->toString();
|
||||
}, $classNode->implements);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function resolveTraitNamesFromTraitUse(TraitUse $traitUse): array
|
||||
{
|
||||
$usedTraits = [];
|
||||
|
||||
foreach ($traitUse->traits as $trait) {
|
||||
if ($trait->hasAttribute(Attribute::RESOLVED_NAME)) {
|
||||
$usedTraits[] = (string) $trait->getAttribute(Attribute::RESOLVED_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
return $usedTraits;
|
||||
}
|
||||
}
|
@ -4,9 +4,12 @@ namespace Rector\NodeTypeResolver\PerNodeTypeResolver;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
|
||||
|
||||
final class InterfaceTypeResolver extends AbstractClassLikeTypeResolver implements PerNodeTypeResolverInterface
|
||||
final class InterfaceTypeResolver implements PerNodeTypeResolverInterface
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
@ -22,8 +25,20 @@ final class InterfaceTypeResolver extends AbstractClassLikeTypeResolver implemen
|
||||
*/
|
||||
public function resolve(Node $interfaceNode): array
|
||||
{
|
||||
$interfaceName = $this->resolveNameNode($interfaceNode);
|
||||
/** @var Scope $interfaceNodeScope */
|
||||
$interfaceNodeScope = $interfaceNode->getAttribute(Attribute::SCOPE);
|
||||
|
||||
return array_merge([$interfaceName], $this->resolveExtendsTypes($interfaceNode, $interfaceName));
|
||||
/** @var ClassReflection $classReflection */
|
||||
$classReflection = $interfaceNodeScope->getClassReflection();
|
||||
|
||||
$types = [];
|
||||
$types[] = $classReflection->getName();
|
||||
|
||||
// interfaces
|
||||
foreach ($classReflection->getInterfaces() as $classReflection) {
|
||||
$types[] = $classReflection->getName();
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,12 @@ namespace Rector\NodeTypeResolver\PerNodeTypeResolver;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Trait_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
|
||||
|
||||
final class TraitTypeResolver extends AbstractClassLikeTypeResolver implements PerNodeTypeResolverInterface
|
||||
final class TraitTypeResolver implements PerNodeTypeResolverInterface
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
@ -22,6 +25,15 @@ final class TraitTypeResolver extends AbstractClassLikeTypeResolver implements P
|
||||
*/
|
||||
public function resolve(Node $traitNode): array
|
||||
{
|
||||
/** @var Scope $traitNodeScope */
|
||||
$traitNodeScope = $traitNode->getAttribute(Attribute::SCOPE);
|
||||
|
||||
/** @var ClassReflection $classReflection */
|
||||
$classReflection = $traitNodeScope->getClassReflection();
|
||||
|
||||
dump($classReflection);
|
||||
die;
|
||||
|
||||
$types[] = $this->resolveNameNode($traitNode);
|
||||
return array_merge($types, $this->resolveUsedTraitTypes($traitNode));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user