Skip to content

Commit

Permalink
[Core] Refactor CallAnalyzer: Move isNewInstance() from FluentChainMe…
Browse files Browse the repository at this point in the history
…thodCallNodeAnalyzer to CallAnalyzer (#731)

* [Core] Refactor CallAnalyzer: Move isNewInstance() from FluentChainMethodCallNodeANalyzer to CallAnalyzer

* update test fixture for exatly return datetime

* more

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* Update rules/CodeQuality/Rector/ClassMethod/DateTimeToDateTimeInterfaceRector.php

Co-authored-by: Dominik Peters <kuhlesdominik@gmx.de>

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Dominik Peters <kuhlesdominik@gmx.de>
  • Loading branch information
3 people authored Aug 21, 2021
1 parent ddd20e9 commit a1395e5
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,24 @@ class SkipExactlyReturnDateTime
{
return new DateTime('now');
}

public static function run2(): DateTime
{
$obj = new DateTime('now');
return $obj;
}

public static function run3(): DateTime
{
$obj = new DateTime('now');
$obj2 = clone $obj;

return $obj2;
}

public static function run4(): DateTime
{
$obj = new DateTime('now');
return clone $obj;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
Expand All @@ -21,6 +19,7 @@
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\CodeQuality\NodeManipulator\ClassMethodParameterTypeManipulator;
use Rector\CodeQuality\NodeManipulator\ClassMethodReturnTypeManipulator;
use Rector\Core\NodeAnalyzer\CallAnalyzer;
use Rector\Core\NodeAnalyzer\ParamAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
Expand Down Expand Up @@ -50,7 +49,8 @@ public function __construct(
private PhpDocTypeChanger $phpDocTypeChanger,
private ParamAnalyzer $paramAnalyzer,
private ClassMethodReturnTypeManipulator $classMethodReturnTypeManipulator,
private ClassMethodParameterTypeManipulator $classMethodParameterTypeManipulator
private ClassMethodParameterTypeManipulator $classMethodParameterTypeManipulator,
private CallAnalyzer $callAnalyzer
) {
}

Expand Down Expand Up @@ -201,9 +201,11 @@ private function shouldSkipExactlyReturnDateTime(ClassMethod $classMethod): bool
return false;
}

return $return->expr instanceof New_ && $return->expr->class instanceof Name && $this->nodeNameResolver->isName(
$return->expr->class,
self::DATE_TIME
);
if (! $this->callAnalyzer->isNewInstance($this->betterNodeFinder, $return->expr)) {
return false;
}

$type = $this->nodeTypeResolver->resolve($return->expr);
return $type instanceof ObjectType && $type->getClassName() === self::DATE_TIME;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Clone_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
Expand All @@ -23,7 +21,6 @@
use PHPStan\Type\Type;
use Rector\Core\NodeAnalyzer\CallAnalyzer;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
Expand All @@ -50,7 +47,6 @@ public function __construct(
private NodeFinder $nodeFinder,
private AstResolver $astResolver,
private BetterNodeFinder $betterNodeFinder,
private NodeComparator $nodeComparator,
private ReturnTypeInferer $returnTypeInferer,
private CallAnalyzer $callAnalyzer
) {
Expand Down Expand Up @@ -265,7 +261,7 @@ private function isMethodCallCreatingNewInstance(MethodCall $methodCall): bool
continue;
}

if (! $this->isNewInstance($expr)) {
if (! $this->callAnalyzer->isNewInstance($this->betterNodeFinder, $expr)) {
continue;
}

Expand All @@ -274,23 +270,4 @@ private function isMethodCallCreatingNewInstance(MethodCall $methodCall): bool

return false;
}

private function isNewInstance(Expr $expr): bool
{
if ($expr instanceof Clone_ || $expr instanceof New_) {
return true;
}

return (bool) $this->betterNodeFinder->findFirstPreviousOfNode($expr, function (Node $node) use ($expr): bool {
if (! $node instanceof Assign) {
return false;
}

if (! $this->nodeComparator->areNodesEqual($node->var, $expr)) {
return false;
}

return $node->expr instanceof Clone_ || $node->expr instanceof New_;
});
}
}
33 changes: 33 additions & 0 deletions src/NodeAnalyzer/CallAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@

namespace Rector\Core\NodeAnalyzer;

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\BinaryOp;
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Expr\Clone_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\NullsafeMethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\If_;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;

final class CallAnalyzer
{
Expand All @@ -19,6 +25,11 @@ final class CallAnalyzer
*/
private const OBJECT_CALL_TYPES = [MethodCall::class, NullsafeMethodCall::class, StaticCall::class];

public function __construct(
private NodeComparator $nodeComparator
) {
}

public function isObjectCall(Expr $expr): bool
{
if ($expr instanceof BooleanNot) {
Expand Down Expand Up @@ -54,4 +65,26 @@ public function doesIfHasObjectCall(array $ifs): bool

return false;
}

/**
* Inject BetterNodeFinder due Circular reference
*/
public function isNewInstance(BetterNodeFinder $betterNodeFinder, Expr $expr): bool
{
if ($expr instanceof Clone_ || $expr instanceof New_) {
return true;
}

return (bool) $betterNodeFinder->findFirstPreviousOfNode($expr, function (Node $node) use ($expr): bool {
if (! $node instanceof Assign) {
return false;
}

if (! $this->nodeComparator->areNodesEqual($node->var, $expr)) {
return false;
}

return $node->expr instanceof Clone_ || $node->expr instanceof New_;
});
}
}

0 comments on commit a1395e5

Please sign in to comment.