diff --git a/rules/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector.php b/rules/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector.php index 013a302c0ab..1bc75d5f37c 100644 --- a/rules/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector.php +++ b/rules/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector.php @@ -4,6 +4,7 @@ declare (strict_types=1); namespace Rector\DeadCode\Rector\Stmt; use PhpParser\Node; +use PhpParser\Node\Expr\Exit_; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\FunctionLike; @@ -13,7 +14,10 @@ use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\Foreach_; use PhpParser\Node\Stmt\If_; use PhpParser\Node\Stmt\Nop; +use PhpParser\Node\Stmt\Return_; +use PhpParser\Node\Stmt\Throw_; use Rector\Core\Rector\AbstractRector; +use Rector\DeadCode\SideEffect\SideEffectNodeDetector; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -24,6 +28,15 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; */ final class RemoveUnreachableStatementRector extends \Rector\Core\Rector\AbstractRector { + /** + * @readonly + * @var \Rector\DeadCode\SideEffect\SideEffectNodeDetector + */ + private $sideEffectNodeDetector; + public function __construct(\Rector\DeadCode\SideEffect\SideEffectNodeDetector $sideEffectNodeDetector) + { + $this->sideEffectNodeDetector = $sideEffectNodeDetector; + } public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition { return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Remove unreachable statements', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE' @@ -62,7 +75,7 @@ CODE_SAMPLE { $stmts = $node->stmts; $isPassedTheUnreachable = \false; - $hasChanged = \false; + $toBeRemovedKeys = []; foreach ($stmts as $key => $stmt) { if ($this->shouldSkipNode($stmt)) { continue; @@ -77,13 +90,51 @@ CODE_SAMPLE if (!$isPassedTheUnreachable) { continue; } - unset($stmts[$key]); - $hasChanged = \true; + $toBeRemovedKeys[] = $key; } - if (!$hasChanged) { + if ($toBeRemovedKeys === []) { return null; } - $node->stmts = $stmts; + $start = \reset($toBeRemovedKeys); + if (!isset($stmts[$start - 1])) { + return null; + } + $previousFirstUnreachable = $stmts[$start - 1]; + if (\in_array(\get_class($previousFirstUnreachable), [\PhpParser\Node\Stmt\Throw_::class, \PhpParser\Node\Stmt\Return_::class, \PhpParser\Node\Expr\Exit_::class], \true)) { + return $this->processCleanUpUnreachabelStmts($node, $toBeRemovedKeys); + } + // check previous side effect can check against start jump key - 2 + // as previously already checked as reachable part + if (!$this->hasPreviousSideEffect($start - 2, $stmts)) { + return $this->processCleanUpUnreachabelStmts($node, $toBeRemovedKeys); + } + return null; + } + /** + * @param Stmt[] $stmts + */ + private function hasPreviousSideEffect(int $start, array $stmts) : bool + { + for ($key = $start; $key > 0; --$key) { + $previousStmt = $stmts[$key]; + $hasSideEffect = (bool) $this->betterNodeFinder->findFirst($previousStmt, function (\PhpParser\Node $node) : bool { + return $this->sideEffectNodeDetector->detectCallExpr($node); + }); + if ($hasSideEffect) { + return \true; + } + } + return \false; + } + /** + * @param int[] $toBeRemovedKeys + * @param \PhpParser\Node\FunctionLike|\PhpParser\Node\Stmt\Else_|\PhpParser\Node\Stmt\Foreach_|\PhpParser\Node\Stmt\If_ $node + */ + private function processCleanUpUnreachabelStmts($node, array $toBeRemovedKeys) : \PhpParser\Node + { + foreach ($toBeRemovedKeys as $toBeRemovedKey) { + unset($node->stmts[$toBeRemovedKey]); + } return $node; } private function shouldSkipNode(\PhpParser\Node\Stmt $stmt) : bool diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 09b6f4e9ca1..9a1e005f2ca 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -16,11 +16,11 @@ final class VersionResolver /** * @var string */ - public const PACKAGE_VERSION = 'b192ec7ca89cc9c0e4813e4823d49fe595d3a6a7'; + public const PACKAGE_VERSION = 'e5c94a20cf618a23b882329860a441a0d3eb4040'; /** * @var string */ - public const RELEASE_DATE = '2022-04-22 17:50:53'; + public const RELEASE_DATE = '2022-04-23 01:00:40'; /** * @var string */ diff --git a/vendor/autoload.php b/vendor/autoload.php index c32e57361dd..5cc95e1b309 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -9,4 +9,4 @@ if (PHP_VERSION_ID < 50600) { require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad::getLoader(); +return ComposerAutoloaderInitd747d28daa648bb0f7946d1a979db2ca::getLoader(); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index a84ac9e8ab5..2b091a74a81 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad +class ComposerAutoloaderInitd747d28daa648bb0f7946d1a979db2ca { private static $loader; @@ -22,19 +22,19 @@ class ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInitd747d28daa648bb0f7946d1a979db2ca', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInitd747d28daa648bb0f7946d1a979db2ca', 'loadClassLoader')); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInit1b81052b37c79e6194fc9b2f8f4d91ad::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInitd747d28daa648bb0f7946d1a979db2ca::getInitializer($loader)); $loader->setClassMapAuthoritative(true); $loader->register(true); - $includeFiles = \Composer\Autoload\ComposerStaticInit1b81052b37c79e6194fc9b2f8f4d91ad::$files; + $includeFiles = \Composer\Autoload\ComposerStaticInitd747d28daa648bb0f7946d1a979db2ca::$files; foreach ($includeFiles as $fileIdentifier => $file) { - composerRequire1b81052b37c79e6194fc9b2f8f4d91ad($fileIdentifier, $file); + composerRequired747d28daa648bb0f7946d1a979db2ca($fileIdentifier, $file); } return $loader; @@ -46,7 +46,7 @@ class ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad * @param string $file * @return void */ -function composerRequire1b81052b37c79e6194fc9b2f8f4d91ad($fileIdentifier, $file) +function composerRequired747d28daa648bb0f7946d1a979db2ca($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 c9d28c5a191..ff20049dbc4 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInit1b81052b37c79e6194fc9b2f8f4d91ad +class ComposerStaticInitd747d28daa648bb0f7946d1a979db2ca { public static $files = array ( '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', @@ -3869,9 +3869,9 @@ class ComposerStaticInit1b81052b37c79e6194fc9b2f8f4d91ad public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInit1b81052b37c79e6194fc9b2f8f4d91ad::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInit1b81052b37c79e6194fc9b2f8f4d91ad::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInit1b81052b37c79e6194fc9b2f8f4d91ad::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInitd747d28daa648bb0f7946d1a979db2ca::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitd747d28daa648bb0f7946d1a979db2ca::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInitd747d28daa648bb0f7946d1a979db2ca::$classMap; }, null, ClassLoader::class); } diff --git a/vendor/scoper-autoload.php b/vendor/scoper-autoload.php index 0de16c34194..423efd71c8b 100644 --- a/vendor/scoper-autoload.php +++ b/vendor/scoper-autoload.php @@ -9,8 +9,8 @@ $loader = require_once __DIR__.'/autoload.php'; if (!class_exists('AutoloadIncluder', false) && !interface_exists('AutoloadIncluder', false) && !trait_exists('AutoloadIncluder', false)) { spl_autoload_call('RectorPrefix20220422\AutoloadIncluder'); } -if (!class_exists('ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad', false) && !interface_exists('ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad', false) && !trait_exists('ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad', false)) { - spl_autoload_call('RectorPrefix20220422\ComposerAutoloaderInit1b81052b37c79e6194fc9b2f8f4d91ad'); +if (!class_exists('ComposerAutoloaderInitd747d28daa648bb0f7946d1a979db2ca', false) && !interface_exists('ComposerAutoloaderInitd747d28daa648bb0f7946d1a979db2ca', false) && !trait_exists('ComposerAutoloaderInitd747d28daa648bb0f7946d1a979db2ca', false)) { + spl_autoload_call('RectorPrefix20220422\ComposerAutoloaderInitd747d28daa648bb0f7946d1a979db2ca'); } if (!class_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false) && !interface_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false) && !trait_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false)) { spl_autoload_call('RectorPrefix20220422\Helmich\TypoScriptParser\Parser\AST\Statement'); @@ -59,9 +59,9 @@ if (!function_exists('print_node')) { return \RectorPrefix20220422\print_node(...func_get_args()); } } -if (!function_exists('composerRequire1b81052b37c79e6194fc9b2f8f4d91ad')) { - function composerRequire1b81052b37c79e6194fc9b2f8f4d91ad() { - return \RectorPrefix20220422\composerRequire1b81052b37c79e6194fc9b2f8f4d91ad(...func_get_args()); +if (!function_exists('composerRequired747d28daa648bb0f7946d1a979db2ca')) { + function composerRequired747d28daa648bb0f7946d1a979db2ca() { + return \RectorPrefix20220422\composerRequired747d28daa648bb0f7946d1a979db2ca(...func_get_args()); } } if (!function_exists('scanPath')) {