Skip to content

Commit

Permalink
Add currentStmt property on AbstractRector to allow pull Scope from i…
Browse files Browse the repository at this point in the history
…t on deep Expr (#4437)

Co-authored-by: GitHub Action <actions@github.com>
  • Loading branch information
samsonasik and actions-user committed Jul 19, 2023
1 parent ab13fe4 commit ceab6d7
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 23 deletions.
6 changes: 4 additions & 2 deletions src/Application/ChangedNodeScopeRefresher.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function __construct(
) {
}

public function refresh(Node $node, ?MutatingScope $mutatingScope, ?string $filePath = null): void
public function refresh(Node $node, ?MutatingScope $mutatingScope, ?string $filePath = null, ?Stmt $currentStmt = null): void
{
// nothing to refresh
if (! $this->scopeAnalyzer->isRefreshable($node)) {
Expand All @@ -56,7 +56,9 @@ public function refresh(Node $node, ?MutatingScope $mutatingScope, ?string $file
$filePath = $file->getFilePath();
}

$mutatingScope = $this->scopeAnalyzer->resolveScope($node, $filePath, $mutatingScope);
$mutatingScope = $mutatingScope instanceof MutatingScope
? $mutatingScope
: $this->scopeAnalyzer->resolveScope($node, $filePath, $currentStmt);

if (! $mutatingScope instanceof MutatingScope) {
$errorMessage = sprintf('Node "%s" with is missing scope required for scope refresh', $node::class);
Expand Down
19 changes: 8 additions & 11 deletions src/NodeAnalyzer/ScopeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt;
use PHPStan\Analyser\MutatingScope;
use PHPStan\Analyser\Scope;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PHPStan\Scope\ScopeFactory;

Expand All @@ -39,23 +39,20 @@ public function isRefreshable(Node $node): bool
return true;
}

public function resolveScope(
Node $node,
string $filePath,
?MutatingScope $mutatingScope = null
): ?MutatingScope {
if ($mutatingScope instanceof MutatingScope) {
return $mutatingScope;
}

public function resolveScope(Node $node, string $filePath, ?Stmt $currentStmt = null): ?Scope
{
// on File level
if ($node instanceof Stmt && $node->getAttribute(AttributeKey::STATEMENT_DEPTH) === 0) {
return $this->scopeFactory->createFromFile($filePath);
}

// too deep Expr, eg: $$param = $$bar = self::decodeValue($result->getItem()->getTextContent());
if ($node instanceof Expr && $node->getAttribute(AttributeKey::EXPRESSION_DEPTH) >= 2) {
return $this->scopeFactory->createFromFile($filePath);
$scope = $currentStmt instanceof Stmt
? $currentStmt->getAttribute(AttributeKey::SCOPE)
: $this->scopeFactory->createFromFile($filePath);

return $scope instanceof Scope ? $scope : $this->scopeFactory->createFromFile($filePath);
}

/**
Expand Down
23 changes: 14 additions & 9 deletions src/Rector/AbstractRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn

protected File $file;

protected ?Stmt $currentStmt = null;

private ChangedNodeScopeRefresher $changedNodeScopeRefresher;

private SimpleCallableNodeTraverser $simpleCallableNodeTraverser;
Expand Down Expand Up @@ -162,8 +164,7 @@ public function beforeTraverse(array $nodes): ?array

final public function enterNode(Node $node)
{
$nodeClass = $node::class;
if (! $this->isMatchingNodeType($nodeClass)) {
if (! $this->isMatchingNodeType($node)) {
return null;
}

Expand Down Expand Up @@ -360,19 +361,23 @@ private function refreshScopeNodes(array | Node $node, string $filePath, ?Mutati
$nodes = $node instanceof Node ? [$node] : $node;

foreach ($nodes as $node) {
$this->changedNodeScopeRefresher->refresh($node, $mutatingScope, $filePath);
$this->changedNodeScopeRefresher->refresh($node, $mutatingScope, $filePath, $this->currentStmt);
}
}

/**
* @param class-string<Node> $nodeClass
*/
private function isMatchingNodeType(string $nodeClass): bool
private function isMatchingNodeType(Node $node): bool
{
$nodeClass = $node::class;
foreach ($this->getNodeTypes() as $nodeType) {
if (is_a($nodeClass, $nodeType, true)) {
return true;
if (! is_a($nodeClass, $nodeType, true)) {
if ($node instanceof Stmt) {
$this->currentStmt = $node;
}

continue;
}

return true;
}

return false;
Expand Down
2 changes: 1 addition & 1 deletion src/Rector/AbstractScopeAwareRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function refactor(Node $node)
$currentScope = $node->getAttribute(AttributeKey::SCOPE);

if (! $currentScope instanceof MutatingScope) {
$currentScope = $this->scopeAnalyzer->resolveScope($node, $this->file->getFilePath());
$currentScope = $this->scopeAnalyzer->resolveScope($node, $this->file->getFilePath(), $this->currentStmt);
}

if (! $currentScope instanceof Scope) {
Expand Down

0 comments on commit ceab6d7

Please sign in to comment.