[Core] Refactor CallAnalyzer: Move isNewInstance() from FluentChainMethodCallNodeAnalyzer 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>
This commit is contained in:
Abdul Malik Ikhsan 2021-08-22 00:33:55 +07:00 committed by GitHub
parent ddd20e9e9b
commit a1395e5841
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 31 deletions

View File

@ -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;
}
}

View File

@ -6,8 +6,6 @@ namespace Rector\CodeQuality\Rector\ClassMethod;
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;
@ -21,6 +19,7 @@ use PHPStan\Type\UnionType;
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;
@ -50,7 +49,8 @@ final class DateTimeToDateTimeInterfaceRector extends AbstractRector implements
private PhpDocTypeChanger $phpDocTypeChanger,
private ParamAnalyzer $paramAnalyzer,
private ClassMethodReturnTypeManipulator $classMethodReturnTypeManipulator,
private ClassMethodParameterTypeManipulator $classMethodParameterTypeManipulator
private ClassMethodParameterTypeManipulator $classMethodParameterTypeManipulator,
private CallAnalyzer $callAnalyzer
) {
}
@ -201,9 +201,11 @@ CODE_SAMPLE
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;
}
}

View File

@ -6,8 +6,6 @@ namespace Rector\Defluent\NodeAnalyzer;
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;
@ -23,7 +21,6 @@ use PHPStan\Type\ThisType;
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;
@ -50,7 +47,6 @@ final class FluentChainMethodCallNodeAnalyzer
private NodeFinder $nodeFinder,
private AstResolver $astResolver,
private BetterNodeFinder $betterNodeFinder,
private NodeComparator $nodeComparator,
private ReturnTypeInferer $returnTypeInferer,
private CallAnalyzer $callAnalyzer
) {
@ -265,7 +261,7 @@ final class FluentChainMethodCallNodeAnalyzer
continue;
}
if (! $this->isNewInstance($expr)) {
if (! $this->callAnalyzer->isNewInstance($this->betterNodeFinder, $expr)) {
continue;
}
@ -274,23 +270,4 @@ final class FluentChainMethodCallNodeAnalyzer
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_;
});
}
}

View File

@ -4,13 +4,19 @@ declare(strict_types=1);
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
{
@ -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) {
@ -54,4 +65,26 @@ final class CallAnalyzer
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_;
});
}
}