Skip to content

Commit

Permalink
[Traverser] Add GlobalVariableNodeVisitor (#3816)
Browse files Browse the repository at this point in the history
* [Traverser] Add GlobalVariableNodeVariableVisitor

* rename

* Fix return

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* Fix phpstan

---------

Co-authored-by: GitHub Action <actions@github.com>
  • Loading branch information
samsonasik and actions-user authored May 13, 2023
1 parent 849459b commit 0d3a9a2
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 27 deletions.
5 changes: 5 additions & 0 deletions packages/NodeTypeResolver/Node/AttributeKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,9 @@ final class AttributeKey
* @var string
*/
public const ASSIGNED_TO = 'assigned_to';

/**
* @var string
*/
public const IS_GLOBAL_VAR = 'is_global_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\Global_;
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 GlobalVariableNodeVisitor 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[] $globalVariableNames */
$globalVariableNames = [];

foreach ($node->stmts as $stmt) {
if (! $stmt instanceof Global_) {
$this->setIsGlobalVarAttribute($stmt, $globalVariableNames);
continue;
}

foreach ($stmt->vars as $variable) {
if ($variable instanceof Variable && is_string($variable->name)) {
$variable->setAttribute(AttributeKey::IS_GLOBAL_VAR, true);
$globalVariableNames[] = $variable->name;
}
}
}

return null;
}

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

$this->simpleCallableNodeTraverser->traverseNodesWithCallable(
$stmt,
static function (Node $subNode) use ($globalVariableNames): 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, $globalVariableNames, true)) {
return null;
}

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

Expand All @@ -74,6 +75,7 @@ public function __construct(
private readonly ReflectionProvider $reflectionProvider,
RemoveDeepChainMethodCallNodeVisitor $removeDeepChainMethodCallNodeVisitor,
AssignedToNodeVisitor $assignedToNodeVisitor,
GlobalVariableNodeVisitor $globalVariableNodeVisitor,
private readonly ScopeFactory $scopeFactory,
private readonly PrivatesAccessor $privatesAccessor,
private readonly NodeNameResolver $nodeNameResolver,
Expand All @@ -83,6 +85,7 @@ public function __construct(
$this->nodeTraverser = new NodeTraverser();
$this->nodeTraverser->addVisitor($removeDeepChainMethodCallNodeVisitor);
$this->nodeTraverser->addVisitor($assignedToNodeVisitor);
$this->nodeTraverser->addVisitor($globalVariableNodeVisitor);
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/Testing/PHPUnit/AbstractTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ private function createConfigsHash(array $configFiles): string
if ($hash === false) {
throw new ShouldNotHappenException(sprintf('File %s is not readable', $configFile));
}

$configHash .= $hash;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\Type;
use Rector\Core\Enum\ObjectReference;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\DeadCode\Comparator\Parameter\ParameterDefaultsComparator;
use Rector\DeadCode\Comparator\Parameter\ParameterTypeComparator;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;

final class CurrentAndParentClassMethodComparator
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use PHPStan\Analyser\Scope;
use Rector\Core\NodeAnalyzer\InlineHTMLAnalyzer;
use Rector\Core\PhpParser\Node\CustomNode\FileWithoutNamespace;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\PSR4\Contract\PSR4AutoloadNamespaceMatcherInterface;
use Rector\PSR4\NodeManipulator\FullyQualifyStmtsAnalyzer;
Expand Down
3 changes: 0 additions & 3 deletions rules/Php71/NodeAnalyzer/CountableAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\ClassLike;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\Php\PhpPropertyReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ArrayType;
use PHPStan\Type\Constant\ConstantArrayType;
Expand All @@ -23,7 +21,6 @@
use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\TypeDeclaration\AlreadyAssignDetector\ConstructorAssignDetector;

Expand Down
1 change: 0 additions & 1 deletion rules/Php71/Rector/FuncCall/CountOnNullRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
use PHPStan\Type\UnionType;
use Rector\Core\NodeAnalyzer\VariableAnalyzer;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\NodeTypeResolver\Node\AttributeKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
use Rector\Core\ValueObject\MethodName;
use Rector\Naming\Naming\PropertyNaming;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;

final class TypeProvidingExprFromClassResolver
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Analyser\Scope;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Transform\NodeAnalyzer\FuncCallStaticCallToMethodCallAnalyzer;
use Rector\Transform\ValueObject\FuncCallToMethodCall;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use PHPStan\Analyser\Scope;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Transform\NodeAnalyzer\FuncCallStaticCallToMethodCallAnalyzer;
use Rector\Transform\ValueObject\StaticCallToMethodCall;
Expand Down
25 changes: 8 additions & 17 deletions src/NodeAnalyzer/VariableAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use PhpParser\Node\Expr\ClosureUse;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Global_;
use PhpParser\Node\Stmt\Static_;
use PhpParser\Node\Stmt\StaticVar;
use Rector\Core\PhpParser\Comparing\NodeComparator;
Expand All @@ -26,28 +25,24 @@ public function __construct(

public function isStaticOrGlobal(Variable $variable): bool
{
if ($this->isParentStaticOrGlobal($variable)) {
if ($variable->getAttribute(AttributeKey::IS_GLOBAL_VAR) === true) {
return true;
}

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

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

/**
* @var Static_|Global_ $node
* @var StaticVar[]|Variable[] $vars
*/
$vars = $node->vars;
foreach ($vars as $var) {
$staticVarVariable = $var instanceof StaticVar
? $var->var
: $var;

if ($this->nodeComparator->areNodesEqual($staticVarVariable, $variable)) {
if ($this->nodeComparator->areNodesEqual($var->var, $variable)) {
return true;
}
}
Expand Down Expand Up @@ -82,18 +77,14 @@ public function isUsedByReference(Variable $variable): bool
});
}

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

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

if ($parentNode instanceof Global_) {
return true;
}

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

0 comments on commit 0d3a9a2

Please sign in to comment.