fluentChainMethodCallNodeAnalyzer = $fluentChainMethodCallNodeAnalyzer; $this->variableNaming = $variableNaming; $this->firstMethodCallVarResolver = $firstMethodCallVarResolver; } /** * @return Expression[] */ public function createFromNewAndRootMethodCall(\PhpParser\Node\Expr\New_ $new, \PhpParser\Node\Expr\MethodCall $rootMethodCall) : array { $variableName = $this->variableNaming->resolveFromNode($new); if ($variableName === null) { throw new \Rector\Core\Exception\ShouldNotHappenException(); } $newVariable = new \PhpParser\Node\Expr\Variable($variableName); $newStmts = []; $newStmts[] = $this->createAssignExpression($newVariable, $new); // resolve chain calls $chainMethodCalls = $this->fluentChainMethodCallNodeAnalyzer->collectAllMethodCallsInChainWithoutRootOne($rootMethodCall); $chainMethodCalls = \array_reverse($chainMethodCalls); foreach ($chainMethodCalls as $chainMethodCall) { $methodCall = new \PhpParser\Node\Expr\MethodCall($newVariable, $chainMethodCall->name, $chainMethodCall->args); $newStmts[] = new \PhpParser\Node\Stmt\Expression($methodCall); } return $newStmts; } /** * @param MethodCall[] $chainMethodCalls * @return Assign[]|MethodCall[]|Return_[] */ public function createFromAssignObjectAndMethodCalls(\Rector\Defluent\ValueObject\AssignAndRootExpr $assignAndRootExpr, array $chainMethodCalls, string $kind) : array { $nodesToAdd = []; $isNewNodeNeeded = $this->isNewNodeNeeded($assignAndRootExpr); if ($isNewNodeNeeded) { $nodesToAdd[] = $assignAndRootExpr->createFirstAssign(); } $decoupledMethodCalls = $this->createNonFluentMethodCalls($chainMethodCalls, $assignAndRootExpr, $isNewNodeNeeded); $nodesToAdd = \array_merge($nodesToAdd, $decoupledMethodCalls); if ($assignAndRootExpr->getSilentVariable() !== null && $kind !== \Rector\Defluent\ValueObject\FluentCallsKind::IN_ARGS) { $nodesToAdd[] = $assignAndRootExpr->getReturnSilentVariable(); } return $nodesToAdd; } private function createAssignExpression(\PhpParser\Node\Expr\Variable $newVariable, \PhpParser\Node\Expr\New_ $new) : \PhpParser\Node\Stmt\Expression { $assign = new \PhpParser\Node\Expr\Assign($newVariable, $new); return new \PhpParser\Node\Stmt\Expression($assign); } private function isNewNodeNeeded(\Rector\Defluent\ValueObject\AssignAndRootExpr $assignAndRootExpr) : bool { if ($assignAndRootExpr->isFirstCallFactory()) { return \true; } if ($assignAndRootExpr->getRootExpr() === $assignAndRootExpr->getAssignExpr()) { return \false; } return $assignAndRootExpr->getRootExpr() instanceof \PhpParser\Node\Expr\New_; } /** * @param MethodCall[] $chainMethodCalls * @return Assign[]|MethodCall[] */ private function createNonFluentMethodCalls(array $chainMethodCalls, \Rector\Defluent\ValueObject\AssignAndRootExpr $assignAndRootExpr, bool $isNewNodeNeeded) : array { $decoupledMethodCalls = []; \end($chainMethodCalls); $lastKey = \key($chainMethodCalls); foreach ($chainMethodCalls as $key => $chainMethodCall) { // skip first, already handled if ($key === $lastKey && $assignAndRootExpr->isFirstCallFactory() && $isNewNodeNeeded) { continue; } $chainMethodCall->var = $this->firstMethodCallVarResolver->resolve($assignAndRootExpr, $key); $decoupledMethodCalls[] = $chainMethodCall; } if ($assignAndRootExpr->getRootExpr() instanceof \PhpParser\Node\Expr\New_ && $assignAndRootExpr->getSilentVariable() !== null) { $decoupledMethodCalls[] = new \PhpParser\Node\Expr\Assign($assignAndRootExpr->getSilentVariable(), $assignAndRootExpr->getRootExpr()); } return \array_reverse($decoupledMethodCalls); } }