mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-01 17:00:51 +00:00
Updated Rector to commit 6712529d24205b4b08e86f8da79876fb0d122c49
6712529d24
[PHP 8.0] Refactor ChangeSwitchToMatchRector to StmstAwareInterface (#2801)
This commit is contained in:
parent
237f7bb846
commit
8629ef2977
|
@ -8,13 +8,13 @@ use PhpParser\Node\Expr;
|
|||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\Match_;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PhpParser\Node\Stmt\Switch_;
|
||||
use PhpParser\Node\Stmt\Throw_;
|
||||
use Rector\Core\PhpParser\Comparing\NodeComparator;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Php80\Enum\MatchKind;
|
||||
use Rector\Php80\ValueObject\CondAndExpr;
|
||||
final class MatchSwitchAnalyzer
|
||||
|
@ -43,7 +43,7 @@ final class MatchSwitchAnalyzer
|
|||
/**
|
||||
* @param CondAndExpr[] $condAndExprs
|
||||
*/
|
||||
public function shouldSkipSwitch(Switch_ $switch, array $condAndExprs) : bool
|
||||
public function shouldSkipSwitch(Switch_ $switch, array $condAndExprs, ?Stmt $nextStmt) : bool
|
||||
{
|
||||
if ($condAndExprs === []) {
|
||||
return \true;
|
||||
|
@ -61,10 +61,10 @@ final class MatchSwitchAnalyzer
|
|||
return \false;
|
||||
}
|
||||
// is followed by return? is considered implicit default
|
||||
if ($this->isNextStmtReturnWithExpr($switch)) {
|
||||
if ($this->isNextStmtReturnWithExpr($switch, $nextStmt)) {
|
||||
return \false;
|
||||
}
|
||||
return !$this->isNextStmtThrows($switch);
|
||||
return !$nextStmt instanceof Throw_;
|
||||
}
|
||||
/**
|
||||
* @param CondAndExpr[] $condAndExprs
|
||||
|
@ -118,13 +118,12 @@ final class MatchSwitchAnalyzer
|
|||
}
|
||||
return \array_unique($condAndExprKinds);
|
||||
}
|
||||
private function isNextStmtReturnWithExpr(Switch_ $switch) : bool
|
||||
private function isNextStmtReturnWithExpr(Switch_ $switch, ?Stmt $nextStmt) : bool
|
||||
{
|
||||
$nextNode = $switch->getAttribute(AttributeKey::NEXT_NODE);
|
||||
if (!$nextNode instanceof Return_) {
|
||||
if (!$nextStmt instanceof Return_) {
|
||||
return \false;
|
||||
}
|
||||
if (!$nextNode->expr instanceof Expr) {
|
||||
if (!$nextStmt->expr instanceof Expr) {
|
||||
return \false;
|
||||
}
|
||||
foreach ($switch->cases as $case) {
|
||||
|
@ -136,16 +135,11 @@ final class MatchSwitchAnalyzer
|
|||
if (!$expression->expr instanceof Assign) {
|
||||
continue;
|
||||
}
|
||||
if (!$this->nodeComparator->areNodesEqual($expression->expr->var, $nextNode->expr)) {
|
||||
if (!$this->nodeComparator->areNodesEqual($expression->expr->var, $nextStmt->expr)) {
|
||||
return \false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return \true;
|
||||
}
|
||||
private function isNextStmtThrows(Switch_ $switch) : bool
|
||||
{
|
||||
$next = $switch->getAttribute(AttributeKey::NEXT_NODE);
|
||||
return $next instanceof Throw_;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ use PhpParser\Node\Stmt\Expression;
|
|||
use PhpParser\Node\Stmt\Return_;
|
||||
use PhpParser\Node\Stmt\Switch_;
|
||||
use PhpParser\Node\Stmt\Throw_ as ThrowsStmt;
|
||||
use Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\ValueObject\PhpVersionFeature;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
@ -83,67 +84,91 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function getNodeTypes() : array
|
||||
{
|
||||
// @todo refactor to stmts aware interface to move away from NEXT_NODE
|
||||
return [Switch_::class];
|
||||
return [StmtsAwareInterface::class];
|
||||
}
|
||||
/**
|
||||
* @param Switch_ $node
|
||||
* @param StmtsAwareInterface $node
|
||||
*/
|
||||
public function refactor(Node $node) : ?Node
|
||||
{
|
||||
$condAndExprs = $this->switchExprsResolver->resolve($node);
|
||||
if ($this->matchSwitchAnalyzer->shouldSkipSwitch($node, $condAndExprs)) {
|
||||
if (!\is_array($node->stmts)) {
|
||||
return null;
|
||||
}
|
||||
if (!$this->matchSwitchAnalyzer->haveCondAndExprsMatchPotential($condAndExprs)) {
|
||||
return null;
|
||||
}
|
||||
$isReturn = \false;
|
||||
foreach ($condAndExprs as $condAndExpr) {
|
||||
if ($condAndExpr->equalsMatchKind(MatchKind::RETURN)) {
|
||||
$isReturn = \true;
|
||||
break;
|
||||
}
|
||||
$expr = $condAndExpr->getExpr();
|
||||
if ($expr instanceof Throw_) {
|
||||
$hasChanged = \false;
|
||||
foreach ($node->stmts as $key => $stmt) {
|
||||
if (!$stmt instanceof Switch_) {
|
||||
continue;
|
||||
}
|
||||
if (!$expr instanceof Assign) {
|
||||
return null;
|
||||
$nextStmt = $node->stmts[$key + 1] ?? null;
|
||||
$condAndExprs = $this->switchExprsResolver->resolve($stmt);
|
||||
if ($this->matchSwitchAnalyzer->shouldSkipSwitch($stmt, $condAndExprs, $nextStmt)) {
|
||||
continue;
|
||||
}
|
||||
if (!$this->matchSwitchAnalyzer->haveCondAndExprsMatchPotential($condAndExprs)) {
|
||||
continue;
|
||||
}
|
||||
$isReturn = \false;
|
||||
foreach ($condAndExprs as $condAndExpr) {
|
||||
if ($condAndExpr->equalsMatchKind(MatchKind::RETURN)) {
|
||||
$isReturn = \true;
|
||||
break;
|
||||
}
|
||||
$expr = $condAndExpr->getExpr();
|
||||
if ($expr instanceof Throw_) {
|
||||
continue;
|
||||
}
|
||||
if (!$expr instanceof Assign) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
$match = $this->matchFactory->createFromCondAndExprs($stmt->cond, $condAndExprs);
|
||||
// implicit return default after switch
|
||||
$match = $this->processImplicitReturnAfterSwitch($match, $condAndExprs, $nextStmt);
|
||||
if (!$match instanceof Match_) {
|
||||
continue;
|
||||
}
|
||||
$match = $this->processImplicitThrowsAfterSwitch($stmt, $match, $condAndExprs, $nextStmt);
|
||||
$assignVar = $this->resolveAssignVar($condAndExprs);
|
||||
$hasDefaultValue = $this->matchSwitchAnalyzer->hasDefaultValue($match);
|
||||
if ($assignVar instanceof Expr) {
|
||||
$previousStmt = $node->stmts[$key - 1] ?? null;
|
||||
$assign = $this->changeToAssign($match, $assignVar, $hasDefaultValue, $previousStmt, $nextStmt);
|
||||
if (!$assign instanceof Assign) {
|
||||
continue;
|
||||
}
|
||||
$node->stmts[$key] = new Expression($assign);
|
||||
$hasChanged = \true;
|
||||
continue;
|
||||
}
|
||||
if (!$hasDefaultValue) {
|
||||
continue;
|
||||
}
|
||||
$node->stmts[$key] = $isReturn ? new Return_($match) : new Expression($match);
|
||||
$hasChanged = \true;
|
||||
}
|
||||
$match = $this->matchFactory->createFromCondAndExprs($node->cond, $condAndExprs);
|
||||
// implicit return default after switch
|
||||
$match = $this->processImplicitReturnAfterSwitch($node, $match, $condAndExprs);
|
||||
if (!$match instanceof Match_) {
|
||||
return null;
|
||||
if ($hasChanged) {
|
||||
return $node;
|
||||
}
|
||||
$match = $this->processImplicitThrowsAfterSwitch($node, $match, $condAndExprs);
|
||||
$assignVar = $this->resolveAssignVar($condAndExprs);
|
||||
$hasDefaultValue = $this->matchSwitchAnalyzer->hasDefaultValue($match);
|
||||
if ($assignVar instanceof Expr) {
|
||||
return $this->changeToAssign($node, $match, $assignVar, $hasDefaultValue);
|
||||
}
|
||||
if (!$hasDefaultValue) {
|
||||
return null;
|
||||
}
|
||||
return $isReturn ? new Return_($match) : $match;
|
||||
return null;
|
||||
}
|
||||
public function provideMinPhpVersion() : int
|
||||
{
|
||||
return PhpVersionFeature::MATCH_EXPRESSION;
|
||||
}
|
||||
private function changeToAssign(Switch_ $switch, Match_ $match, Expr $expr, bool $hasDefaultValue) : ?Assign
|
||||
private function changeToAssign(Match_ $match, Expr $expr, bool $hasDefaultValue, ?Stmt $previousStmt, ?Stmt $nextStmt) : ?Assign
|
||||
{
|
||||
/** @var Stmt|null $nextStmt */
|
||||
$nextStmt = $switch->getAttribute(AttributeKey::NEXT_NODE);
|
||||
// containts next this expr?
|
||||
if (!$hasDefaultValue && $this->isFollowedByReturnWithExprUsage($nextStmt, $expr)) {
|
||||
return null;
|
||||
}
|
||||
$prevInitializedAssign = $this->betterNodeFinder->findFirstInlinedPrevious($switch, function (Node $node) use($expr) : bool {
|
||||
return $node instanceof Assign && $this->nodeComparator->areNodesEqual($node->var, $expr);
|
||||
});
|
||||
// @todo extract?
|
||||
$prevInitializedAssign = null;
|
||||
if ($previousStmt instanceof Expression) {
|
||||
$previousExpr = $previousStmt->expr;
|
||||
if ($previousExpr instanceof Assign && $this->nodeComparator->areNodesEqual($previousExpr->var, $expr)) {
|
||||
$prevInitializedAssign = $previousExpr;
|
||||
}
|
||||
}
|
||||
$assign = new Assign($expr, $match);
|
||||
if (!$prevInitializedAssign instanceof Assign) {
|
||||
return $this->resolveCurrentAssign($hasDefaultValue, $assign);
|
||||
|
@ -154,11 +179,12 @@ CODE_SAMPLE
|
|||
return $assign;
|
||||
}
|
||||
} else {
|
||||
$match->arms[\count($match->arms)] = new MatchArm(null, $prevInitializedAssign->expr);
|
||||
$lastArmPosition = \count($match->arms);
|
||||
$match->arms[$lastArmPosition] = new MatchArm(null, $prevInitializedAssign->expr);
|
||||
}
|
||||
$parentAssign = $prevInitializedAssign->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parentAssign instanceof Expression) {
|
||||
$this->removeNode($parentAssign);
|
||||
$node = $prevInitializedAssign->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($node instanceof Expression) {
|
||||
$this->removeNode($node);
|
||||
}
|
||||
return $assign;
|
||||
}
|
||||
|
@ -183,9 +209,8 @@ CODE_SAMPLE
|
|||
/**
|
||||
* @param CondAndExpr[] $condAndExprs
|
||||
*/
|
||||
private function processImplicitReturnAfterSwitch(Switch_ $switch, Match_ $match, array $condAndExprs) : ?Match_
|
||||
private function processImplicitReturnAfterSwitch(Match_ $match, array $condAndExprs, ?Stmt $nextStmt) : ?Match_
|
||||
{
|
||||
$nextStmt = $switch->getAttribute(AttributeKey::NEXT_NODE);
|
||||
if (!$nextStmt instanceof Return_) {
|
||||
return $match;
|
||||
}
|
||||
|
@ -204,22 +229,21 @@ CODE_SAMPLE
|
|||
$this->removeNode($nextStmt);
|
||||
}
|
||||
$condAndExprs[] = new CondAndExpr([], $returnedExpr, MatchKind::RETURN);
|
||||
return $this->matchFactory->createFromCondAndExprs($switch->cond, $condAndExprs);
|
||||
return $this->matchFactory->createFromCondAndExprs($match->cond, $condAndExprs);
|
||||
}
|
||||
/**
|
||||
* @param CondAndExpr[] $condAndExprs
|
||||
*/
|
||||
private function processImplicitThrowsAfterSwitch(Switch_ $switch, Match_ $match, array $condAndExprs) : Match_
|
||||
private function processImplicitThrowsAfterSwitch(Switch_ $switch, Match_ $match, array $condAndExprs, ?Stmt $nextStmt) : Match_
|
||||
{
|
||||
$nextNode = $switch->getAttribute(AttributeKey::NEXT_NODE);
|
||||
if (!$nextNode instanceof ThrowsStmt) {
|
||||
if (!$nextStmt instanceof ThrowsStmt) {
|
||||
return $match;
|
||||
}
|
||||
if ($this->matchSwitchAnalyzer->hasDefaultValue($match)) {
|
||||
return $match;
|
||||
}
|
||||
$this->removeNode($nextNode);
|
||||
$throw = new Throw_($nextNode->expr);
|
||||
$this->removeNode($nextStmt);
|
||||
$throw = new Throw_($nextStmt->expr);
|
||||
$condAndExprs[] = new CondAndExpr([], $throw, MatchKind::RETURN);
|
||||
return $this->matchFactory->createFromCondAndExprs($switch->cond, $condAndExprs);
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@ final class VersionResolver
|
|||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PACKAGE_VERSION = '236b0ffe16821d82446dffd3603e5ccb8cba8621';
|
||||
public const PACKAGE_VERSION = '6712529d24205b4b08e86f8da79876fb0d122c49';
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const RELEASE_DATE = '2022-08-19 13:14:30';
|
||||
public const RELEASE_DATE = '2022-08-19 14:37:58';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
|
|
@ -265,25 +265,6 @@ final class BetterNodeFinder
|
|||
return $this->nodeComparator->areNodesEqual($node->var, $expr);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Only search in previous Node/Stmt
|
||||
* @api
|
||||
*
|
||||
* @param callable(Node $node): bool $filter
|
||||
*/
|
||||
public function findFirstInlinedPrevious(Node $node, callable $filter) : ?Node
|
||||
{
|
||||
$previousNode = $node->getAttribute(AttributeKey::PREVIOUS_NODE);
|
||||
if (!$previousNode instanceof Node) {
|
||||
return null;
|
||||
}
|
||||
$foundNode = $this->findFirst($previousNode, $filter);
|
||||
// we found what we need
|
||||
if ($foundNode instanceof Node) {
|
||||
return $foundNode;
|
||||
}
|
||||
return $this->findFirstInlinedPrevious($previousNode, $filter);
|
||||
}
|
||||
/**
|
||||
* Search in previous Node/Stmt, when no Node found, lookup previous Stmt of Parent Node
|
||||
*
|
||||
|
@ -468,6 +449,25 @@ final class BetterNodeFinder
|
|||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Only search in previous Node/Stmt
|
||||
* @api
|
||||
*
|
||||
* @param callable(Node $node): bool $filter
|
||||
*/
|
||||
private function findFirstInlinedPrevious(Node $node, callable $filter) : ?Node
|
||||
{
|
||||
$previousNode = $node->getAttribute(AttributeKey::PREVIOUS_NODE);
|
||||
if (!$previousNode instanceof Node) {
|
||||
return null;
|
||||
}
|
||||
$foundNode = $this->findFirst($previousNode, $filter);
|
||||
// we found what we need
|
||||
if ($foundNode instanceof Node) {
|
||||
return $foundNode;
|
||||
}
|
||||
return $this->findFirstInlinedPrevious($previousNode, $filter);
|
||||
}
|
||||
/**
|
||||
* @template T of Node
|
||||
* @param \PhpParser\Node|mixed[] $nodes
|
||||
|
|
2
vendor/autoload.php
vendored
2
vendor/autoload.php
vendored
|
@ -9,4 +9,4 @@ if (PHP_VERSION_ID < 50600) {
|
|||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit85e0a1cc036e2557594b72be869a863f::getLoader();
|
||||
return ComposerAutoloaderInitae68ab1a4f19e6758219b7e98a29a94f::getLoader();
|
||||
|
|
14
vendor/composer/autoload_real.php
vendored
14
vendor/composer/autoload_real.php
vendored
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit85e0a1cc036e2557594b72be869a863f
|
||||
class ComposerAutoloaderInitae68ab1a4f19e6758219b7e98a29a94f
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
|
@ -22,19 +22,19 @@ class ComposerAutoloaderInit85e0a1cc036e2557594b72be869a863f
|
|||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit85e0a1cc036e2557594b72be869a863f', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInitae68ab1a4f19e6758219b7e98a29a94f', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit85e0a1cc036e2557594b72be869a863f', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitae68ab1a4f19e6758219b7e98a29a94f', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit85e0a1cc036e2557594b72be869a863f::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitae68ab1a4f19e6758219b7e98a29a94f::getInitializer($loader));
|
||||
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
$loader->register(true);
|
||||
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInit85e0a1cc036e2557594b72be869a863f::$files;
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInitae68ab1a4f19e6758219b7e98a29a94f::$files;
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire85e0a1cc036e2557594b72be869a863f($fileIdentifier, $file);
|
||||
composerRequireae68ab1a4f19e6758219b7e98a29a94f($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
|
@ -46,7 +46,7 @@ class ComposerAutoloaderInit85e0a1cc036e2557594b72be869a863f
|
|||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
function composerRequire85e0a1cc036e2557594b72be869a863f($fileIdentifier, $file)
|
||||
function composerRequireae68ab1a4f19e6758219b7e98a29a94f($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
|
8
vendor/composer/autoload_static.php
vendored
8
vendor/composer/autoload_static.php
vendored
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit85e0a1cc036e2557594b72be869a863f
|
||||
class ComposerStaticInitae68ab1a4f19e6758219b7e98a29a94f
|
||||
{
|
||||
public static $files = array (
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
|
@ -3253,9 +3253,9 @@ class ComposerStaticInit85e0a1cc036e2557594b72be869a863f
|
|||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit85e0a1cc036e2557594b72be869a863f::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit85e0a1cc036e2557594b72be869a863f::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit85e0a1cc036e2557594b72be869a863f::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitae68ab1a4f19e6758219b7e98a29a94f::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitae68ab1a4f19e6758219b7e98a29a94f::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInitae68ab1a4f19e6758219b7e98a29a94f::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user