Updated Rector to commit 32bf5c7e7a8da2100f12cbef185c958655d4292d

32bf5c7e7a [CodeQuality] Skip if else return on ExplicitReturnNullRector (#5755)
This commit is contained in:
Tomas Votruba 2024-03-22 16:53:50 +00:00
parent 11b9220a05
commit dd51f7ceed
7 changed files with 77 additions and 45 deletions

View File

@ -13,6 +13,7 @@ use PhpParser\Node\Stmt\Return_;
use PhpParser\Node\Stmt\Throw_; use PhpParser\Node\Stmt\Throw_;
use Rector\PhpParser\Node\BetterNodeFinder; use Rector\PhpParser\Node\BetterNodeFinder;
use Rector\Rector\AbstractRector; use Rector\Rector\AbstractRector;
use Rector\TypeDeclaration\TypeInferer\SilentVoidResolver;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/** /**
@ -25,9 +26,15 @@ final class ExplicitReturnNullRector extends AbstractRector
* @var \Rector\PhpParser\Node\BetterNodeFinder * @var \Rector\PhpParser\Node\BetterNodeFinder
*/ */
private $betterNodeFinder; private $betterNodeFinder;
public function __construct(BetterNodeFinder $betterNodeFinder) /**
* @readonly
* @var \Rector\TypeDeclaration\TypeInferer\SilentVoidResolver
*/
private $silentVoidResolver;
public function __construct(BetterNodeFinder $betterNodeFinder, SilentVoidResolver $silentVoidResolver)
{ {
$this->betterNodeFinder = $betterNodeFinder; $this->betterNodeFinder = $betterNodeFinder;
$this->silentVoidResolver = $silentVoidResolver;
} }
public function getRuleDefinition() : RuleDefinition public function getRuleDefinition() : RuleDefinition
{ {
@ -73,9 +80,6 @@ CODE_SAMPLE
if ($node->returnType instanceof Node) { if ($node->returnType instanceof Node) {
return null; return null;
} }
if ($this->hasRootLevelReturn($node)) {
return null;
}
if ($this->containsYieldOrThrow($node)) { if ($this->containsYieldOrThrow($node)) {
return null; return null;
} }
@ -83,18 +87,12 @@ CODE_SAMPLE
if (!$this->hasReturnsWithValues($node)) { if (!$this->hasReturnsWithValues($node)) {
return null; return null;
} }
if (!$this->silentVoidResolver->hasSilentVoid($node)) {
return null;
}
$node->stmts[] = new Return_(new ConstFetch(new Name('null'))); $node->stmts[] = new Return_(new ConstFetch(new Name('null')));
return $node; return $node;
} }
private function hasRootLevelReturn(ClassMethod $classMethod) : bool
{
foreach ((array) $classMethod->stmts as $stmt) {
if ($stmt instanceof Return_) {
return \true;
}
}
return \false;
}
private function containsYieldOrThrow(ClassMethod $classMethod) : bool private function containsYieldOrThrow(ClassMethod $classMethod) : bool
{ {
return (bool) $this->betterNodeFinder->findInstancesOf($classMethod, [Yield_::class, Throw_::class, Node\Expr\Throw_::class, YieldFrom::class]); return (bool) $this->betterNodeFinder->findInstancesOf($classMethod, [Yield_::class, Throw_::class, Node\Expr\Throw_::class, YieldFrom::class]);

View File

@ -7,13 +7,17 @@ use PhpParser\Node;
use PhpParser\Node\Expr; use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrowFunction; use PhpParser\Node\Expr\ArrowFunction;
use PhpParser\Node\Expr\Closure; use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\Exit_;
use PhpParser\Node\Expr\Yield_; use PhpParser\Node\Expr\Yield_;
use PhpParser\Node\Expr\YieldFrom; use PhpParser\Node\Expr\YieldFrom;
use PhpParser\Node\FunctionLike; use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt; use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Else_;
use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Finally_;
use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\If_;
use PhpParser\Node\Stmt\Return_; use PhpParser\Node\Stmt\Return_;
use PhpParser\Node\Stmt\Switch_; use PhpParser\Node\Stmt\Switch_;
use PhpParser\Node\Stmt\Throw_; use PhpParser\Node\Stmt\Throw_;
@ -60,40 +64,62 @@ final class SilentVoidResolver
if ($functionLike instanceof ArrowFunction) { if ($functionLike instanceof ArrowFunction) {
return \false; return \false;
} }
if ($this->hasStmtsAlwaysReturn((array) $functionLike->getStmts())) { $stmts = (array) $functionLike->getStmts();
return \false; return !$this->hasStmtsAlwaysReturnOrExit($stmts);
}
foreach ((array) $functionLike->getStmts() as $stmt) {
// has switch with always return
if ($stmt instanceof Switch_ && $this->isSwitchWithAlwaysReturn($stmt)) {
return \false;
}
// is part of try/catch
if ($stmt instanceof TryCatch && $this->isTryCatchAlwaysReturn($stmt)) {
return \false;
}
if ($stmt instanceof Throw_) {
return \false;
}
}
return \true;
} }
/** /**
* @param Stmt[]|Expression[] $stmts * @param Stmt[]|Expression[] $stmts
*/ */
private function hasStmtsAlwaysReturn(array $stmts) : bool private function hasStmtsAlwaysReturnOrExit(array $stmts) : bool
{ {
foreach ($stmts as $stmt) { foreach ($stmts as $stmt) {
if ($stmt instanceof Expression) { if ($stmt instanceof Expression) {
$stmt = $stmt->expr; $stmt = $stmt->expr;
} }
// is 1st level return if ($this->isStopped($stmt)) {
if ($stmt instanceof Return_) { return \true;
}
// has switch with always return
if ($stmt instanceof Switch_ && $this->isSwitchWithAlwaysReturn($stmt)) {
return \true;
}
if ($stmt instanceof TryCatch && $this->isTryCatchAlwaysReturn($stmt)) {
return \true;
}
if ($this->isIfReturn($stmt)) {
return \true; return \true;
} }
} }
return \false; return \false;
} }
/**
* @param \PhpParser\Node\Stmt|\PhpParser\Node\Expr $stmt
*/
private function isIfReturn($stmt) : bool
{
if (!$stmt instanceof If_) {
return \false;
}
foreach ($stmt->elseifs as $elseIf) {
if (!$this->hasStmtsAlwaysReturnOrExit($elseIf->stmts)) {
return \false;
}
}
if (!$stmt->else instanceof Else_) {
return \false;
}
if (!$this->hasStmtsAlwaysReturnOrExit($stmt->stmts)) {
return \false;
}
return $this->hasStmtsAlwaysReturnOrExit($stmt->else->stmts);
}
/**
* @param \PhpParser\Node\Stmt|\PhpParser\Node\Expr $stmt
*/
private function isStopped($stmt) : bool
{
return $stmt instanceof Throw_ || $stmt instanceof Exit_ || $stmt instanceof Return_;
}
private function isSwitchWithAlwaysReturn(Switch_ $switch) : bool private function isSwitchWithAlwaysReturn(Switch_ $switch) : bool
{ {
$hasDefault = \false; $hasDefault = \false;
@ -112,13 +138,15 @@ final class SilentVoidResolver
} }
private function isTryCatchAlwaysReturn(TryCatch $tryCatch) : bool private function isTryCatchAlwaysReturn(TryCatch $tryCatch) : bool
{ {
if (!$this->hasStmtsAlwaysReturn($tryCatch->stmts)) { if (!$this->hasStmtsAlwaysReturnOrExit($tryCatch->stmts)) {
return \false; return \false;
} }
foreach ($tryCatch->catches as $catch) { foreach ($tryCatch->catches as $catch) {
return $this->hasStmtsAlwaysReturn($catch->stmts); if (!$this->hasStmtsAlwaysReturnOrExit($catch->stmts)) {
return \false;
}
} }
return \true; return !($tryCatch->finally instanceof Finally_ && !$this->hasStmtsAlwaysReturnOrExit($tryCatch->finally->stmts));
} }
private function resolveReturnCount(Switch_ $switch) : int private function resolveReturnCount(Switch_ $switch) : int
{ {

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api * @api
* @var string * @var string
*/ */
public const PACKAGE_VERSION = 'b4eb883e9110f50607ce2eed629c237b5e7e7356'; public const PACKAGE_VERSION = '32bf5c7e7a8da2100f12cbef185c958655d4292d';
/** /**
* @api * @api
* @var string * @var string
*/ */
public const RELEASE_DATE = '2024-03-22 01:35:52'; public const RELEASE_DATE = '2024-03-22 23:51:21';
/** /**
* @var int * @var int
*/ */

View File

@ -1679,12 +1679,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-doctrine.git", "url": "https:\/\/github.com\/rectorphp\/rector-doctrine.git",
"reference": "bbc48ccb87e026a100e86d6dc2a238b1293c14cb" "reference": "b3da143634de79b24a266afc07401cfe75a2c49c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/bbc48ccb87e026a100e86d6dc2a238b1293c14cb", "url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/b3da143634de79b24a266afc07401cfe75a2c49c",
"reference": "bbc48ccb87e026a100e86d6dc2a238b1293c14cb", "reference": "b3da143634de79b24a266afc07401cfe75a2c49c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1709,7 +1709,7 @@
"tomasvotruba\/unused-public": "^0.3", "tomasvotruba\/unused-public": "^0.3",
"tracy\/tracy": "^2.10" "tracy\/tracy": "^2.10"
}, },
"time": "2024-03-22T00:08:11+00:00", "time": "2024-03-22T00:11:46+00:00",
"default-branch": true, "default-branch": true,
"type": "rector-extension", "type": "rector-extension",
"extra": { "extra": {

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
*/ */
final class GeneratedConfig final class GeneratedConfig
{ {
public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => NULL, 'version' => 'dev-main bbc48cc'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => NULL, 'version' => 'dev-main eadea25'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => NULL, 'version' => 'dev-main 6845db4'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => NULL, 'version' => 'dev-main c8b6413')); public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => NULL, 'version' => 'dev-main b3da143'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => NULL, 'version' => 'dev-main eadea25'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => NULL, 'version' => 'dev-main 6845db4'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/rector-build/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => NULL, 'version' => 'dev-main c8b6413'));
private function __construct() private function __construct()
{ {
} }

View File

@ -12,6 +12,8 @@ use Rector\Doctrine\NodeFactory\ArrayCollectionAssignFactory;
use Rector\NodeManipulator\ClassDependencyManipulator; use Rector\NodeManipulator\ClassDependencyManipulator;
use Rector\Rector\AbstractRector; use Rector\Rector\AbstractRector;
use Rector\TypeDeclaration\AlreadyAssignDetector\ConstructorAssignDetector; use Rector\TypeDeclaration\AlreadyAssignDetector\ConstructorAssignDetector;
use Rector\ValueObject\PhpVersionFeature;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/** /**
@ -19,7 +21,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
* *
* @changelog https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/best-practices.html#initialize-collections-in-the-constructor * @changelog https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/best-practices.html#initialize-collections-in-the-constructor
*/ */
final class ExplicitRelationCollectionRector extends AbstractRector final class ExplicitRelationCollectionRector extends AbstractRector implements MinPhpVersionInterface
{ {
/** /**
* @readonly * @readonly
@ -123,4 +125,8 @@ CODE_SAMPLE
$this->classDependencyManipulator->addStmtsToConstructorIfNotThereYet($node, $arrayCollectionAssigns); $this->classDependencyManipulator->addStmtsToConstructorIfNotThereYet($node, $arrayCollectionAssigns);
return $node; return $node;
} }
public function provideMinPhpVersion() : int
{
return PhpVersionFeature::TYPED_PROPERTIES;
}
} }