mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-28 05:35:20 +01:00
89 lines
2.8 KiB
PHP
89 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare (strict_types=1);
|
|
namespace Rector\Defluent\NodeAnalyzer;
|
|
|
|
use PhpParser\Node;
|
|
use PhpParser\Node\Expr;
|
|
use PhpParser\Node\Expr\MethodCall;
|
|
use PhpParser\Node\Expr\StaticCall;
|
|
use PhpParser\Node\Name;
|
|
use Rector\NodeNameResolver\NodeNameResolver;
|
|
use Rector\NodeTypeResolver\Node\AttributeKey;
|
|
/**
|
|
* Utils for chain of MethodCall Node:
|
|
* "$this->methodCall()->chainedMethodCall()"
|
|
*/
|
|
final class FluentChainMethodCallNodeAnalyzer
|
|
{
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\NodeNameResolver\NodeNameResolver
|
|
*/
|
|
private $nodeNameResolver;
|
|
public function __construct(NodeNameResolver $nodeNameResolver)
|
|
{
|
|
$this->nodeNameResolver = $nodeNameResolver;
|
|
}
|
|
/**
|
|
* @return string[]
|
|
*/
|
|
public function collectMethodCallNamesInChain(MethodCall $desiredMethodCall) : array
|
|
{
|
|
$methodCalls = $this->collectAllMethodCallsInChain($desiredMethodCall);
|
|
$methodNames = [];
|
|
foreach ($methodCalls as $methodCall) {
|
|
$methodName = $this->nodeNameResolver->getName($methodCall->name);
|
|
if ($methodName === null) {
|
|
continue;
|
|
}
|
|
$methodNames[] = $methodName;
|
|
}
|
|
return $methodNames;
|
|
}
|
|
/**
|
|
* @return MethodCall[]
|
|
*/
|
|
public function collectAllMethodCallsInChain(MethodCall $methodCall) : array
|
|
{
|
|
$chainMethodCalls = [$methodCall];
|
|
// traverse up
|
|
$currentNode = $methodCall->var;
|
|
while ($currentNode instanceof MethodCall) {
|
|
$chainMethodCalls[] = $currentNode;
|
|
$currentNode = $currentNode->var;
|
|
}
|
|
// traverse down
|
|
if (\count($chainMethodCalls) === 1) {
|
|
$currentNode = $methodCall->getAttribute(AttributeKey::PARENT_NODE);
|
|
while ($currentNode instanceof MethodCall) {
|
|
$chainMethodCalls[] = $currentNode;
|
|
$currentNode = $currentNode->getAttribute(AttributeKey::PARENT_NODE);
|
|
}
|
|
}
|
|
return $chainMethodCalls;
|
|
}
|
|
/**
|
|
* @return \PhpParser\Node\Expr|\PhpParser\Node\Name
|
|
*/
|
|
public function resolveRootExpr(MethodCall $methodCall)
|
|
{
|
|
$callerNode = $methodCall->var;
|
|
while ($callerNode instanceof MethodCall || $callerNode instanceof StaticCall) {
|
|
$callerNode = $callerNode instanceof StaticCall ? $callerNode->class : $callerNode->var;
|
|
}
|
|
return $callerNode;
|
|
}
|
|
public function resolveRootMethodCall(MethodCall $methodCall) : ?MethodCall
|
|
{
|
|
$callerNode = $methodCall->var;
|
|
while ($callerNode instanceof MethodCall && $callerNode->var instanceof MethodCall) {
|
|
$callerNode = $callerNode->var;
|
|
}
|
|
if ($callerNode instanceof MethodCall) {
|
|
return $callerNode;
|
|
}
|
|
return null;
|
|
}
|
|
}
|