mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-18 05:48:21 +01:00
Updated Rector to commit 8df2120b3f546dd7f0eb89bf199a042dfc9283e7
8df2120b3f
Skip void without final keyword in ReturnNeverTypeRector as could be implemented with more precise children (#5379)
This commit is contained in:
parent
0ee99bfbc9
commit
94baa5fede
44
rules/TypeDeclaration/NodeAnalyzer/NeverFuncCallAnalyzer.php
Normal file
44
rules/TypeDeclaration/NodeAnalyzer/NeverFuncCallAnalyzer.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\TypeDeclaration\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PHPStan\Type\NeverType;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
final class NeverFuncCallAnalyzer
|
||||
{
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\NodeTypeResolver\NodeTypeResolver
|
||||
*/
|
||||
private $nodeTypeResolver;
|
||||
public function __construct(NodeTypeResolver $nodeTypeResolver)
|
||||
{
|
||||
$this->nodeTypeResolver = $nodeTypeResolver;
|
||||
}
|
||||
/**
|
||||
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Stmt\Function_ $functionLike
|
||||
*/
|
||||
public function hasNeverFuncCall($functionLike) : bool
|
||||
{
|
||||
$hasNeverType = \false;
|
||||
foreach ((array) $functionLike->stmts as $stmt) {
|
||||
if ($stmt instanceof Expression) {
|
||||
$stmt = $stmt->expr;
|
||||
}
|
||||
if ($stmt instanceof Stmt) {
|
||||
continue;
|
||||
}
|
||||
$stmtType = $this->nodeTypeResolver->getNativeType($stmt);
|
||||
if ($stmtType instanceof NeverType) {
|
||||
$hasNeverType = \true;
|
||||
}
|
||||
}
|
||||
return $hasNeverType;
|
||||
}
|
||||
}
|
@ -7,18 +7,17 @@ use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Expr\Yield_;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PhpParser\Node\Stmt\Throw_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Type\NeverType;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\Core\Rector\AbstractScopeAwareRector;
|
||||
use Rector\Core\ValueObject\PhpVersionFeature;
|
||||
use Rector\NodeNestingScope\ValueObject\ControlStructure;
|
||||
use Rector\TypeDeclaration\NodeAnalyzer\NeverFuncCallAnalyzer;
|
||||
use Rector\VendorLocker\NodeVendorLocker\ClassMethodReturnTypeOverrideGuard;
|
||||
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
@ -40,10 +39,16 @@ final class ReturnNeverTypeRector extends AbstractScopeAwareRector implements Mi
|
||||
* @var \Rector\Core\PhpParser\Node\BetterNodeFinder
|
||||
*/
|
||||
private $betterNodeFinder;
|
||||
public function __construct(ClassMethodReturnTypeOverrideGuard $classMethodReturnTypeOverrideGuard, BetterNodeFinder $betterNodeFinder)
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\TypeDeclaration\NodeAnalyzer\NeverFuncCallAnalyzer
|
||||
*/
|
||||
private $neverFuncCallAnalyzer;
|
||||
public function __construct(ClassMethodReturnTypeOverrideGuard $classMethodReturnTypeOverrideGuard, BetterNodeFinder $betterNodeFinder, NeverFuncCallAnalyzer $neverFuncCallAnalyzer)
|
||||
{
|
||||
$this->classMethodReturnTypeOverrideGuard = $classMethodReturnTypeOverrideGuard;
|
||||
$this->betterNodeFinder = $betterNodeFinder;
|
||||
$this->neverFuncCallAnalyzer = $neverFuncCallAnalyzer;
|
||||
}
|
||||
public function getRuleDefinition() : RuleDefinition
|
||||
{
|
||||
@ -97,17 +102,10 @@ CODE_SAMPLE
|
||||
if ($node->returnType instanceof Node && !$this->isName($node->returnType, 'void')) {
|
||||
return \true;
|
||||
}
|
||||
$hasReturn = $this->betterNodeFinder->hasInstancesOfInFunctionLikeScoped($node, Return_::class);
|
||||
if ($hasReturn) {
|
||||
if ($this->hasReturnOrYields($node)) {
|
||||
return \true;
|
||||
}
|
||||
$hasNotNeverNodes = $this->betterNodeFinder->hasInstancesOfInFunctionLikeScoped($node, \array_merge([Yield_::class], ControlStructure::CONDITIONAL_NODE_SCOPE_TYPES));
|
||||
if ($hasNotNeverNodes) {
|
||||
return \true;
|
||||
}
|
||||
$hasNeverNodes = $this->betterNodeFinder->hasInstancesOfInFunctionLikeScoped($node, [Throw_::class]);
|
||||
$hasNeverFuncCall = $this->hasNeverFuncCall($node);
|
||||
if (!$hasNeverNodes && !$hasNeverFuncCall) {
|
||||
if (!$this->hasNeverNodesOrNeverFuncCalls($node)) {
|
||||
return \true;
|
||||
}
|
||||
if ($node instanceof ClassMethod && $this->classMethodReturnTypeOverrideGuard->shouldSkipClassMethod($node, $scope)) {
|
||||
@ -116,26 +114,32 @@ CODE_SAMPLE
|
||||
if (!$node->returnType instanceof Node) {
|
||||
return \false;
|
||||
}
|
||||
// skip as most likely intentional
|
||||
$classReflection = $scope->getClassReflection();
|
||||
if ($classReflection instanceof ClassReflection && !$classReflection->isFinalByKeyword() && $this->isName($node->returnType, 'void')) {
|
||||
return \true;
|
||||
}
|
||||
return $this->isName($node->returnType, 'never');
|
||||
}
|
||||
/**
|
||||
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Stmt\Function_ $functionLike
|
||||
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure $node
|
||||
*/
|
||||
private function hasNeverFuncCall($functionLike) : bool
|
||||
private function hasReturnOrYields($node) : bool
|
||||
{
|
||||
$hasNeverType = \false;
|
||||
foreach ((array) $functionLike->stmts as $stmt) {
|
||||
if ($stmt instanceof Expression) {
|
||||
$stmt = $stmt->expr;
|
||||
}
|
||||
if ($stmt instanceof Stmt) {
|
||||
continue;
|
||||
}
|
||||
$stmtType = $this->nodeTypeResolver->getNativeType($stmt);
|
||||
if ($stmtType instanceof NeverType) {
|
||||
$hasNeverType = \true;
|
||||
}
|
||||
if ($this->betterNodeFinder->hasInstancesOfInFunctionLikeScoped($node, Return_::class)) {
|
||||
return \true;
|
||||
}
|
||||
return $hasNeverType;
|
||||
return $this->betterNodeFinder->hasInstancesOfInFunctionLikeScoped($node, \array_merge([Yield_::class], ControlStructure::CONDITIONAL_NODE_SCOPE_TYPES));
|
||||
}
|
||||
/**
|
||||
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure $node
|
||||
*/
|
||||
private function hasNeverNodesOrNeverFuncCalls($node) : bool
|
||||
{
|
||||
$hasNeverNodes = $this->betterNodeFinder->hasInstancesOfInFunctionLikeScoped($node, [Throw_::class]);
|
||||
if ($hasNeverNodes) {
|
||||
return \true;
|
||||
}
|
||||
return $this->neverFuncCallAnalyzer->hasNeverFuncCall($node);
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ final class VersionResolver
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PACKAGE_VERSION = '53ba155ab03ce7717ecef42b311880b314a40fbc';
|
||||
public const PACKAGE_VERSION = '8df2120b3f546dd7f0eb89bf199a042dfc9283e7';
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const RELEASE_DATE = '2023-12-23 18:31:28';
|
||||
public const RELEASE_DATE = '2023-12-23 14:49:31';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
1
vendor/composer/autoload_classmap.php
vendored
1
vendor/composer/autoload_classmap.php
vendored
@ -2291,6 +2291,7 @@ return array(
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\CallerParamMatcher' => $baseDir . '/rules/TypeDeclaration/NodeAnalyzer/CallerParamMatcher.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ClassMethodAndPropertyAnalyzer' => $baseDir . '/rules/TypeDeclaration/NodeAnalyzer/ClassMethodAndPropertyAnalyzer.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ClassMethodParamTypeCompleter' => $baseDir . '/rules/TypeDeclaration/NodeAnalyzer/ClassMethodParamTypeCompleter.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\NeverFuncCallAnalyzer' => $baseDir . '/rules/TypeDeclaration/NodeAnalyzer/NeverFuncCallAnalyzer.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ParamAnalyzer' => $baseDir . '/rules/TypeDeclaration/NodeAnalyzer/ParamAnalyzer.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ReturnAnalyzer' => $baseDir . '/rules/TypeDeclaration/NodeAnalyzer/ReturnAnalyzer.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ReturnFilter\\ExclusiveNativeCallLikeReturnMatcher' => $baseDir . '/rules/TypeDeclaration/NodeAnalyzer/ReturnFilter/ExclusiveNativeCallLikeReturnMatcher.php',
|
||||
|
1
vendor/composer/autoload_static.php
vendored
1
vendor/composer/autoload_static.php
vendored
@ -2509,6 +2509,7 @@ class ComposerStaticInit8339caf294dd12447c06647e5d0dc118
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\CallerParamMatcher' => __DIR__ . '/../..' . '/rules/TypeDeclaration/NodeAnalyzer/CallerParamMatcher.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ClassMethodAndPropertyAnalyzer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/NodeAnalyzer/ClassMethodAndPropertyAnalyzer.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ClassMethodParamTypeCompleter' => __DIR__ . '/../..' . '/rules/TypeDeclaration/NodeAnalyzer/ClassMethodParamTypeCompleter.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\NeverFuncCallAnalyzer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/NodeAnalyzer/NeverFuncCallAnalyzer.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ParamAnalyzer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/NodeAnalyzer/ParamAnalyzer.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ReturnAnalyzer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/NodeAnalyzer/ReturnAnalyzer.php',
|
||||
'Rector\\TypeDeclaration\\NodeAnalyzer\\ReturnFilter\\ExclusiveNativeCallLikeReturnMatcher' => __DIR__ . '/../..' . '/rules/TypeDeclaration/NodeAnalyzer/ReturnFilter/ExclusiveNativeCallLikeReturnMatcher.php',
|
||||
|
8
vendor/composer/installed.json
vendored
8
vendor/composer/installed.json
vendored
@ -1808,12 +1808,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https:\/\/github.com\/rectorphp\/rector-phpunit.git",
|
||||
"reference": "669f5eed1a738fc08bb90d7dee6ba6bf72da1302"
|
||||
"reference": "1cbcfcbdf5576e12e213b493db1a8813d8277c3b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/669f5eed1a738fc08bb90d7dee6ba6bf72da1302",
|
||||
"reference": "669f5eed1a738fc08bb90d7dee6ba6bf72da1302",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/1cbcfcbdf5576e12e213b493db1a8813d8277c3b",
|
||||
"reference": "1cbcfcbdf5576e12e213b493db1a8813d8277c3b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1843,7 +1843,7 @@
|
||||
"tomasvotruba\/unused-public": "^0.3",
|
||||
"tracy\/tracy": "^2.10"
|
||||
},
|
||||
"time": "2023-12-22T07:51:11+00:00",
|
||||
"time": "2023-12-23T14:25:09+00:00",
|
||||
"default-branch": true,
|
||||
"type": "rector-extension",
|
||||
"extra": {
|
||||
|
2
vendor/composer/installed.php
vendored
2
vendor/composer/installed.php
vendored
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
|
||||
*/
|
||||
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 c7ff3e5'), '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 917085c'), '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 669f5ee'), '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 5f1e96d'));
|
||||
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 c7ff3e5'), '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 917085c'), '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 1cbcfcb'), '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 5f1e96d'));
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\PHPUnit\PHPUnit60\Rector\MethodCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
@ -74,6 +75,10 @@ CODE_SAMPLE
|
||||
if (!$currentMethodCall instanceof MethodCall) {
|
||||
return null;
|
||||
}
|
||||
// can be only local call, as createMock() is protected method
|
||||
if (!$this->isLocalScopeCaller($currentMethodCall)) {
|
||||
return null;
|
||||
}
|
||||
// must be be test case class
|
||||
if (!$this->isObjectType($currentMethodCall->var, new ObjectType('PHPUnit\\Framework\\TestCase'))) {
|
||||
return null;
|
||||
@ -85,4 +90,11 @@ CODE_SAMPLE
|
||||
$thisVariable = $currentMethodCall->var;
|
||||
return new MethodCall($thisVariable, 'createMock', $args);
|
||||
}
|
||||
private function isLocalScopeCaller(MethodCall $currentMethodCall) : bool
|
||||
{
|
||||
if (!$currentMethodCall->var instanceof Variable) {
|
||||
return \false;
|
||||
}
|
||||
return $currentMethodCall->var->name === 'this';
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user