From f7d28cee5d9da9a1577d212315f0bfcddfe3a28f Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 25 May 2023 09:21:23 +0000 Subject: [PATCH] Updated Rector to commit 794bc8b5484e3eafcc91f85d443f665565c4ad44 https://github.com/rectorphp/rector-src/commit/794bc8b5484e3eafcc91f85d443f665565c4ad44 Remove PARENT_NODE from ForeachItemsAssignToEmptyArrayToAssignRector (#3958) --- .../NodeFinder/ScopeAwareNodeFinder.php | 53 ----------- .../ValueObject/ControlStructure.php | 5 -- .../ReadWrite/NodeFinder/NodeUsageFinder.php | 28 +----- ...hItemsAssignToEmptyArrayToAssignRector.php | 88 ++++++++++++------- src/Application/VersionResolver.php | 4 +- src/Kernel/RectorKernel.php | 2 +- vendor/autoload.php | 2 +- vendor/composer/autoload_classmap.php | 1 - vendor/composer/autoload_real.php | 10 +-- vendor/composer/autoload_static.php | 9 +- 10 files changed, 70 insertions(+), 132 deletions(-) delete mode 100644 packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php diff --git a/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php b/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php deleted file mode 100644 index 25ae67853eb..00000000000 --- a/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php +++ /dev/null @@ -1,53 +0,0 @@ -betterNodeFinder = $betterNodeFinder; - } - /** - * @api - * Find node based on $callable or null, when the nesting scope is broken - * @param callable(Node $node): bool $callable - * @param array> $allowedTypes - */ - public function findParent(Node $node, callable $callable, array $allowedTypes) : ?Node - { - /** @var array> $parentNestingBreakTypes */ - $parentNestingBreakTypes = \array_diff(ControlStructure::BREAKING_SCOPE_NODE_TYPES, $allowedTypes); - $this->isBreakingNodeFoundFirst = \false; - $foundNode = $this->betterNodeFinder->findFirstPrevious($node, function (Node $node) use($callable, $parentNestingBreakTypes) : bool { - if ($callable($node)) { - return \true; - } - foreach ($parentNestingBreakTypes as $parentNestingBreakType) { - if (!$node instanceof $parentNestingBreakType) { - continue; - } - $this->isBreakingNodeFoundFirst = \true; - return \true; - } - return \false; - }); - if ($this->isBreakingNodeFoundFirst) { - return null; - } - return $foundNode; - } -} diff --git a/packages/NodeNestingScope/ValueObject/ControlStructure.php b/packages/NodeNestingScope/ValueObject/ControlStructure.php index ca9788b344d..15b7b8e44b6 100644 --- a/packages/NodeNestingScope/ValueObject/ControlStructure.php +++ b/packages/NodeNestingScope/ValueObject/ControlStructure.php @@ -5,7 +5,6 @@ namespace Rector\NodeNestingScope\ValueObject; use PhpParser\Node; use PhpParser\Node\Expr\Match_; -use PhpParser\Node\FunctionLike; use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Case_; use PhpParser\Node\Stmt\Catch_; @@ -19,10 +18,6 @@ use PhpParser\Node\Stmt\Switch_; use PhpParser\Node\Stmt\While_; final class ControlStructure { - /** - * @var array> - */ - public const BREAKING_SCOPE_NODE_TYPES = [For_::class, Foreach_::class, If_::class, While_::class, Do_::class, Else_::class, ElseIf_::class, Catch_::class, Case_::class, FunctionLike::class]; /** * These situations happens only if condition is met * @var array> diff --git a/packages/ReadWrite/NodeFinder/NodeUsageFinder.php b/packages/ReadWrite/NodeFinder/NodeUsageFinder.php index 806e74bd5e4..2c0c6617f1b 100644 --- a/packages/ReadWrite/NodeFinder/NodeUsageFinder.php +++ b/packages/ReadWrite/NodeFinder/NodeUsageFinder.php @@ -4,13 +4,9 @@ declare (strict_types=1); namespace Rector\ReadWrite\NodeFinder; use PhpParser\Node; -use PhpParser\Node\Expr; use PhpParser\Node\Expr\Variable; -use PhpParser\Node\Stmt\Foreach_; -use Rector\Core\PhpParser\Comparing\NodeComparator; use Rector\Core\PhpParser\Node\BetterNodeFinder; use Rector\NodeNameResolver\NodeNameResolver; -use Rector\NodeNestingScope\NodeFinder\ScopeAwareNodeFinder; use Rector\NodeTypeResolver\Node\AttributeKey; final class NodeUsageFinder { @@ -24,22 +20,10 @@ final class NodeUsageFinder * @var \Rector\Core\PhpParser\Node\BetterNodeFinder */ private $betterNodeFinder; - /** - * @readonly - * @var \Rector\NodeNestingScope\NodeFinder\ScopeAwareNodeFinder - */ - private $scopeAwareNodeFinder; - /** - * @readonly - * @var \Rector\Core\PhpParser\Comparing\NodeComparator - */ - private $nodeComparator; - public function __construct(NodeNameResolver $nodeNameResolver, BetterNodeFinder $betterNodeFinder, ScopeAwareNodeFinder $scopeAwareNodeFinder, NodeComparator $nodeComparator) + public function __construct(NodeNameResolver $nodeNameResolver, BetterNodeFinder $betterNodeFinder) { $this->nodeNameResolver = $nodeNameResolver; $this->betterNodeFinder = $betterNodeFinder; - $this->scopeAwareNodeFinder = $scopeAwareNodeFinder; - $this->nodeComparator = $nodeComparator; } /** * @param Node[] $nodes @@ -65,14 +49,4 @@ final class NodeUsageFinder return $assignedTo === null; }); } - public function findPreviousForeachNodeUsage(Foreach_ $foreach, Expr $expr) : ?Node - { - return $this->scopeAwareNodeFinder->findParent($foreach, function (Node $node) use($expr) : bool { - // skip itself - if ($node === $expr) { - return \false; - } - return $this->nodeComparator->areNodesEqual($node, $expr); - }, [Foreach_::class]); - } } diff --git a/rules/CodeQuality/Rector/Foreach_/ForeachItemsAssignToEmptyArrayToAssignRector.php b/rules/CodeQuality/Rector/Foreach_/ForeachItemsAssignToEmptyArrayToAssignRector.php index e6e4d76c208..1737c6f82b7 100644 --- a/rules/CodeQuality/Rector/Foreach_/ForeachItemsAssignToEmptyArrayToAssignRector.php +++ b/rules/CodeQuality/Rector/Foreach_/ForeachItemsAssignToEmptyArrayToAssignRector.php @@ -3,16 +3,18 @@ declare (strict_types=1); namespace Rector\CodeQuality\Rector\Foreach_; +use PhpParser\Node\Stmt; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Assign; +use PhpParser\Node\Expr\Variable; +use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\Foreach_; use PHPStan\Analyser\Scope; use Rector\CodeQuality\NodeAnalyzer\ForeachAnalyzer; +use Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface; use Rector\Core\Rector\AbstractScopeAwareRector; use Rector\NodeNestingScope\ValueObject\ControlStructure; -use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\ReadWrite\NodeFinder\NodeUsageFinder; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** @@ -20,19 +22,13 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; */ final class ForeachItemsAssignToEmptyArrayToAssignRector extends AbstractScopeAwareRector { - /** - * @readonly - * @var \Rector\ReadWrite\NodeFinder\NodeUsageFinder - */ - private $nodeUsageFinder; /** * @readonly * @var \Rector\CodeQuality\NodeAnalyzer\ForeachAnalyzer */ private $foreachAnalyzer; - public function __construct(NodeUsageFinder $nodeUsageFinder, ForeachAnalyzer $foreachAnalyzer) + public function __construct(ForeachAnalyzer $foreachAnalyzer) { - $this->nodeUsageFinder = $nodeUsageFinder; $this->foreachAnalyzer = $foreachAnalyzer; } public function getRuleDefinition() : RuleDefinition @@ -68,50 +64,78 @@ CODE_SAMPLE */ public function getNodeTypes() : array { - return [Foreach_::class]; + return [StmtsAwareInterface::class]; } /** - * @param Foreach_ $node + * @param StmtsAwareInterface $node */ public function refactorWithScope(Node $node, Scope $scope) : ?Node { - if ($this->shouldSkip($node, $scope)) { + if ($node->stmts === null) { return null; } - $assignVariable = $this->foreachAnalyzer->matchAssignItemsOnlyForeachArrayVariable($node); - if (!$assignVariable instanceof Expr) { - return null; + $emptyArrayVariables = []; + foreach ($node->stmts as $key => $stmt) { + $variableName = $this->matchEmptyArrayVariableAssign($stmt); + if (\is_string($variableName)) { + $emptyArrayVariables[] = $variableName; + } + if (!$stmt instanceof Foreach_) { + continue; + } + if ($this->shouldSkip($stmt, $emptyArrayVariables)) { + continue; + } + $assignVariable = $this->foreachAnalyzer->matchAssignItemsOnlyForeachArrayVariable($stmt); + if (!$assignVariable instanceof Expr) { + continue; + } + $directAssign = new Assign($assignVariable, $stmt->expr); + $node->stmts[$key] = new Expression($directAssign); + return $node; } - return new Assign($assignVariable, $node->expr); + return null; } - private function shouldSkip(Foreach_ $foreach, Scope $scope) : bool + /** + * @param string[] $emptyArrayVariables + */ + private function shouldSkip(Foreach_ $foreach, array $emptyArrayVariables) : bool { $assignVariable = $this->foreachAnalyzer->matchAssignItemsOnlyForeachArrayVariable($foreach); if (!$assignVariable instanceof Expr) { return \true; } + $foreachedExprType = $this->getType($foreach->expr); + // only arrays, not traversable/iterable + if (!$foreachedExprType->isArray()->yes()) { + return \true; + } if ($this->shouldSkipAsPartOfOtherLoop($foreach)) { return \true; } - $node = $this->nodeUsageFinder->findPreviousForeachNodeUsage($foreach, $assignVariable); - if (!$node instanceof Node) { - return \true; - } - $previousDeclarationParentNode = $node->getAttribute(AttributeKey::PARENT_NODE); - if (!$previousDeclarationParentNode instanceof Assign) { - return \true; - } - // must be empty array, otherwise it will false override - $defaultValue = $this->valueResolver->getValue($previousDeclarationParentNode->expr); - if ($defaultValue !== []) { - return \true; - } - $type = $scope->getType($foreach->expr); - return !$type->isArray()->yes(); + return !$this->isNames($assignVariable, $emptyArrayVariables); } private function shouldSkipAsPartOfOtherLoop(Foreach_ $foreach) : bool { $foreachParent = $this->betterNodeFinder->findParentByTypes($foreach, ControlStructure::LOOP_NODES); return $foreachParent instanceof Node; } + private function matchEmptyArrayVariableAssign(Stmt $stmt) : ?string + { + if (!$stmt instanceof Expression) { + return null; + } + if (!$stmt->expr instanceof Assign) { + return null; + } + $assign = $stmt->expr; + if (!$assign->var instanceof Variable) { + return null; + } + // must be assign of empty array + if (!$this->valueResolver->isValue($assign->expr, [])) { + return null; + } + return $this->getName($assign->var); + } } diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index e9c990eb99c..2b4efc2855e 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '179b5cba82257fd1d310301679a1913db458809e'; + public const PACKAGE_VERSION = '794bc8b5484e3eafcc91f85d443f665565c4ad44'; /** * @api * @var string */ - public const RELEASE_DATE = '2023-05-24 19:44:06'; + public const RELEASE_DATE = '2023-05-25 09:16:36'; /** * @var int */ diff --git a/src/Kernel/RectorKernel.php b/src/Kernel/RectorKernel.php index c1fc236ef9e..df60fb52599 100644 --- a/src/Kernel/RectorKernel.php +++ b/src/Kernel/RectorKernel.php @@ -15,7 +15,7 @@ final class RectorKernel /** * @var string */ - private const CACHE_KEY = 'v30'; + private const CACHE_KEY = 'v31'; /** * @var \Symfony\Component\DependencyInjection\ContainerInterface|null */ diff --git a/vendor/autoload.php b/vendor/autoload.php index 4bc6b8a076d..e1ec5e087f3 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) { require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInit1196db29f81134b3b253351d2128b6cb::getLoader(); +return ComposerAutoloaderInitcbaa9abc947ed42092c0b6aa69071d6d::getLoader(); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index a330c11cff7..31489f2929d 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -1947,7 +1947,6 @@ return array( 'Rector\\NodeNameResolver\\NodeNameResolver\\VariableNameResolver' => $baseDir . '/packages/NodeNameResolver/NodeNameResolver/VariableNameResolver.php', 'Rector\\NodeNameResolver\\Regex\\RegexPatternDetector' => $baseDir . '/packages/NodeNameResolver/Regex/RegexPatternDetector.php', 'Rector\\NodeNestingScope\\ContextAnalyzer' => $baseDir . '/packages/NodeNestingScope/ContextAnalyzer.php', - 'Rector\\NodeNestingScope\\NodeFinder\\ScopeAwareNodeFinder' => $baseDir . '/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php', 'Rector\\NodeNestingScope\\ParentScopeFinder' => $baseDir . '/packages/NodeNestingScope/ParentScopeFinder.php', 'Rector\\NodeNestingScope\\ScopeNestingComparator' => $baseDir . '/packages/NodeNestingScope/ScopeNestingComparator.php', 'Rector\\NodeNestingScope\\ValueObject\\ControlStructure' => $baseDir . '/packages/NodeNestingScope/ValueObject/ControlStructure.php', diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index b11bdc72492..5bf33767420 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit1196db29f81134b3b253351d2128b6cb +class ComposerAutoloaderInitcbaa9abc947ed42092c0b6aa69071d6d { private static $loader; @@ -22,17 +22,17 @@ class ComposerAutoloaderInit1196db29f81134b3b253351d2128b6cb return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit1196db29f81134b3b253351d2128b6cb', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInitcbaa9abc947ed42092c0b6aa69071d6d', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInit1196db29f81134b3b253351d2128b6cb', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInitcbaa9abc947ed42092c0b6aa69071d6d', 'loadClassLoader')); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInit1196db29f81134b3b253351d2128b6cb::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInitcbaa9abc947ed42092c0b6aa69071d6d::getInitializer($loader)); $loader->setClassMapAuthoritative(true); $loader->register(true); - $filesToLoad = \Composer\Autoload\ComposerStaticInit1196db29f81134b3b253351d2128b6cb::$files; + $filesToLoad = \Composer\Autoload\ComposerStaticInitcbaa9abc947ed42092c0b6aa69071d6d::$files; $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 45626a144ac..0601d46917f 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInit1196db29f81134b3b253351d2128b6cb +class ComposerStaticInitcbaa9abc947ed42092c0b6aa69071d6d { public static $files = array ( 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', @@ -2189,7 +2189,6 @@ class ComposerStaticInit1196db29f81134b3b253351d2128b6cb 'Rector\\NodeNameResolver\\NodeNameResolver\\VariableNameResolver' => __DIR__ . '/../..' . '/packages/NodeNameResolver/NodeNameResolver/VariableNameResolver.php', 'Rector\\NodeNameResolver\\Regex\\RegexPatternDetector' => __DIR__ . '/../..' . '/packages/NodeNameResolver/Regex/RegexPatternDetector.php', 'Rector\\NodeNestingScope\\ContextAnalyzer' => __DIR__ . '/../..' . '/packages/NodeNestingScope/ContextAnalyzer.php', - 'Rector\\NodeNestingScope\\NodeFinder\\ScopeAwareNodeFinder' => __DIR__ . '/../..' . '/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php', 'Rector\\NodeNestingScope\\ParentScopeFinder' => __DIR__ . '/../..' . '/packages/NodeNestingScope/ParentScopeFinder.php', 'Rector\\NodeNestingScope\\ScopeNestingComparator' => __DIR__ . '/../..' . '/packages/NodeNestingScope/ScopeNestingComparator.php', 'Rector\\NodeNestingScope\\ValueObject\\ControlStructure' => __DIR__ . '/../..' . '/packages/NodeNestingScope/ValueObject/ControlStructure.php', @@ -3097,9 +3096,9 @@ class ComposerStaticInit1196db29f81134b3b253351d2128b6cb public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInit1196db29f81134b3b253351d2128b6cb::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInit1196db29f81134b3b253351d2128b6cb::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInit1196db29f81134b3b253351d2128b6cb::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInitcbaa9abc947ed42092c0b6aa69071d6d::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitcbaa9abc947ed42092c0b6aa69071d6d::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInitcbaa9abc947ed42092c0b6aa69071d6d::$classMap; }, null, ClassLoader::class); }