mirror of
https://github.com/rectorphp/rector.git
synced 2025-03-14 12:29:43 +01:00
[MagicDisclosure] Fluent refactoring (#3861)
Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
parent
55acb3578a
commit
4624778cb0
@ -98,6 +98,16 @@ trait NodeCommandersTrait
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $newNodes
|
||||
*/
|
||||
protected function addNodesBeforeNode(array $newNodes, Node $positionNode): void
|
||||
{
|
||||
foreach ($newNodes as $newNode) {
|
||||
$this->addNodeBeforeNode($newNode, $positionNode);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addNodeAfterNode(Node $newNode, Node $positionNode): void
|
||||
{
|
||||
$this->nodesToAddCollector->addNodeAfterNode($newNode, $positionNode);
|
||||
|
@ -163,7 +163,7 @@ final class ChainMethodCallNodeAnalyzer
|
||||
$chainMethodCalls = $this->collectAllMethodCallsInChain($methodCall);
|
||||
|
||||
foreach ($chainMethodCalls as $key => $chainMethodCall) {
|
||||
if (! $chainMethodCall->var instanceof MethodCall) {
|
||||
if (! $chainMethodCall->var instanceof MethodCall && ! $chainMethodCall->var instanceof New_) {
|
||||
unset($chainMethodCalls[$key]);
|
||||
break;
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\MagicDisclosure\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PHPStan\Type\MixedType;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
|
||||
final class NewChainMethodCallNodeAnalyzer
|
||||
{
|
||||
/**
|
||||
* @var NodeTypeResolver
|
||||
*/
|
||||
private $nodeTypeResolver;
|
||||
|
||||
public function __construct(NodeTypeResolver $nodeTypeResolver)
|
||||
{
|
||||
$this->nodeTypeResolver = $nodeTypeResolver;
|
||||
}
|
||||
|
||||
public function isNewMethodCallReturningSelf(MethodCall $methodCall): bool
|
||||
{
|
||||
$newStaticType = $this->nodeTypeResolver->getStaticType($methodCall->var);
|
||||
$methodCallStaticType = $this->nodeTypeResolver->getStaticType($methodCall);
|
||||
|
||||
return $methodCallStaticType->equals($newStaticType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method call with "new X", that returns "X"?
|
||||
* e.g.
|
||||
*
|
||||
* $this->setItem(new Item) // → returns "Item"
|
||||
*/
|
||||
public function matchNewInFluentSetterMethodCall(MethodCall $methodCall): ?New_
|
||||
{
|
||||
if (count($methodCall->args) !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$onlyArgValue = $methodCall->args[0]->value;
|
||||
if (! $onlyArgValue instanceof New_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$newType = $this->nodeTypeResolver->resolve($onlyArgValue);
|
||||
if ($newType instanceof MixedType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parentMethodCallReturnType = $this->nodeTypeResolver->resolve($methodCall);
|
||||
if (! $newType->equals($parentMethodCallReturnType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $onlyArgValue;
|
||||
}
|
||||
}
|
@ -8,10 +8,57 @@ use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use Rector\MagicDisclosure\NodeAnalyzer\ChainMethodCallNodeAnalyzer;
|
||||
use Rector\MagicDisclosure\ValueObject\AssignAndRootExpr;
|
||||
use Rector\NetteKdyby\Naming\VariableNaming;
|
||||
|
||||
final class NonFluentMethodCallFactory
|
||||
{
|
||||
/**
|
||||
* @var ChainMethodCallNodeAnalyzer
|
||||
*/
|
||||
private $chainMethodCallNodeAnalyzer;
|
||||
|
||||
/**
|
||||
* @var VariableNaming
|
||||
*/
|
||||
private $variableNaming;
|
||||
|
||||
public function __construct(
|
||||
ChainMethodCallNodeAnalyzer $chainMethodCallNodeAnalyzer,
|
||||
VariableNaming $variableNaming
|
||||
) {
|
||||
$this->chainMethodCallNodeAnalyzer = $chainMethodCallNodeAnalyzer;
|
||||
$this->variableNaming = $variableNaming;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Expression[]
|
||||
*/
|
||||
public function createFromNewAndRootMethodCall(New_ $new, MethodCall $rootMethodCall): array
|
||||
{
|
||||
$variableName = $this->variableNaming->resolveFromNode($new);
|
||||
$newVariable = new Variable($variableName);
|
||||
|
||||
$newStmts = [];
|
||||
$newStmts[] = $this->createAssignExpression($newVariable, $new);
|
||||
|
||||
// resolve chain calls
|
||||
$chainMethodCalls = $this->chainMethodCallNodeAnalyzer->collectAllMethodCallsInChainWithoutRootOne(
|
||||
$rootMethodCall
|
||||
);
|
||||
|
||||
$chainMethodCalls = array_reverse($chainMethodCalls);
|
||||
foreach ($chainMethodCalls as $chainMethodCall) {
|
||||
$methodCall = new MethodCall($newVariable, $chainMethodCall->name, $chainMethodCall->args);
|
||||
$newStmts[] = new Expression($methodCall);
|
||||
}
|
||||
|
||||
return $newStmts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall[] $chainMethodCalls
|
||||
*/
|
||||
@ -66,4 +113,10 @@ final class NonFluentMethodCallFactory
|
||||
|
||||
return $assignAndRootExpr->getRootExpr() !== $assignAndRootExpr->getAssignExpr();
|
||||
}
|
||||
|
||||
private function createAssignExpression(Variable $newVariable, New_ $new): Expression
|
||||
{
|
||||
$assign = new Assign($newVariable, $new);
|
||||
return new Expression($assign);
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ PHP
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
// @todo decouple "Return_" completelly to \Rector\MagicDisclosure\Rector\Return_\DefluentReturnMethodCallRector
|
||||
$methodCall = $this->matchMethodCall($node);
|
||||
if ($methodCall === null) {
|
||||
return null;
|
||||
@ -104,6 +105,7 @@ PHP
|
||||
return null;
|
||||
}
|
||||
|
||||
// DUPLICATED
|
||||
$chainMethodCalls = $this->chainMethodCallNodeAnalyzer->collectAllMethodCallsInChain($methodCall);
|
||||
|
||||
$assignAndRootExpr = $this->chainMethodCallRootExtractor->extractFromMethodCalls($chainMethodCalls);
|
||||
@ -177,6 +179,7 @@ PHP
|
||||
}
|
||||
|
||||
/**
|
||||
* @duplicated
|
||||
* @param MethodCall|Return_ $node
|
||||
*/
|
||||
private function removeCurrentNode(Node $node): void
|
||||
|
@ -7,17 +7,19 @@ namespace Rector\MagicDisclosure\Rector\MethodCall;
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\MagicDisclosure\NodeAnalyzer\ChainMethodCallNodeAnalyzer;
|
||||
use Rector\MagicDisclosure\NodeAnalyzer\NewChainMethodCallNodeAnalyzer;
|
||||
use Rector\MagicDisclosure\NodeFactory\NonFluentMethodCallFactory;
|
||||
use Rector\MagicDisclosure\NodeManipulator\ChainMethodCallRootExtractor;
|
||||
use Rector\MagicDisclosure\Rector\AbstractRector\AbstractConfigurableMatchTypeRector;
|
||||
use Rector\MagicDisclosure\ValueObject\AssignAndRootExpr;
|
||||
use Rector\NetteKdyby\Naming\VariableNaming;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
/**
|
||||
@ -32,24 +34,38 @@ final class InArgChainMethodCallToStandaloneMethodCallRector extends AbstractCon
|
||||
*/
|
||||
private $chainMethodCallNodeAnalyzer;
|
||||
|
||||
/**
|
||||
* @var ChainMethodCallRootExtractor
|
||||
*/
|
||||
private $chainMethodCallRootExtractor;
|
||||
|
||||
/**
|
||||
* @var NonFluentMethodCallFactory
|
||||
*/
|
||||
private $nonFluentMethodCallFactory;
|
||||
|
||||
/**
|
||||
* @var VariableNaming
|
||||
*/
|
||||
private $variableNaming;
|
||||
|
||||
/**
|
||||
* @var NewChainMethodCallNodeAnalyzer
|
||||
*/
|
||||
private $newChainMethodCallNodeAnalyzer;
|
||||
|
||||
/**
|
||||
* @var ChainMethodCallRootExtractor
|
||||
*/
|
||||
private $chainMethodCallRootExtractor;
|
||||
|
||||
public function __construct(
|
||||
ChainMethodCallNodeAnalyzer $chainMethodCallNodeAnalyzer,
|
||||
ChainMethodCallRootExtractor $chainMethodCallRootExtractor,
|
||||
NonFluentMethodCallFactory $nonFluentMethodCallFactory
|
||||
NonFluentMethodCallFactory $nonFluentMethodCallFactory,
|
||||
VariableNaming $variableNaming,
|
||||
NewChainMethodCallNodeAnalyzer $newChainMethodCallNodeAnalyzer,
|
||||
ChainMethodCallRootExtractor $chainMethodCallRootExtractor
|
||||
) {
|
||||
$this->chainMethodCallNodeAnalyzer = $chainMethodCallNodeAnalyzer;
|
||||
$this->chainMethodCallRootExtractor = $chainMethodCallRootExtractor;
|
||||
$this->nonFluentMethodCallFactory = $nonFluentMethodCallFactory;
|
||||
$this->variableNaming = $variableNaming;
|
||||
$this->newChainMethodCallNodeAnalyzer = $newChainMethodCallNodeAnalyzer;
|
||||
$this->chainMethodCallRootExtractor = $chainMethodCallRootExtractor;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
@ -99,24 +115,30 @@ PHP
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
$methodCall = $this->matchMethodCall($node);
|
||||
if ($methodCall === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->hasParentType($node, Arg::class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->chainMethodCallNodeAnalyzer->isLastChainMethodCall($methodCall)) {
|
||||
/** @var Arg $arg */
|
||||
$arg = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
/** @var Node|null $parentMethodCall */
|
||||
$parentMethodCall = $arg->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! $parentMethodCall instanceof MethodCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->isGetterMethodCall($methodCall)) {
|
||||
if (! $this->chainMethodCallNodeAnalyzer->isLastChainMethodCall($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$chainMethodCalls = $this->chainMethodCallNodeAnalyzer->collectAllMethodCallsInChain($methodCall);
|
||||
// create instances from (new ...)->call, re-use from
|
||||
if ($node->var instanceof New_) {
|
||||
$this->refactorNew($node, $node->var);
|
||||
return null;
|
||||
}
|
||||
|
||||
// DUPLCIATED
|
||||
$chainMethodCalls = $this->chainMethodCallNodeAnalyzer->collectAllMethodCallsInChain($node);
|
||||
|
||||
$assignAndRootExpr = $this->chainMethodCallRootExtractor->extractFromMethodCalls($chainMethodCalls);
|
||||
if ($assignAndRootExpr === null) {
|
||||
@ -132,39 +154,58 @@ PHP
|
||||
$chainMethodCalls
|
||||
);
|
||||
|
||||
$nodesToAdd = $this->addFluentAsArg($node, $assignAndRootExpr, $nodesToAdd);
|
||||
$this->addNodesBeforeNode($nodesToAdd, $node);
|
||||
|
||||
$this->removeCurrentNode($node);
|
||||
|
||||
foreach ($nodesToAdd as $nodeToAdd) {
|
||||
// needed to remove weird spacing
|
||||
$nodeToAdd->setAttribute(AttributeKey::ORIGINAL_NODE, null);
|
||||
$this->addNodeAfterNode($nodeToAdd, $node);
|
||||
}
|
||||
|
||||
return $node;
|
||||
return $assignAndRootExpr->getCallerExpr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall|Return_ $node
|
||||
*/
|
||||
private function matchMethodCall(Node $node): ?MethodCall
|
||||
private function removeParentParent(MethodCall $methodCall): void
|
||||
{
|
||||
if ($node instanceof Return_) {
|
||||
if ($node->expr === null) {
|
||||
return null;
|
||||
}
|
||||
/** @var Arg $parent */
|
||||
$parent = $methodCall->getAttribute(AttributeKey::PARENT_NODE);
|
||||
|
||||
if ($node->expr instanceof MethodCall) {
|
||||
return $node->expr;
|
||||
}
|
||||
return null;
|
||||
/** @var MethodCall $parentParent */
|
||||
$parentParent = $parent->getAttribute(AttributeKey::PARENT_NODE);
|
||||
|
||||
$this->removeNode($parentParent);
|
||||
}
|
||||
|
||||
private function createFluentAsArg(MethodCall $methodCall, Variable $variable): MethodCall
|
||||
{
|
||||
/** @var Arg $parent */
|
||||
$parent = $methodCall->getAttribute(AttributeKey::PARENT_NODE);
|
||||
/** @var MethodCall $parentParent */
|
||||
$parentParent = $parent->getAttribute(AttributeKey::PARENT_NODE);
|
||||
|
||||
$lastMethodCall = new MethodCall($parentParent->var, $parentParent->name);
|
||||
$lastMethodCall->args[] = new Arg($variable);
|
||||
|
||||
return $lastMethodCall;
|
||||
}
|
||||
|
||||
private function crateVariableFromNew(New_ $new): Variable
|
||||
{
|
||||
$variableName = $this->variableNaming->resolveFromNode($new);
|
||||
return new Variable($variableName);
|
||||
}
|
||||
|
||||
private function refactorNew(MethodCall $methodCall, New_ $new): void
|
||||
{
|
||||
if (! $this->newChainMethodCallNodeAnalyzer->isNewMethodCallReturningSelf($methodCall)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return $node;
|
||||
$nodesToAdd = $this->nonFluentMethodCallFactory->createFromNewAndRootMethodCall($new, $methodCall);
|
||||
|
||||
$newVariable = $this->crateVariableFromNew($new);
|
||||
$nodesToAdd[] = $this->createFluentAsArg($methodCall, $newVariable);
|
||||
|
||||
$this->addNodesBeforeNode($nodesToAdd, $methodCall);
|
||||
$this->removeParentParent($methodCall);
|
||||
}
|
||||
|
||||
/**
|
||||
* @duplicated
|
||||
* @param MethodCall[] $chainMethodCalls
|
||||
*/
|
||||
private function shouldSkip(AssignAndRootExpr $assignAndRootExpr, array $chainMethodCalls): bool
|
||||
@ -187,63 +228,4 @@ PHP
|
||||
|
||||
return ! $this->isMatchedType($calleeUniqueType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall|Return_ $node
|
||||
*/
|
||||
private function removeCurrentNode(Node $node): void
|
||||
{
|
||||
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parentNode instanceof Assign) {
|
||||
$this->removeNode($parentNode);
|
||||
return;
|
||||
}
|
||||
|
||||
// part of method call
|
||||
if ($parentNode instanceof Arg) {
|
||||
$parentParent = $parentNode->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parentParent instanceof MethodCall) {
|
||||
$this->removeNode($parentParent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$this->removeNode($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Return_|MethodCall $node
|
||||
* @param Node[] $nodesToAdd
|
||||
* @return Node[]
|
||||
*/
|
||||
private function addFluentAsArg(Node $node, AssignAndRootExpr $assignAndRootExpr, array $nodesToAdd): array
|
||||
{
|
||||
$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! $parent instanceof Arg) {
|
||||
return $nodesToAdd;
|
||||
}
|
||||
|
||||
$parentParent = $parent->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! $parentParent instanceof MethodCall) {
|
||||
return $nodesToAdd;
|
||||
}
|
||||
|
||||
$lastMethodCall = new MethodCall($parentParent->var, $parentParent->name);
|
||||
$lastMethodCall->args[] = new Arg($assignAndRootExpr->getRootExpr());
|
||||
$nodesToAdd[] = $lastMethodCall;
|
||||
|
||||
return $nodesToAdd;
|
||||
}
|
||||
|
||||
private function isGetterMethodCall(MethodCall $methodCall): bool
|
||||
{
|
||||
if ($methodCall->var instanceof MethodCall) {
|
||||
return false;
|
||||
}
|
||||
$methodCallStaticType = $this->getStaticType($methodCall);
|
||||
$methodCallVarStaticType = $this->getStaticType($methodCall->var);
|
||||
|
||||
// getter short call type
|
||||
return ! $methodCallStaticType->equals($methodCallVarStaticType);
|
||||
}
|
||||
}
|
||||
|
@ -6,18 +6,16 @@ namespace Rector\MagicDisclosure\Rector\MethodCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PHPStan\Type\MixedType;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\MagicDisclosure\NodeAnalyzer\ChainMethodCallNodeAnalyzer;
|
||||
use Rector\MagicDisclosure\NodeAnalyzer\NewChainMethodCallNodeAnalyzer;
|
||||
use Rector\MagicDisclosure\NodeFactory\NonFluentMethodCallFactory;
|
||||
use Rector\NetteKdyby\Naming\VariableNaming;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
|
||||
|
||||
/**
|
||||
* @sponsor Thanks https://amateri.com for sponsoring this rule - visit them on https://www.startupjobs.cz/startup/scrumworks-s-r-o
|
||||
@ -36,12 +34,26 @@ final class MethodCallOnSetterMethodCallToStandaloneAssignRector extends Abstrac
|
||||
*/
|
||||
private $chainMethodCallNodeAnalyzer;
|
||||
|
||||
/**
|
||||
* @var NonFluentMethodCallFactory
|
||||
*/
|
||||
private $nonFluentMethodCallFactory;
|
||||
|
||||
/**
|
||||
* @var NewChainMethodCallNodeAnalyzer
|
||||
*/
|
||||
private $newChainMethodCallNodeAnalyzer;
|
||||
|
||||
public function __construct(
|
||||
VariableNaming $variableNaming,
|
||||
ChainMethodCallNodeAnalyzer $chainMethodCallNodeAnalyzer
|
||||
ChainMethodCallNodeAnalyzer $chainMethodCallNodeAnalyzer,
|
||||
NonFluentMethodCallFactory $nonFluentMethodCallFactory,
|
||||
NewChainMethodCallNodeAnalyzer $newChainMethodCallNodeAnalyzer
|
||||
) {
|
||||
$this->variableNaming = $variableNaming;
|
||||
$this->chainMethodCallNodeAnalyzer = $chainMethodCallNodeAnalyzer;
|
||||
$this->nonFluentMethodCallFactory = $nonFluentMethodCallFactory;
|
||||
$this->newChainMethodCallNodeAnalyzer = $newChainMethodCallNodeAnalyzer;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
@ -104,67 +116,24 @@ PHP
|
||||
return null;
|
||||
}
|
||||
|
||||
$new = $this->matchNewInFluentSetterMethodCall($rootMethodCall);
|
||||
$new = $this->newChainMethodCallNodeAnalyzer->matchNewInFluentSetterMethodCall($rootMethodCall);
|
||||
if ($new === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$variableName = $this->variableNaming->resolveFromNode($new);
|
||||
$newVariable = new Variable($variableName);
|
||||
|
||||
$assignExpression = $this->createAssignExpression($newVariable, $new);
|
||||
$this->addNodeBeforeNode($assignExpression, $node);
|
||||
|
||||
// resolve chain calls
|
||||
$chainMethodCalls = $this->chainMethodCallNodeAnalyzer->collectAllMethodCallsInChainWithoutRootOne($node);
|
||||
$chainMethodCalls = array_reverse($chainMethodCalls);
|
||||
foreach ($chainMethodCalls as $chainMethodCall) {
|
||||
$currentMethodCall = new MethodCall($newVariable, $chainMethodCall->name, $chainMethodCall->args);
|
||||
$this->addNodeBeforeNode($currentMethodCall, $node);
|
||||
}
|
||||
$newStmts = $this->nonFluentMethodCallFactory->createFromNewAndRootMethodCall($new, $node);
|
||||
$this->addNodesBeforeNode($newStmts, $node);
|
||||
|
||||
// change new arg to root variable
|
||||
$newVariable = $this->crateVariableFromNew($new);
|
||||
$rootMethodCall->args = [new Arg($newVariable)];
|
||||
|
||||
return $rootMethodCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method call with "new X", that returns "X"?
|
||||
* e.g.
|
||||
*
|
||||
* $this->setItem(new Item) // → returns "Item"
|
||||
* @duplicated
|
||||
*/
|
||||
private function matchNewInFluentSetterMethodCall(MethodCall $methodCall): ?New_
|
||||
{
|
||||
if (count($methodCall->args) !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$onlyArgValue = $methodCall->args[0]->value;
|
||||
if (! $onlyArgValue instanceof New_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$newType = $this->getObjectType($onlyArgValue);
|
||||
if ($newType instanceof MixedType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parentMethodCallReturnType = $this->getObjectType($methodCall);
|
||||
if (! $newType->equals($parentMethodCallReturnType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $onlyArgValue;
|
||||
}
|
||||
|
||||
private function createAssignExpression(Variable $newVariable, New_ $new): Expression
|
||||
{
|
||||
$assign = new Assign($newVariable, $new);
|
||||
return new Expression($assign);
|
||||
}
|
||||
|
||||
private function shouldSkip(MethodCall $methodCall): bool
|
||||
{
|
||||
if (! $methodCall->var instanceof MethodCall) {
|
||||
@ -173,4 +142,10 @@ PHP
|
||||
|
||||
return ! $this->chainMethodCallNodeAnalyzer->isLastChainMethodCall($methodCall);
|
||||
}
|
||||
|
||||
private function crateVariableFromNew(New_ $new): Variable
|
||||
{
|
||||
$variableName = $this->variableNaming->resolveFromNode($new);
|
||||
return new Variable($variableName);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\MagicDisclosure\Tests\Rector\MethodCall\InArgChainMethodCallToStandaloneMethodCallRector\Fixture;
|
||||
|
||||
use Rector\MagicDisclosure\Tests\Rector\MethodCall\InArgChainMethodCallToStandaloneMethodCallRector\Source\FluentClass;
|
||||
|
||||
class NewInArg
|
||||
{
|
||||
public function someFunction(FluentClass $someClass)
|
||||
{
|
||||
$this->processFluentClass((new FluentClass())->someFunction());
|
||||
}
|
||||
|
||||
public function processFluentClass(FluentClass $someClass)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\MagicDisclosure\Tests\Rector\MethodCall\InArgChainMethodCallToStandaloneMethodCallRector\Fixture;
|
||||
|
||||
use Rector\MagicDisclosure\Tests\Rector\MethodCall\InArgChainMethodCallToStandaloneMethodCallRector\Source\FluentClass;
|
||||
|
||||
class NewInArg
|
||||
{
|
||||
public function someFunction(FluentClass $someClass)
|
||||
{
|
||||
$fluentClass = new FluentClass();
|
||||
$fluentClass->someFunction();
|
||||
$this->processFluentClass($fluentClass);
|
||||
}
|
||||
|
||||
public function processFluentClass(FluentClass $someClass)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\MagicDisclosure\Tests\Rector\MethodCall\InArgChainMethodCallToStandaloneMethodCallRector\Fixture;
|
||||
|
||||
use Rector\MagicDisclosure\Tests\Rector\MethodCall\InArgChainMethodCallToStandaloneMethodCallRector\Source\FluentClass;
|
||||
|
||||
class SkipNonArg
|
||||
{
|
||||
public function someFunction()
|
||||
{
|
||||
(new FluentClass())->otherFunction()
|
||||
->someFunction();
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\MagicDisclosure\Tests\Rector\MethodCall\InArgChainMethodCallToStandaloneMethodCallRector\Fixture;
|
||||
|
||||
use Rector\MagicDisclosure\Tests\Rector\MethodCall\InArgChainMethodCallToStandaloneMethodCallRector\Source\NonFluentClass;
|
||||
|
||||
class SkipNonFluentNewInArg
|
||||
{
|
||||
public function someFunction()
|
||||
{
|
||||
$this->processFluentClass((new NonFluentClass())->number());
|
||||
}
|
||||
|
||||
public function processFluentClass(int $number)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\MagicDisclosure\Tests\Rector\MethodCall\InArgChainMethodCallToStandaloneMethodCallRector\Source;
|
||||
|
||||
final class NonFluentClass
|
||||
{
|
||||
public function number()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function letter()
|
||||
{
|
||||
return 'Z';
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user