mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-17 13:28:18 +01:00
Updated Rector to commit 8281a06bc8432d9d7f8e20842e3961df99a277bc
8281a06bc8
[PHP 7.2] Add error suppres support to each() rule (#5844)
This commit is contained in:
parent
d5e203a6e9
commit
7141ae6e56
@ -3,13 +3,13 @@
|
||||
declare (strict_types=1);
|
||||
namespace Rector\DeadCode\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node\Expr\NullsafeMethodCall;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\CallLike;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\NullsafeMethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
|
@ -6,12 +6,11 @@ namespace Rector\Php72\Rector\Assign;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\List_;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeManipulator\AssignManipulator;
|
||||
use Rector\Php72\ValueObject\ListAndEach;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\ValueObject\PhpVersionFeature;
|
||||
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
|
||||
@ -65,58 +64,55 @@ CODE_SAMPLE
|
||||
if (!$node->expr instanceof Assign) {
|
||||
return null;
|
||||
}
|
||||
$assign = $node->expr;
|
||||
if ($this->shouldSkipAssign($assign)) {
|
||||
$listAndEach = $this->assignManipulator->matchListAndEach($node->expr);
|
||||
if (!$listAndEach instanceof ListAndEach) {
|
||||
return null;
|
||||
}
|
||||
/** @var List_ $listNode */
|
||||
$listNode = $assign->var;
|
||||
/** @var FuncCall $eachFuncCall */
|
||||
$eachFuncCall = $assign->expr;
|
||||
if ($this->shouldSkipAssign($listAndEach)) {
|
||||
return null;
|
||||
}
|
||||
$list = $listAndEach->getList();
|
||||
$eachFuncCall = $listAndEach->getEachFuncCall();
|
||||
// only key: list($key, ) = each($values);
|
||||
if ($listNode->items[0] instanceof ArrayItem && !$listNode->items[1] instanceof ArrayItem) {
|
||||
if ($list->items[0] instanceof ArrayItem && !$list->items[1] instanceof ArrayItem) {
|
||||
$keyFuncCall = $this->nodeFactory->createFuncCall('key', $eachFuncCall->args);
|
||||
$keyFuncCallAssign = new Assign($listNode->items[0]->value, $keyFuncCall);
|
||||
$keyFuncCallAssign = new Assign($list->items[0]->value, $keyFuncCall);
|
||||
return new Expression($keyFuncCallAssign);
|
||||
}
|
||||
// only value: list(, $value) = each($values);
|
||||
if ($listNode->items[1] instanceof ArrayItem && !$listNode->items[0] instanceof ArrayItem) {
|
||||
if ($list->items[1] instanceof ArrayItem && !$list->items[0] instanceof ArrayItem) {
|
||||
$nextFuncCall = $this->nodeFactory->createFuncCall('next', $eachFuncCall->args);
|
||||
$currentFuncCall = $this->nodeFactory->createFuncCall('current', $eachFuncCall->args);
|
||||
$secondArrayItem = $listNode->items[1];
|
||||
$secondArrayItem = $list->items[1];
|
||||
$currentAssign = new Assign($secondArrayItem->value, $currentFuncCall);
|
||||
return [new Expression($currentAssign), new Expression($nextFuncCall)];
|
||||
}
|
||||
// both: list($key, $value) = each($values);
|
||||
$currentFuncCall = $this->nodeFactory->createFuncCall('current', $eachFuncCall->args);
|
||||
$secondArrayItem = $listNode->items[1];
|
||||
$secondArrayItem = $list->items[1];
|
||||
if (!$secondArrayItem instanceof ArrayItem) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
$currentAssign = new Assign($secondArrayItem->value, $currentFuncCall);
|
||||
$nextFuncCall = $this->nodeFactory->createFuncCall('next', $eachFuncCall->args);
|
||||
$keyFuncCall = $this->nodeFactory->createFuncCall('key', $eachFuncCall->args);
|
||||
$firstArrayItem = $listNode->items[0];
|
||||
$firstArrayItem = $list->items[0];
|
||||
if (!$firstArrayItem instanceof ArrayItem) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
$keyAssign = new Assign($firstArrayItem->value, $keyFuncCall);
|
||||
return [new Expression($keyAssign), new Expression($currentAssign), new Expression($nextFuncCall)];
|
||||
}
|
||||
private function shouldSkipAssign(Assign $assign) : bool
|
||||
private function shouldSkipAssign(ListAndEach $listAndEach) : bool
|
||||
{
|
||||
if (!$this->assignManipulator->isListToEachAssign($assign)) {
|
||||
return \true;
|
||||
}
|
||||
/** @var List_ $listNode */
|
||||
$listNode = $assign->var;
|
||||
if (\count($listNode->items) !== 2) {
|
||||
$list = $listAndEach->getList();
|
||||
if (\count($list->items) !== 2) {
|
||||
return \true;
|
||||
}
|
||||
// empty list → cannot handle
|
||||
if ($listNode->items[0] instanceof ArrayItem) {
|
||||
if ($list->items[0] instanceof ArrayItem) {
|
||||
return \false;
|
||||
}
|
||||
return !$listNode->items[1] instanceof ArrayItem;
|
||||
return !$list->items[1] instanceof ArrayItem;
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,10 @@ namespace Rector\Php72\Rector\While_;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\List_;
|
||||
use PhpParser\Node\Stmt\Foreach_;
|
||||
use PhpParser\Node\Stmt\While_;
|
||||
use Rector\NodeManipulator\AssignManipulator;
|
||||
use Rector\Php72\ValueObject\ListAndEach;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\ValueObject\PhpVersionFeature;
|
||||
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
|
||||
@ -75,37 +74,31 @@ CODE_SAMPLE
|
||||
if (!$node->cond instanceof Assign) {
|
||||
return null;
|
||||
}
|
||||
/** @var Assign $assignNode */
|
||||
$assignNode = $node->cond;
|
||||
if (!$this->assignManipulator->isListToEachAssign($assignNode)) {
|
||||
$listAndEach = $this->assignManipulator->matchListAndEach($node->cond);
|
||||
if (!$listAndEach instanceof ListAndEach) {
|
||||
return null;
|
||||
}
|
||||
/** @var FuncCall $eachFuncCall */
|
||||
$eachFuncCall = $assignNode->expr;
|
||||
if ($eachFuncCall->isFirstClassCallable()) {
|
||||
return null;
|
||||
}
|
||||
/** @var List_ $listNode */
|
||||
$listNode = $assignNode->var;
|
||||
$eachFuncCall = $listAndEach->getEachFuncCall();
|
||||
$list = $listAndEach->getList();
|
||||
if (!isset($eachFuncCall->getArgs()[0])) {
|
||||
return null;
|
||||
}
|
||||
$firstArg = $eachFuncCall->getArgs()[0];
|
||||
$foreachedExpr = \count($listNode->items) === 1 ? $this->nodeFactory->createFuncCall('array_keys', [$firstArg]) : $firstArg->value;
|
||||
$arrayItem = \array_pop($listNode->items);
|
||||
$foreachedExpr = \count($list->items) === 1 ? $this->nodeFactory->createFuncCall('array_keys', [$firstArg]) : $firstArg->value;
|
||||
$arrayItem = \array_pop($list->items);
|
||||
$isTrailingCommaLast = \false;
|
||||
if (!$arrayItem instanceof ArrayItem) {
|
||||
$foreachedExpr = $this->nodeFactory->createFuncCall('array_keys', [$eachFuncCall->args[0]]);
|
||||
/** @var ArrayItem $arrayItem */
|
||||
$arrayItem = \current($listNode->items);
|
||||
$arrayItem = \current($list->items);
|
||||
$isTrailingCommaLast = \true;
|
||||
}
|
||||
$foreach = new Foreach_($foreachedExpr, $arrayItem, ['stmts' => $node->stmts]);
|
||||
$this->mirrorComments($foreach, $node);
|
||||
// is key included? add it to foreach
|
||||
if ($listNode->items !== []) {
|
||||
if ($list->items !== []) {
|
||||
/** @var ArrayItem|null $keyItem */
|
||||
$keyItem = \array_pop($listNode->items);
|
||||
$keyItem = \array_pop($list->items);
|
||||
if ($keyItem instanceof ArrayItem && !$isTrailingCommaLast) {
|
||||
$foreach->keyVar = $keyItem->value;
|
||||
}
|
||||
|
33
rules/Php72/ValueObject/ListAndEach.php
Normal file
33
rules/Php72/ValueObject/ListAndEach.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\Php72\ValueObject;
|
||||
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\List_;
|
||||
final class ListAndEach
|
||||
{
|
||||
/**
|
||||
* @readonly
|
||||
* @var \PhpParser\Node\Expr\List_
|
||||
*/
|
||||
private $list;
|
||||
/**
|
||||
* @readonly
|
||||
* @var \PhpParser\Node\Expr\FuncCall
|
||||
*/
|
||||
private $eachFuncCall;
|
||||
public function __construct(List_ $list, FuncCall $eachFuncCall)
|
||||
{
|
||||
$this->list = $list;
|
||||
$this->eachFuncCall = $eachFuncCall;
|
||||
}
|
||||
public function getList() : List_
|
||||
{
|
||||
return $this->list;
|
||||
}
|
||||
public function getEachFuncCall() : FuncCall
|
||||
{
|
||||
return $this->eachFuncCall;
|
||||
}
|
||||
}
|
@ -19,12 +19,12 @@ final class VersionResolver
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PACKAGE_VERSION = 'd5069f0fccf649646eeea05b5291c0ac34e511d6';
|
||||
public const PACKAGE_VERSION = '8281a06bc8432d9d7f8e20842e3961df99a277bc';
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const RELEASE_DATE = '2024-04-23 19:08:22';
|
||||
public const RELEASE_DATE = '2024-04-24 08:54:03';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\NodeManipulator;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\ErrorSuppress;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\List_;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
@ -13,6 +14,7 @@ use PhpParser\Node\FunctionLike;
|
||||
use Rector\NodeAnalyzer\PropertyFetchAnalyzer;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Php72\ValueObject\ListAndEach;
|
||||
use Rector\PhpParser\Node\BetterNodeFinder;
|
||||
final class AssignManipulator
|
||||
{
|
||||
@ -39,17 +41,31 @@ final class AssignManipulator
|
||||
}
|
||||
/**
|
||||
* Matches:
|
||||
* each() = [1, 2];
|
||||
* list([1, 2]) = each($items)
|
||||
*/
|
||||
public function isListToEachAssign(Assign $assign) : bool
|
||||
public function matchListAndEach(Assign $assign) : ?ListAndEach
|
||||
{
|
||||
if (!$assign->expr instanceof FuncCall) {
|
||||
return \false;
|
||||
// could be behind error suppress
|
||||
if ($assign->expr instanceof ErrorSuppress) {
|
||||
$errorSuppress = $assign->expr;
|
||||
$bareExpr = $errorSuppress->expr;
|
||||
} else {
|
||||
$bareExpr = $assign->expr;
|
||||
}
|
||||
if (!$bareExpr instanceof FuncCall) {
|
||||
return null;
|
||||
}
|
||||
if (!$assign->var instanceof List_) {
|
||||
return \false;
|
||||
return null;
|
||||
}
|
||||
return $this->nodeNameResolver->isName($assign->expr, 'each');
|
||||
if (!$this->nodeNameResolver->isName($bareExpr, 'each')) {
|
||||
return null;
|
||||
}
|
||||
// no placeholders
|
||||
if ($bareExpr->isFirstClassCallable()) {
|
||||
return null;
|
||||
}
|
||||
return new ListAndEach($assign->var, $bareExpr);
|
||||
}
|
||||
public function isLeftPartOfAssign(Node $node) : bool
|
||||
{
|
||||
|
1
vendor/composer/autoload_classmap.php
vendored
1
vendor/composer/autoload_classmap.php
vendored
@ -1841,6 +1841,7 @@ return array(
|
||||
'Rector\\Php72\\Rector\\FuncCall\\StringsAssertNakedRector' => $baseDir . '/rules/Php72/Rector/FuncCall/StringsAssertNakedRector.php',
|
||||
'Rector\\Php72\\Rector\\Unset_\\UnsetCastRector' => $baseDir . '/rules/Php72/Rector/Unset_/UnsetCastRector.php',
|
||||
'Rector\\Php72\\Rector\\While_\\WhileEachToForeachRector' => $baseDir . '/rules/Php72/Rector/While_/WhileEachToForeachRector.php',
|
||||
'Rector\\Php72\\ValueObject\\ListAndEach' => $baseDir . '/rules/Php72/ValueObject/ListAndEach.php',
|
||||
'Rector\\Php73\\Rector\\BooleanOr\\IsCountableRector' => $baseDir . '/rules/Php73/Rector/BooleanOr/IsCountableRector.php',
|
||||
'Rector\\Php73\\Rector\\ConstFetch\\SensitiveConstantNameRector' => $baseDir . '/rules/Php73/Rector/ConstFetch/SensitiveConstantNameRector.php',
|
||||
'Rector\\Php73\\Rector\\FuncCall\\ArrayKeyFirstLastRector' => $baseDir . '/rules/Php73/Rector/FuncCall/ArrayKeyFirstLastRector.php',
|
||||
|
1
vendor/composer/autoload_static.php
vendored
1
vendor/composer/autoload_static.php
vendored
@ -2060,6 +2060,7 @@ class ComposerStaticInit005507a96a37a412a8adf9cfaae1e621
|
||||
'Rector\\Php72\\Rector\\FuncCall\\StringsAssertNakedRector' => __DIR__ . '/../..' . '/rules/Php72/Rector/FuncCall/StringsAssertNakedRector.php',
|
||||
'Rector\\Php72\\Rector\\Unset_\\UnsetCastRector' => __DIR__ . '/../..' . '/rules/Php72/Rector/Unset_/UnsetCastRector.php',
|
||||
'Rector\\Php72\\Rector\\While_\\WhileEachToForeachRector' => __DIR__ . '/../..' . '/rules/Php72/Rector/While_/WhileEachToForeachRector.php',
|
||||
'Rector\\Php72\\ValueObject\\ListAndEach' => __DIR__ . '/../..' . '/rules/Php72/ValueObject/ListAndEach.php',
|
||||
'Rector\\Php73\\Rector\\BooleanOr\\IsCountableRector' => __DIR__ . '/../..' . '/rules/Php73/Rector/BooleanOr/IsCountableRector.php',
|
||||
'Rector\\Php73\\Rector\\ConstFetch\\SensitiveConstantNameRector' => __DIR__ . '/../..' . '/rules/Php73/Rector/ConstFetch/SensitiveConstantNameRector.php',
|
||||
'Rector\\Php73\\Rector\\FuncCall\\ArrayKeyFirstLastRector' => __DIR__ . '/../..' . '/rules/Php73/Rector/FuncCall/ArrayKeyFirstLastRector.php',
|
||||
|
8
vendor/composer/installed.json
vendored
8
vendor/composer/installed.json
vendored
@ -504,8 +504,8 @@
|
||||
},
|
||||
{
|
||||
"name": "illuminate\/container",
|
||||
"version": "v10.48.8",
|
||||
"version_normalized": "10.48.8.0",
|
||||
"version": "v10.48.9",
|
||||
"version_normalized": "10.48.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https:\/\/github.com\/illuminate\/container.git",
|
||||
@ -561,8 +561,8 @@
|
||||
},
|
||||
{
|
||||
"name": "illuminate\/contracts",
|
||||
"version": "v10.48.8",
|
||||
"version_normalized": "10.48.8.0",
|
||||
"version": "v10.48.9",
|
||||
"version_normalized": "10.48.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https:\/\/github.com\/illuminate\/contracts.git",
|
||||
|
2
vendor/composer/installed.php
vendored
2
vendor/composer/installed.php
vendored
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user