Updated Rector to commit 26a368c89ba8297d33600aa5a1c954d2a1b5d274

26a368c89b Fix ReturnBinaryOrToEarlyReturnRector mixing up returned nodes of array, hook into StmtsAwareInterface instead to keep next Rector rules updated (#4476)
This commit is contained in:
Tomas Votruba 2023-07-11 15:35:53 +00:00
parent a552423177
commit 2e39614116
13 changed files with 94 additions and 64 deletions

View File

@ -109,21 +109,24 @@ CODE_SAMPLE
private function createMultipleIfs(Expr $expr, Continue_ $continue, array $ifs) : array
{
while ($expr instanceof BooleanOr) {
$ifs = \array_merge($ifs, $this->collectLeftbooleanOrToIfs($expr, $continue, $ifs));
$ifs[] = $this->ifManipulator->createIfStmt($expr->right, $continue);
$ifs = \array_merge($ifs, $this->collectLeftBooleanOrToIfs($expr, $continue, $ifs));
$ifs[] = new If_($expr->right, ['stmts' => [$continue]]);
$expr = $expr->right;
}
return $ifs + [$this->ifManipulator->createIfStmt($expr, $continue)];
$lastContinueIf = new If_($expr, ['stmts' => [$continue]]);
// the + is on purpose here, to keep only single continue as last
return $ifs + [$lastContinueIf];
}
/**
* @param If_[] $ifs
* @return If_[]
*/
private function collectLeftbooleanOrToIfs(BooleanOr $booleanOr, Continue_ $continue, array $ifs) : array
private function collectLeftBooleanOrToIfs(BooleanOr $booleanOr, Continue_ $continue, array $ifs) : array
{
$left = $booleanOr->left;
if (!$left instanceof BooleanOr) {
return [$this->ifManipulator->createIfStmt($left, $continue)];
$if = new If_($left, ['stmts' => [$continue]]);
return [$if];
}
return $this->createMultipleIfs($left, $continue, $ifs);
}

View File

@ -12,13 +12,14 @@ use PHPStan\Analyser\Scope;
use Rector\Core\NodeAnalyzer\CallAnalyzer;
use Rector\Core\NodeManipulator\IfManipulator;
use Rector\Core\PhpParser\Node\AssignAndBinaryMap;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\EarlyReturn\Rector\Return_\ReturnBinaryAndToEarlyReturnRector\ReturnBinaryAndToEarlyReturnRectorTest
*/
final class ReturnBinaryAndToEarlyReturnRector extends AbstractScopeAwareRector
final class ReturnBinaryAndToEarlyReturnRector extends AbstractRector
{
/**
* @readonly
@ -78,7 +79,7 @@ CODE_SAMPLE
* @param Return_ $node
* @return null|Node[]
*/
public function refactorWithScope(Node $node, Scope $scope) : ?array
public function refactor(Node $node) : ?array
{
if (!$node->expr instanceof BooleanAnd) {
return null;
@ -95,7 +96,7 @@ CODE_SAMPLE
$this->mirrorComments($ifNegations[0], $node);
/** @var BooleanAnd $booleanAnd */
$booleanAnd = $node->expr;
$lastReturnExpr = $this->assignAndBinaryMap->getTruthyExpr($booleanAnd->right, $scope);
$lastReturnExpr = $this->assignAndBinaryMap->getTruthyExpr($booleanAnd->right);
return \array_merge($ifNegations, [new Return_($lastReturnExpr)]);
}
/**

View File

@ -9,23 +9,17 @@ use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
use PhpParser\Node\Expr\BinaryOp\BooleanOr;
use PhpParser\Node\Stmt\If_;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Analyser\Scope;
use Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface;
use Rector\Core\NodeAnalyzer\CallAnalyzer;
use Rector\Core\NodeManipulator\IfManipulator;
use Rector\Core\PhpParser\Node\AssignAndBinaryMap;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\EarlyReturn\Rector\Return_\ReturnBinaryOrToEarlyReturnRector\ReturnBinaryOrToEarlyReturnRectorTest
*/
final class ReturnBinaryOrToEarlyReturnRector extends AbstractScopeAwareRector
final class ReturnBinaryOrToEarlyReturnRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\Core\NodeManipulator\IfManipulator
*/
private $ifManipulator;
/**
* @readonly
* @var \Rector\Core\PhpParser\Node\AssignAndBinaryMap
@ -36,9 +30,8 @@ final class ReturnBinaryOrToEarlyReturnRector extends AbstractScopeAwareRector
* @var \Rector\Core\NodeAnalyzer\CallAnalyzer
*/
private $callAnalyzer;
public function __construct(IfManipulator $ifManipulator, AssignAndBinaryMap $assignAndBinaryMap, CallAnalyzer $callAnalyzer)
public function __construct(AssignAndBinaryMap $assignAndBinaryMap, CallAnalyzer $callAnalyzer)
{
$this->ifManipulator = $ifManipulator;
$this->assignAndBinaryMap = $assignAndBinaryMap;
$this->callAnalyzer = $callAnalyzer;
}
@ -72,31 +65,45 @@ CODE_SAMPLE
*/
public function getNodeTypes() : array
{
return [Return_::class];
return [StmtsAwareInterface::class];
}
/**
* @param Return_ $node
* @return null|Node[]
* @param StmtsAwareInterface $node
*/
public function refactorWithScope(Node $node, Scope $scope) : ?array
public function refactor(Node $node) : ?Node
{
if (!$node->expr instanceof BooleanOr) {
if ($node->stmts === null) {
return null;
}
/** @var BooleanOr $booleanOr */
$booleanOr = $node->expr;
$left = $booleanOr->left;
$ifs = $this->createMultipleIfs($left, $node, []);
// ensure ifs not removed by other rules
if ($ifs === []) {
return null;
$hasChanged = \false;
foreach ($node->stmts as $key => $stmt) {
if (!$stmt instanceof Return_) {
continue;
}
if (!$stmt->expr instanceof BooleanOr) {
continue;
}
/** @var BooleanOr $booleanOr */
$booleanOr = $stmt->expr;
$left = $booleanOr->left;
$ifs = $this->createMultipleIfs($left, $stmt, []);
// ensure ifs not removed by other rules
if ($ifs === []) {
continue;
}
if (!$this->callAnalyzer->doesIfHasObjectCall($ifs)) {
continue;
}
$this->mirrorComments($ifs[0], $stmt);
$lastReturnExpr = $this->assignAndBinaryMap->getTruthyExpr($booleanOr->right);
$ifsWithLastIf = \array_merge($ifs, [new Return_($lastReturnExpr)]);
\array_splice($node->stmts, $key, 1, $ifsWithLastIf);
$hasChanged = \true;
}
if (!$this->callAnalyzer->doesIfHasObjectCall($ifs)) {
return null;
if ($hasChanged) {
return $node;
}
$this->mirrorComments($ifs[0], $node);
$lastReturnExpr = $this->assignAndBinaryMap->getTruthyExpr($booleanOr->right, $scope);
return \array_merge($ifs, [new Return_($lastReturnExpr)]);
return null;
}
/**
* @param If_[] $ifs
@ -106,7 +113,7 @@ CODE_SAMPLE
{
while ($expr instanceof BooleanOr) {
$ifs = \array_merge($ifs, $this->collectLeftBooleanOrToIfs($expr, $return, $ifs));
$ifs[] = $this->ifManipulator->createIfStmt($expr->right, new Return_($this->nodeFactory->createTrue()));
$ifs[] = new If_($expr->right, ['stmts' => [new Return_($this->nodeFactory->createTrue())]]);
$expr = $expr->right;
if ($expr instanceof BooleanAnd) {
return [];
@ -116,7 +123,12 @@ CODE_SAMPLE
}
return [];
}
return $ifs + [$this->ifManipulator->createIfStmt($expr, new Return_($this->nodeFactory->createTrue()))];
$lastIf = new If_($expr, ['stmts' => [new Return_($this->nodeFactory->createTrue())]]);
// if empty, fallback to last if
if ($ifs === []) {
return [$lastIf];
}
return $ifs;
}
/**
* @param If_[] $ifs
@ -126,7 +138,8 @@ CODE_SAMPLE
{
$left = $booleanOr->left;
if (!$left instanceof BooleanOr) {
return [$this->ifManipulator->createIfStmt($left, new Return_($this->nodeFactory->createTrue()))];
$returnTrueIf = new If_($left, ['stmts' => [new Return_($this->nodeFactory->createTrue())]]);
return [$returnTrueIf];
}
return $this->createMultipleIfs($left, $return, $ifs);
}

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = 'aac0f2a90922bcfe90a1918448dc6e80172beb62';
public const PACKAGE_VERSION = '26a368c89ba8297d33600aa5a1c954d2a1b5d274';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2023-07-11 06:13:44';
public const RELEASE_DATE = '2023-07-11 15:31:49';
/**
* @var int
*/

View File

@ -178,8 +178,11 @@ final class IfManipulator
public function createIfNegation(Expr $expr, Return_ $return) : If_
{
$expr = $this->conditionInverter->createInvertedCondition($expr);
return $this->createIfStmt($expr, $return);
return new If_($expr, ['stmts' => [$return]]);
}
/**
* @deprecated Create If_ directly, this is simple new with no added value
*/
public function createIfStmt(Expr $condExpr, Stmt $stmt) : If_
{
return new If_($condExpr, ['stmts' => [$stmt]]);

View File

@ -41,9 +41,14 @@ use PhpParser\Node\Expr\BinaryOp\Smaller;
use PhpParser\Node\Expr\BinaryOp\SmallerOrEqual;
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Expr\Cast\Bool_;
use PHPStan\Analyser\Scope;
use Rector\NodeTypeResolver\NodeTypeResolver;
final class AssignAndBinaryMap
{
/**
* @readonly
* @var \Rector\NodeTypeResolver\NodeTypeResolver
*/
private $nodeTypeResolver;
/**
* @var array<class-string<BinaryOp>, class-string<BinaryOp>>
*/
@ -56,8 +61,9 @@ final class AssignAndBinaryMap
* @var array<class-string<BinaryOp>, class-string<BinaryOp>>
*/
private $binaryOpToAssignClasses = [];
public function __construct()
public function __construct(NodeTypeResolver $nodeTypeResolver)
{
$this->nodeTypeResolver = $nodeTypeResolver;
$this->binaryOpToAssignClasses = \array_flip(self::ASSIGN_OP_TO_BINARY_OP_CLASSES);
}
/**
@ -82,7 +88,7 @@ final class AssignAndBinaryMap
$nodeClass = \get_class($binaryOp);
return self::BINARY_OP_TO_INVERSE_CLASSES[$nodeClass] ?? null;
}
public function getTruthyExpr(Expr $expr, Scope $scope) : Expr
public function getTruthyExpr(Expr $expr) : Expr
{
if ($expr instanceof Bool_) {
return $expr;
@ -90,8 +96,9 @@ final class AssignAndBinaryMap
if ($expr instanceof BooleanNot) {
return $expr;
}
$type = $scope->getType($expr);
if ($type->isBoolean()->yes()) {
$exprType = $this->nodeTypeResolver->getType($expr);
// $type = $scope->getType($expr);
if ($exprType->isBoolean()->yes()) {
return $expr;
}
return new Bool_($expr);

View File

@ -46,6 +46,10 @@ final class RectifiedAnalyzer
if ($node->hasAttribute(AttributeKey::ORIGINAL_NODE)) {
return \false;
}
// if (! $node instanceof Stmt) {
// $createdByRule = $node->getAttribute(AttributeKey::CREATED_BY_RULE) ?? [];
// return $createdByRule === [];
// }
/**
* Start token pos must be < 0 to continue, as the node and parent node just re-printed
*

View File

@ -237,7 +237,6 @@ CODE_SAMPLE;
return NodeTraverser::REMOVE_NODE;
}
$objectHash = \spl_object_hash($node);
// update parents relations!!!
return $this->nodesToReturn[$objectHash] ?? $node;
}
protected function isName(Node $node, string $name) : bool
@ -317,8 +316,8 @@ CODE_SAMPLE;
$firstNode = \current($refactoredNode);
$this->mirrorComments($firstNode, $originalNode);
$this->refreshScopeNodes($refactoredNode, $filePath, $currentScope);
$this->nodesToReturn[$originalNodeHash] = $refactoredNode;
// will be replaced in leaveNode() the original node must be passed
$this->nodesToReturn[$originalNodeHash] = $refactoredNode;
return $originalNode;
}
$this->refreshScopeNodes($refactoredNode, $filePath, $currentScope);

2
vendor/autoload.php vendored
View File

@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInite8a80413f9ef624f25c8b8a017a5836f::getLoader();
return ComposerAutoloaderInit5ceed2a2267cc3c890477c5705171035::getLoader();

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInite8a80413f9ef624f25c8b8a017a5836f
class ComposerAutoloaderInit5ceed2a2267cc3c890477c5705171035
{
private static $loader;
@ -22,17 +22,17 @@ class ComposerAutoloaderInite8a80413f9ef624f25c8b8a017a5836f
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInite8a80413f9ef624f25c8b8a017a5836f', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit5ceed2a2267cc3c890477c5705171035', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInite8a80413f9ef624f25c8b8a017a5836f', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit5ceed2a2267cc3c890477c5705171035', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInite8a80413f9ef624f25c8b8a017a5836f::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit5ceed2a2267cc3c890477c5705171035::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInite8a80413f9ef624f25c8b8a017a5836f::$files;
$filesToLoad = \Composer\Autoload\ComposerStaticInit5ceed2a2267cc3c890477c5705171035::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInite8a80413f9ef624f25c8b8a017a5836f
class ComposerStaticInit5ceed2a2267cc3c890477c5705171035
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -3067,9 +3067,9 @@ class ComposerStaticInite8a80413f9ef624f25c8b8a017a5836f
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInite8a80413f9ef624f25c8b8a017a5836f::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInite8a80413f9ef624f25c8b8a017a5836f::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInite8a80413f9ef624f25c8b8a017a5836f::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit5ceed2a2267cc3c890477c5705171035::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit5ceed2a2267cc3c890477c5705171035::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit5ceed2a2267cc3c890477c5705171035::$classMap;
}, null, ClassLoader::class);
}

View File

@ -504,8 +504,8 @@
},
{
"name": "illuminate\/container",
"version": "v10.14.1",
"version_normalized": "10.14.1.0",
"version": "v10.15.0",
"version_normalized": "10.15.0.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/illuminate\/container.git",
@ -558,8 +558,8 @@
},
{
"name": "illuminate\/contracts",
"version": "v10.14.1",
"version_normalized": "10.14.1.0",
"version": "v10.15.0",
"version_normalized": "10.15.0.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/illuminate\/contracts.git",

File diff suppressed because one or more lines are too long