mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-09 20:52:23 +00:00
decouple class const fetch and static call type resolvers
This commit is contained in:
parent
cd8ed41b9c
commit
af5acd4bf5
|
@ -17,7 +17,6 @@ use PhpParser\Node\Expr\FuncCall;
|
|||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Expr\StaticPropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Param;
|
||||
|
@ -236,10 +235,6 @@ final class NodeTypeResolver
|
|||
return $this->resolveClassNode($node);
|
||||
}
|
||||
|
||||
if ($node instanceof StaticCall) {
|
||||
return $this->resolveStaticCallType($node);
|
||||
}
|
||||
|
||||
if ($node instanceof ClassConstFetch) {
|
||||
return $this->resolve($node->class);
|
||||
}
|
||||
|
@ -538,42 +533,11 @@ final class NodeTypeResolver
|
|||
return $this->resolve($classNode);
|
||||
}
|
||||
|
||||
private function resolveStaticCallType(StaticCall $staticCall): Type
|
||||
{
|
||||
$classType = $this->resolve($staticCall->class);
|
||||
$methodName = $this->nameResolver->getName($staticCall->name);
|
||||
|
||||
// no specific method found, return class types, e.g. <ClassType>::$method()
|
||||
if (! is_string($methodName)) {
|
||||
return $classType;
|
||||
}
|
||||
|
||||
$classNames = TypeUtils::getDirectClassNames($classType);
|
||||
foreach ($classNames as $className) {
|
||||
if (! method_exists($className, $methodName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var Scope|null $nodeScope */
|
||||
$nodeScope = $staticCall->getAttribute(AttributeKey::SCOPE);
|
||||
if ($nodeScope === null) {
|
||||
return $classType;
|
||||
}
|
||||
|
||||
return $nodeScope->getType($staticCall);
|
||||
}
|
||||
|
||||
return $classType;
|
||||
}
|
||||
|
||||
private function resolveFirstType(Node $node): Type
|
||||
{
|
||||
// nodes that cannot be resolver by PHPStan
|
||||
$nodeClass = get_class($node);
|
||||
|
||||
foreach ($this->perNodeTypeResolvers as $perNodeTypeResolver) {
|
||||
foreach ($perNodeTypeResolver->getNodeClasses() as $nodeClass) {
|
||||
if (! is_a($node, $nodeClass, true)) {
|
||||
if (! is_a($node, $nodeClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -583,7 +547,6 @@ final class NodeTypeResolver
|
|||
|
||||
/** @var Scope|null $nodeScope */
|
||||
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
|
||||
|
||||
if ($nodeScope === null) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\PerNodeTypeResolver;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
|
||||
final class ClassConstFetchTypeResolver implements PerNodeTypeResolverInterface
|
||||
{
|
||||
/**
|
||||
* @var NodeTypeResolver
|
||||
*/
|
||||
private $nodeTypeResolver;
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function autowirePropertyTypeResolver(NodeTypeResolver $nodeTypeResolver): void
|
||||
{
|
||||
$this->nodeTypeResolver = $nodeTypeResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeClasses(): array
|
||||
{
|
||||
return [ClassConstFetch::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassConstFetch $node
|
||||
*/
|
||||
public function resolve(Node $node): Type
|
||||
{
|
||||
return $this->nodeTypeResolver->resolve($node->class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\PerNodeTypeResolver;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\TypeUtils;
|
||||
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
use Rector\PhpParser\Node\Resolver\NameResolver;
|
||||
|
||||
final class StaticCallTypeResolver implements PerNodeTypeResolverInterface
|
||||
{
|
||||
/**
|
||||
* @var NodeTypeResolver
|
||||
*/
|
||||
private $nodeTypeResolver;
|
||||
|
||||
/**
|
||||
* @var NameResolver
|
||||
*/
|
||||
private $nameResolver;
|
||||
|
||||
public function __construct(NameResolver $nameResolver)
|
||||
{
|
||||
$this->nameResolver = $nameResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function autowirePropertyTypeResolver(NodeTypeResolver $nodeTypeResolver): void
|
||||
{
|
||||
$this->nodeTypeResolver = $nodeTypeResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeClasses(): array
|
||||
{
|
||||
return [StaticCall::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StaticCall $node
|
||||
*/
|
||||
public function resolve(Node $node): Type
|
||||
{
|
||||
$classType = $this->nodeTypeResolver->resolve($node->class);
|
||||
$methodName = $this->nameResolver->getName($node->name);
|
||||
|
||||
// no specific method found, return class types, e.g. <ClassType>::$method()
|
||||
if (! is_string($methodName)) {
|
||||
return $classType;
|
||||
}
|
||||
|
||||
$classNames = TypeUtils::getDirectClassNames($classType);
|
||||
foreach ($classNames as $className) {
|
||||
if (! method_exists($className, $methodName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var Scope|null $nodeScope */
|
||||
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
|
||||
if ($nodeScope === null) {
|
||||
return $classType;
|
||||
}
|
||||
|
||||
return $nodeScope->getType($node);
|
||||
}
|
||||
|
||||
return $classType;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user