2020-12-21 03:12:42 +01:00
|
|
|
<?php
|
|
|
|
|
2021-05-09 20:15:43 +00:00
|
|
|
declare (strict_types=1);
|
2020-12-21 03:12:42 +01:00
|
|
|
namespace Rector\Defluent\ValueObject;
|
|
|
|
|
|
|
|
use PhpParser\Node\Expr;
|
|
|
|
use PhpParser\Node\Expr\Assign;
|
|
|
|
use PhpParser\Node\Expr\MethodCall;
|
|
|
|
use PhpParser\Node\Stmt\Expression;
|
|
|
|
use Rector\Core\Exception\ShouldNotHappenException;
|
|
|
|
use Rector\Defluent\Contract\ValueObject\FirstCallFactoryAwareInterface;
|
|
|
|
use Rector\Defluent\Contract\ValueObject\RootExprAwareInterface;
|
|
|
|
use Rector\NodeTypeResolver\Node\AttributeKey;
|
2021-05-10 22:23:08 +00:00
|
|
|
abstract class AbstractRootExpr implements \Rector\Defluent\Contract\ValueObject\RootExprAwareInterface, \Rector\Defluent\Contract\ValueObject\FirstCallFactoryAwareInterface
|
2020-12-21 03:12:42 +01:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var bool
|
|
|
|
*/
|
2021-05-09 20:15:43 +00:00
|
|
|
protected $isFirstCallFactory = \false;
|
2020-12-21 03:12:42 +01:00
|
|
|
/**
|
2021-05-12 13:15:45 +00:00
|
|
|
* @var \PhpParser\Node\Expr
|
2020-12-21 03:12:42 +01:00
|
|
|
*/
|
|
|
|
protected $rootExpr;
|
|
|
|
/**
|
2021-05-12 13:15:45 +00:00
|
|
|
* @var \PhpParser\Node\Expr
|
2020-12-21 03:12:42 +01:00
|
|
|
*/
|
|
|
|
protected $assignExpr;
|
2021-05-10 22:23:08 +00:00
|
|
|
public function createFirstAssign() : \PhpParser\Node\Expr\Assign
|
2020-12-21 03:12:42 +01:00
|
|
|
{
|
|
|
|
if ($this->isFirstCallFactory && $this->getFirstAssign() !== null) {
|
|
|
|
return $this->createFactoryAssign();
|
|
|
|
}
|
|
|
|
return $this->createAssign($this->assignExpr, $this->rootExpr);
|
|
|
|
}
|
2021-07-05 22:50:18 +00:00
|
|
|
/**
|
|
|
|
* @param \PhpParser\Node\Expr $assignVar
|
|
|
|
* @param \PhpParser\Node\Expr $assignExpr
|
|
|
|
*/
|
|
|
|
protected function createAssign($assignVar, $assignExpr) : \PhpParser\Node\Expr\Assign
|
2020-12-21 03:12:42 +01:00
|
|
|
{
|
|
|
|
if ($assignVar === $assignExpr) {
|
2021-05-10 22:23:08 +00:00
|
|
|
throw new \Rector\Core\Exception\ShouldNotHappenException();
|
2020-12-21 03:12:42 +01:00
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
return new \PhpParser\Node\Expr\Assign($assignVar, $assignExpr);
|
2020-12-21 03:12:42 +01:00
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
protected function getFirstAssign() : ?\PhpParser\Node\Expr\Assign
|
2020-12-21 03:12:42 +01:00
|
|
|
{
|
2021-05-10 22:23:08 +00:00
|
|
|
$currentStmt = $this->assignExpr->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::CURRENT_STATEMENT);
|
|
|
|
if (!$currentStmt instanceof \PhpParser\Node\Stmt\Expression) {
|
2020-12-21 03:12:42 +01:00
|
|
|
return null;
|
|
|
|
}
|
2021-03-08 15:52:36 +01:00
|
|
|
$currentExpr = $currentStmt->expr;
|
2021-05-10 22:23:08 +00:00
|
|
|
if ($currentExpr instanceof \PhpParser\Node\Expr\Assign) {
|
2021-03-08 15:52:36 +01:00
|
|
|
return $currentExpr;
|
2020-12-21 03:12:42 +01:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
private function createFactoryAssign() : \PhpParser\Node\Expr\Assign
|
2020-12-21 03:12:42 +01:00
|
|
|
{
|
|
|
|
/** @var Assign $firstAssign */
|
|
|
|
$firstAssign = $this->getFirstAssign();
|
|
|
|
$currentMethodCall = $firstAssign->expr;
|
2021-05-10 22:23:08 +00:00
|
|
|
if (!$currentMethodCall instanceof \PhpParser\Node\Expr\MethodCall) {
|
|
|
|
throw new \Rector\Core\Exception\ShouldNotHappenException();
|
2020-12-21 03:12:42 +01:00
|
|
|
}
|
|
|
|
$currentMethodCall = $this->resolveLastMethodCall($currentMethodCall);
|
|
|
|
// ensure var and expr are different
|
|
|
|
$assignVar = $firstAssign->var;
|
|
|
|
$assignExpr = $currentMethodCall;
|
|
|
|
return $this->createAssign($assignVar, $assignExpr);
|
|
|
|
}
|
2021-07-05 23:06:30 +00:00
|
|
|
private function resolveLastMethodCall(\PhpParser\Node\Expr\MethodCall $currentMethodCall) : \PhpParser\Node\Expr\MethodCall
|
2020-12-21 03:12:42 +01:00
|
|
|
{
|
2021-05-10 22:23:08 +00:00
|
|
|
while ($currentMethodCall->var instanceof \PhpParser\Node\Expr\MethodCall) {
|
2020-12-21 03:12:42 +01:00
|
|
|
$currentMethodCall = $currentMethodCall->var;
|
|
|
|
}
|
|
|
|
return $currentMethodCall;
|
|
|
|
}
|
|
|
|
}
|