Skip to content

Commit

Permalink
[Performance] Add $hasUnreachableStatementNode flag on PHPStanNodeSco…
Browse files Browse the repository at this point in the history
…peResolver to ensure execute UnreachableStatementNodeVisitor only when it has (#4416)
  • Loading branch information
samsonasik committed Jul 4, 2023
1 parent 93a4b2b commit fb0ae6d
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 14 deletions.
1 change: 1 addition & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@
__DIR__ . '/../src/functions',
__DIR__ . '/../src/PhpParser/Node/CustomNode',
__DIR__ . '/../src/PhpParser/ValueObject',
__DIR__ . '/../src/PHPStan/NodeVisitor',
__DIR__ . '/../src/constants.php',
]);

Expand Down
15 changes: 12 additions & 3 deletions packages/NodeTypeResolver/NodeScopeAndMetadataDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Rector\Core\ValueObject\Application\File;
use Rector\NodeTypeResolver\NodeVisitor\FunctionLikeParamArgPositionNodeVisitor;
use Rector\NodeTypeResolver\PHPStan\Scope\PHPStanNodeScopeResolver;
use Rector\NodeTypeResolver\PHPStan\Scope\ScopeFactory;

final class NodeScopeAndMetadataDecorator
{
Expand All @@ -23,7 +24,7 @@ public function __construct(
private readonly PHPStanNodeScopeResolver $phpStanNodeScopeResolver,
ParentConnectingVisitor $parentConnectingVisitor,
FunctionLikeParamArgPositionNodeVisitor $functionLikeParamArgPositionNodeVisitor,
UnreachableStatementNodeVisitor $unreachableStatementNodeVisitor,
private readonly ScopeFactory $scopeFactory,
private readonly FileWithoutNamespaceNodeTraverser $fileWithoutNamespaceNodeTraverser
) {
$this->nodeTraverser = new NodeTraverser();
Expand All @@ -35,8 +36,6 @@ public function __construct(
$this->nodeTraverser->addVisitor($parentConnectingVisitor);

$this->nodeTraverser->addVisitor($functionLikeParamArgPositionNodeVisitor);

$this->nodeTraverser->addVisitor($unreachableStatementNodeVisitor);
}

/**
Expand All @@ -48,6 +47,16 @@ public function decorateNodesFromFile(File $file, array $stmts): array
$stmts = $this->fileWithoutNamespaceNodeTraverser->traverse($stmts);
$stmts = $this->phpStanNodeScopeResolver->processNodes($stmts, $file->getFilePath());

if ($this->phpStanNodeScopeResolver->hasUnreachableStatementNode()) {
$this->nodeTraverser->addVisitor(
new UnreachableStatementNodeVisitor(
$this->phpStanNodeScopeResolver,
$file->getFilePath(),
$this->scopeFactory
)
);
}

return $this->nodeTraverser->traverse($stmts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ final class PHPStanNodeScopeResolver

private readonly NodeTraverser $nodeTraverser;

private bool $hasUnreachableStatementNode = false;

/**
* @param ScopeResolverNodeVisitorInterface[] $nodeVisitors
*/
Expand Down Expand Up @@ -117,6 +119,7 @@ public function processNodes(
?MutatingScope $formerMutatingScope = null
): array {
$isScopeRefreshing = $formerMutatingScope instanceof MutatingScope;
$this->hasUnreachableStatementNode = false;

/**
* The stmts must be array of Stmt, or it will be silently skipped by PHPStan
Expand Down Expand Up @@ -484,6 +487,13 @@ private function processUnreachableStatementNode(
$originalStmt->setAttribute(AttributeKey::SCOPE, $mutatingScope);

$this->processNodes([$originalStmt], $filePath, $mutatingScope);

$this->hasUnreachableStatementNode = true;
}

public function hasUnreachableStatementNode(): bool
{
return $this->hasUnreachableStatementNode;
}

private function processProperty(Property $property, MutatingScope $mutatingScope): void
Expand Down
14 changes: 3 additions & 11 deletions src/PHPStan/NodeVisitor/UnreachableStatementNodeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,15 @@
use PhpParser\NodeVisitorAbstract;
use PHPStan\Analyser\MutatingScope;
use Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface;
use Rector\Core\Provider\CurrentFileProvider;
use Rector\Core\ValueObject\Application\File;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PHPStan\Scope\PHPStanNodeScopeResolver;
use Rector\NodeTypeResolver\PHPStan\Scope\ScopeFactory;

final class UnreachableStatementNodeVisitor extends NodeVisitorAbstract
{
public function __construct(
private readonly CurrentFileProvider $currentFileProvider,
private readonly PHPStanNodeScopeResolver $phpStanNodeScopeResolver,
private readonly string $filePath,
private readonly ScopeFactory $scopeFactory
) {
}
Expand All @@ -35,17 +33,11 @@ public function enterNode(Node $node): ?Node
return null;
}

$file = $this->currentFileProvider->getFile();
if (! $file instanceof File) {
return null;
}

$filePath = $file->getFilePath();
$isPassedUnreachableStmt = false;

$mutatingScope = $node->getAttribute(AttributeKey::SCOPE);
$mutatingScope = $mutatingScope instanceof MutatingScope ? $mutatingScope : $this->scopeFactory->createFromFile(
$filePath
$this->filePath
);

foreach ($node->stmts as $stmt) {
Expand All @@ -57,7 +49,7 @@ public function enterNode(Node $node): ?Node
if ($isPassedUnreachableStmt) {
$stmt->setAttribute(AttributeKey::IS_UNREACHABLE, true);
$stmt->setAttribute(AttributeKey::SCOPE, $mutatingScope);
$this->phpStanNodeScopeResolver->processNodes([$stmt], $filePath, $mutatingScope);
$this->phpStanNodeScopeResolver->processNodes([$stmt], $this->filePath, $mutatingScope);
}
}

Expand Down

0 comments on commit fb0ae6d

Please sign in to comment.