Skip to content

Commit

Permalink
[Traverser] Add StaticVariableNodeVisitor (#3817)
Browse files Browse the repository at this point in the history
* [Traverser] Add StaticVariableNodeVisitor

* fix phpstan
  • Loading branch information
samsonasik committed May 13, 2023
1 parent 0d3a9a2 commit 1828db5
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 38 deletions.
5 changes: 5 additions & 0 deletions packages/NodeTypeResolver/Node/AttributeKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,9 @@ final class AttributeKey
* @var string
*/
public const IS_GLOBAL_VAR = 'is_global_var';

/**
* @var string
*/
public const IS_STATIC_VAR = 'is_static_var';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;

use PhpParser\Node;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Static_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitorAbstract;
use Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser;

final class StaticVariableNodeVisitor extends NodeVisitorAbstract
{
public function __construct(
private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser
) {
}

public function enterNode(Node $node): ?Node
{
if (! $node instanceof StmtsAwareInterface) {
return null;
}

if ($node->stmts === null) {
return null;
}

/** @var string[] $staticVariableNames */
$staticVariableNames = [];

foreach ($node->stmts as $stmt) {
if (! $stmt instanceof Static_) {
$this->setIsStaticVarAttribute($stmt, $staticVariableNames);
continue;
}

foreach ($stmt->vars as $staticVar) {
if (is_string($staticVar->var->name)) {
$staticVar->var->setAttribute(AttributeKey::IS_STATIC_VAR, true);
$staticVariableNames[] = $staticVar->var->name;
}
}
}

return null;
}

/**
* @param string[] $staticVariableNames
*/
private function setIsStaticVarAttribute(Stmt $stmt, array $staticVariableNames): void
{
if ($staticVariableNames === []) {
return;
}

$this->simpleCallableNodeTraverser->traverseNodesWithCallable(
$stmt,
static function (Node $subNode) use ($staticVariableNames): int|null|Variable {
if ($subNode instanceof Class_) {
return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
}

if (! $subNode instanceof Variable) {
return null;
}

if (! is_string($subNode->name)) {
return null;
}

if (! in_array($subNode->name, $staticVariableNames, true)) {
return null;
}

$subNode->setAttribute(AttributeKey::IS_STATIC_VAR, true);
return $subNode;
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\AssignedToNodeVisitor;
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\GlobalVariableNodeVisitor;
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\RemoveDeepChainMethodCallNodeVisitor;
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\StaticVariableNodeVisitor;
use Webmozart\Assert\Assert;

/**
Expand All @@ -76,6 +77,7 @@ public function __construct(
RemoveDeepChainMethodCallNodeVisitor $removeDeepChainMethodCallNodeVisitor,
AssignedToNodeVisitor $assignedToNodeVisitor,
GlobalVariableNodeVisitor $globalVariableNodeVisitor,
StaticVariableNodeVisitor $staticVariableNodeVisitor,
private readonly ScopeFactory $scopeFactory,
private readonly PrivatesAccessor $privatesAccessor,
private readonly NodeNameResolver $nodeNameResolver,
Expand All @@ -86,6 +88,7 @@ public function __construct(
$this->nodeTraverser->addVisitor($removeDeepChainMethodCallNodeVisitor);
$this->nodeTraverser->addVisitor($assignedToNodeVisitor);
$this->nodeTraverser->addVisitor($globalVariableNodeVisitor);
$this->nodeTraverser->addVisitor($staticVariableNodeVisitor);
}

/**
Expand Down
39 changes: 1 addition & 38 deletions src/NodeAnalyzer/VariableAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
use PhpParser\Node\Expr\ClosureUse;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Static_;
use PhpParser\Node\Stmt\StaticVar;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeTypeResolver\Node\AttributeKey;
Expand All @@ -29,26 +27,7 @@ public function isStaticOrGlobal(Variable $variable): bool
return true;
}

if ($this->isParentStatic($variable)) {
return true;
}

return (bool) $this->betterNodeFinder->findFirstPrevious($variable, function (Node $node) use (
$variable
): bool {
if (! $node instanceof Static_) {
return false;
}

$vars = $node->vars;
foreach ($vars as $var) {
if ($this->nodeComparator->areNodesEqual($var->var, $variable)) {
return true;
}
}

return false;
});
return $variable->getAttribute(AttributeKey::IS_STATIC_VAR) === true;
}

public function isUsedByReference(Variable $variable): bool
Expand Down Expand Up @@ -77,22 +56,6 @@ public function isUsedByReference(Variable $variable): bool
});
}

private function isParentStatic(Variable $variable): bool
{
$parentNode = $variable->getAttribute(AttributeKey::PARENT_NODE);

if (! $parentNode instanceof Node) {
return false;
}

if (! $parentNode instanceof StaticVar) {
return false;
}

$parentParentNode = $parentNode->getAttribute(AttributeKey::PARENT_NODE);
return $parentParentNode instanceof Static_;
}

private function isParamReferenced(Node $node, Variable $variable): bool
{
if (! $node instanceof Param) {
Expand Down

0 comments on commit 1828db5

Please sign in to comment.