Skip to content

Commit

Permalink
[NodeTypeResolver] Remove findParentType() on NameTypeResolver (#4199)
Browse files Browse the repository at this point in the history
* [NodeTypeResolver] Remove findParentType() on NameTypeResolver

* Fix

* [ci-review] Rector Rectify

* fix

* fix

* Fill ConstFetch and ClassConstFetch scope

* [ci-review] Rector Rectify

* Fix phpstan

* Fix phpstan

---------

Co-authored-by: GitHub Action <actions@github.com>
  • Loading branch information
samsonasik and actions-user committed Jun 17, 2023
1 parent 8263d90 commit 1d26219
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 28 deletions.
38 changes: 15 additions & 23 deletions packages/NodeTypeResolver/NodeTypeResolver/NameTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@
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\Reflection\ClassReflection;
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\Core\Reflection\ReflectionResolver;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Symfony\Contracts\Service\Attribute\Required;

/**
* @see \Rector\Tests\NodeTypeResolver\PerNodeTypeResolver\NameTypeResolver\NameTypeResolverTest
Expand All @@ -27,11 +25,12 @@
*/
final class NameTypeResolver implements NodeTypeResolverInterface
{
public function __construct(
private readonly ReflectionProvider $reflectionProvider,
private readonly BetterNodeFinder $betterNodeFinder,
private readonly NodeNameResolver $nodeNameResolver
) {
private ReflectionResolver $reflectionResolver;

#[Required]
public function autowire(ReflectionResolver $reflectionResolver): void
{
$this->reflectionResolver = $reflectionResolver;
}

/**
Expand Down Expand Up @@ -62,22 +61,15 @@ public function resolve(Node $node): Type

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)) {
$classReflection = $this->reflectionResolver->resolveClassReflection($name);
if (! $classReflection instanceof ClassReflection || ! $classReflection->isClass()) {
return new MixedType();
}

if (! $this->reflectionProvider->hasClass($className)) {
if ($classReflection->isAnonymous()) {
return new MixedType();
}

$classReflection = $this->reflectionProvider->getClass($className);

$parentClassObjectTypes = [];
foreach ($classReflection->getParents() as $parentClassReflection) {
$parentClassObjectTypes[] = new ObjectType($parentClassReflection->getName());
Expand All @@ -99,12 +91,12 @@ private function resolveFullyQualifiedName(Name $name): string
$nameValue = $name->toString();

if (in_array($nameValue, [ObjectReference::SELF, ObjectReference::STATIC, 'this'], true)) {
$classLike = $this->betterNodeFinder->findParentType($name, ClassLike::class);
if (! $classLike instanceof ClassLike) {
$classReflection = $this->reflectionResolver->resolveClassReflection($name);
if (! $classReflection instanceof ClassReflection || $classReflection->isAnonymous()) {
return $name->toString();
}

return (string) $this->nodeNameResolver->getName($classLike);
return $classReflection->getName();
}

return $nameValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@
use PhpParser\Node\Expr\BinaryOp;
use PhpParser\Node\Expr\CallLike;
use PhpParser\Node\Expr\Cast;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\NullsafeMethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Expr\Ternary;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
Expand Down Expand Up @@ -207,6 +215,29 @@ public function processNodes(
}
}

if ($node instanceof StaticPropertyFetch) {
$node->class->setAttribute(AttributeKey::SCOPE, $mutatingScope);
$node->name->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}

if ($node instanceof PropertyFetch) {
$node->var->setAttribute(AttributeKey::SCOPE, $mutatingScope);
$node->name->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}

if ($node instanceof CallLike) {
$this->processCallike($node, $mutatingScope);
}

if ($node instanceof ConstFetch) {
$node->name->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}

if ($node instanceof ClassConstFetch) {
$node->class->setAttribute(AttributeKey::SCOPE, $mutatingScope);
$node->name->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}

if ($node instanceof Trait_) {
$traitName = $this->resolveClassName($node);

Expand Down Expand Up @@ -265,6 +296,47 @@ public function processNodes(
return $this->processNodesWithDependentFiles($filePath, $stmts, $scope, $nodeCallback);
}

private function processCallike(CallLike $callLike, MutatingScope $mutatingScope): void
{
$this->processArgsForCallike($callLike, $mutatingScope);

if ($callLike instanceof StaticCall) {
$callLike->class->setAttribute(AttributeKey::SCOPE, $mutatingScope);
$callLike->name->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}

if ($callLike instanceof MethodCall) {
$callLike->var->setAttribute(AttributeKey::SCOPE, $mutatingScope);
$callLike->name->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}

if ($callLike instanceof FuncCall) {
$callLike->name->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}

if ($callLike instanceof New_ && ! $callLike->class instanceof Class_) {
$callLike->class->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}

if ($callLike instanceof NullsafeMethodCall) {
$callLike->var->setAttribute(AttributeKey::SCOPE, $mutatingScope);
$callLike->name->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}
}

private function processArgsForCallike(Expr $expr, MutatingScope $mutatingScope): void
{
if (! $expr instanceof CallLike) {
return;
}

if (! $expr->isFirstClassCallable()) {
foreach ($expr->getArgs() as $arg) {
$arg->value->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}
}
}

private function processAssign(Assign|AssignOp $assign, MutatingScope $mutatingScope): void
{
if (! $assign->var instanceof Variable || ! $assign->var->name instanceof Variable) {
Expand All @@ -275,11 +347,7 @@ private function processAssign(Assign|AssignOp $assign, MutatingScope $mutatingS
$expr = $assign;

while ($expr instanceof Assign || $expr instanceof AssignOp) {
if ($expr->expr instanceof CallLike && ! $expr->expr->isFirstClassCallable()) {
foreach ($expr->expr->getArgs() as $arg) {
$arg->value->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}
}
$this->processArgsForCallike($expr->expr, $mutatingScope);

// decorate value as well
$expr->var->setAttribute(AttributeKey::SCOPE, $mutatingScope);
Expand Down

0 comments on commit 1d26219

Please sign in to comment.