mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-03 01:40:49 +00:00
fc10fce13d
* re-enable rectify and ecs * [Rectify] [Php81] Enable Rectify on Readonly Property only * comment * [ci-review] Rector Rectify * [ci-review] Rector Rectify * [ci-review] Rector Rectify * [ci-review] Rector Rectify * [ci-review] Rector Rectify Co-authored-by: GitHub Action <action@github.com>
124 lines
3.6 KiB
PHP
124 lines
3.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Rector\NodeTypeResolver\NodeTypeResolver;
|
|
|
|
use PhpParser\Node;
|
|
use PhpParser\Node\Name;
|
|
use PhpParser\Node\Name\FullyQualified;
|
|
use PhpParser\Node\Stmt\Class_;
|
|
use PhpParser\Node\Stmt\ClassLike;
|
|
use PHPStan\Reflection\ReflectionProvider;
|
|
use PHPStan\Type\ArrayType;
|
|
use PHPStan\Type\MixedType;
|
|
use PHPStan\Type\ObjectType;
|
|
use PHPStan\Type\Type;
|
|
use PHPStan\Type\UnionType;
|
|
use Rector\Core\Enum\ObjectReference;
|
|
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
|
use Rector\NodeNameResolver\NodeNameResolver;
|
|
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
|
|
use Rector\NodeTypeResolver\Node\AttributeKey;
|
|
|
|
/**
|
|
* @see \Rector\Tests\NodeTypeResolver\PerNodeTypeResolver\NameTypeResolver\NameTypeResolverTest
|
|
*
|
|
* @implements NodeTypeResolverInterface<Name|FullyQualified>
|
|
*/
|
|
final class NameTypeResolver implements NodeTypeResolverInterface
|
|
{
|
|
public function __construct(
|
|
private readonly ReflectionProvider $reflectionProvider,
|
|
private readonly BetterNodeFinder $betterNodeFinder,
|
|
private readonly NodeNameResolver $nodeNameResolver
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @return array<class-string<Node>>
|
|
*/
|
|
public function getNodeClasses(): array
|
|
{
|
|
return [Name::class, FullyQualified::class];
|
|
}
|
|
|
|
/**
|
|
* @param Name $node
|
|
*/
|
|
public function resolve(Node $node): Type
|
|
{
|
|
if ($node->toString() === ObjectReference::PARENT()->getValue()) {
|
|
return $this->resolveParent($node);
|
|
}
|
|
|
|
$fullyQualifiedName = $this->resolveFullyQualifiedName($node);
|
|
|
|
if ($node->toString() === 'array') {
|
|
return new ArrayType(new MixedType(), new MixedType());
|
|
}
|
|
|
|
return new ObjectType($fullyQualifiedName);
|
|
}
|
|
|
|
private function resolveParent(Name $name): MixedType | ObjectType | UnionType
|
|
{
|
|
$class = $this->betterNodeFinder->findParentType($name, Class_::class);
|
|
if (! $class instanceof Class_) {
|
|
return new MixedType();
|
|
}
|
|
|
|
$className = $this->nodeNameResolver->getName($class);
|
|
if (! is_string($className)) {
|
|
return new MixedType();
|
|
}
|
|
|
|
if (! $this->reflectionProvider->hasClass($className)) {
|
|
return new MixedType();
|
|
}
|
|
|
|
$classReflection = $this->reflectionProvider->getClass($className);
|
|
|
|
$parentClassObjectTypes = [];
|
|
foreach ($classReflection->getParents() as $parentClassReflection) {
|
|
$parentClassObjectTypes[] = new ObjectType($parentClassReflection->getName());
|
|
}
|
|
|
|
if ($parentClassObjectTypes === []) {
|
|
return new MixedType();
|
|
}
|
|
|
|
if (count($parentClassObjectTypes) === 1) {
|
|
return $parentClassObjectTypes[0];
|
|
}
|
|
|
|
return new UnionType($parentClassObjectTypes);
|
|
}
|
|
|
|
private function resolveFullyQualifiedName(Name $name): string
|
|
{
|
|
$nameValue = $name->toString();
|
|
|
|
if (in_array(
|
|
$nameValue,
|
|
[ObjectReference::SELF()->getValue(), ObjectReference::STATIC()->getValue(), 'this'],
|
|
true
|
|
)) {
|
|
$classLike = $this->betterNodeFinder->findParentType($name, ClassLike::class);
|
|
if (! $classLike instanceof ClassLike) {
|
|
return $name->toString();
|
|
}
|
|
|
|
return (string) $this->nodeNameResolver->getName($classLike);
|
|
}
|
|
|
|
/** @var Name|null $resolvedNameNode */
|
|
$resolvedNameNode = $name->getAttribute(AttributeKey::RESOLVED_NAME);
|
|
if ($resolvedNameNode instanceof Name) {
|
|
return $resolvedNameNode->toString();
|
|
}
|
|
|
|
return $nameValue;
|
|
}
|
|
}
|