[TypeDeclaration] Skip Throw_ in construct and as Expr on ReturnNeverTypeRector (#1679)

* [TypeDeclaration] Skip Throw_ in construct and as Expr on ReturnNeverTypeRector

* move to ParentClassMethodTypeOverrideGuard

* [ci-review] Rector Rectify

* resolve phpstan notice

* final touch: define types for FunctionLike to replace new in params

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* final touch: update phpstan req to ^1.4

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Abdul Malik Ikhsan 2022-01-15 15:44:55 +07:00 committed by GitHub
parent a9d29826d4
commit 80882ad175
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 44 additions and 11 deletions

View File

@ -7,7 +7,7 @@
],
"require": {
"php": "^7.1|^8.0",
"phpstan/phpstan": "^1.3"
"phpstan/phpstan": "^1.4"
},
"autoload": {
"files": [

View File

@ -21,7 +21,7 @@
"nette/utils": "^3.2",
"nikic/php-parser": "^4.13.2",
"phpstan/phpdoc-parser": "^1.2",
"phpstan/phpstan": "^1.3",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1.0",
"psr/log": "^2.0",
"react/child-process": "^0.6.3",

View File

@ -25,7 +25,7 @@ final class PropertyToAddCollector implements NodeCollectorInterface
private array $propertiesByClass = [];
/**
* @var array<string, array<string, Type>>
* @var array<string, array<string, Type|null>>
*/
private array $propertiesWithoutConstructorByClass = [];
@ -93,7 +93,7 @@ final class PropertyToAddCollector implements NodeCollectorInterface
}
/**
* @return array<string, Type>
* @return array<string, Type|null>
*/
public function getPropertiesWithoutConstructorByClass(Class_ $class): array
{

View File

@ -13,6 +13,7 @@ use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\TypeDeclaration\TypeInferer\ParamTypeInferer;
@ -30,6 +31,12 @@ final class ParentClassMethodTypeOverrideGuard
public function isReturnTypeChangeAllowed(ClassMethod $classMethod): bool
{
// __construct cannot declare a return type
// so the return type change is not allowed
if ($this->nodeNameResolver->isName($classMethod, MethodName::CONSTRUCT)) {
return false;
}
// make sure return type is not protected by parent contract
$parentClassMethodReflection = $this->getParentClassMethod($classMethod);

View File

@ -0,0 +1,13 @@
<?php
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector\Fixture;
use Exception;
final class SkipThrowAsExpr
{
public function run($someClass)
{
$this->foo = $someClass ?: throw new Exception('current request is null');
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector\Fixture;
use Exception;
final class SkipThrowInConstruct
{
public function __construct()
{
throw new Exception();
}
}

View File

@ -11,6 +11,7 @@ use PhpParser\Node\Expr\ArrowFunction;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\AssignOp\Coalesce as AssignCoalesce;
use PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
@ -22,6 +23,7 @@ use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Return_;
use PhpParser\Node\UnionType;
use Rector\Core\Exception\ShouldNotHappenException;
@ -89,8 +91,8 @@ CODE_SAMPLE
return null;
}
/** @var ClassMethod|Closure|Function_ $node */
$node = $this->convertArrowFunctionToClosure($node);
return $this->replaceNewInParams($node);
}
@ -137,7 +139,7 @@ CODE_SAMPLE
return $param->type instanceof IntersectionType;
}
private function replaceNewInParams(FunctionLike $functionLike): FunctionLike
private function replaceNewInParams(ClassMethod|Closure|Function_ $functionLike): ClassMethod|Closure|Function_
{
$isConstructor = $functionLike instanceof ClassMethod && $this->isName($functionLike, MethodName::CONSTRUCT);

View File

@ -6,6 +6,7 @@ namespace Rector\PhpSpecToPHPUnit\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\ValueObject\MethodName;
use Rector\PhpSpecToPHPUnit\Naming\PhpSpecRenaming;
@ -74,7 +75,7 @@ final class PhpSpecMethodToPHPUnitMethodRector extends AbstractPhpSpecToPHPUnitR
foreach ((array) $classMethod->stmts as $key => $stmt) {
$printedStmtContent = $this->print($stmt);
if (\str_contains($printedStmtContent, 'duringInstantiation')) {
if (\str_contains($printedStmtContent, 'duringInstantiation') && $previousStmt instanceof Stmt) {
$printedPreviousStmt = $this->print($previousStmt);
if (\str_contains($printedPreviousStmt, 'beConstructedThrough')) {
$classMethod->stmts[$key - 1] = $stmt;

View File

@ -113,10 +113,7 @@ CODE_SAMPLE
return true;
}
$hasNeverNodes = $this->betterNodeFinder->hasInstancesOfInFunctionLikeScoped(
$node,
[Node\Expr\Throw_::class, Throw_::class]
);
$hasNeverNodes = $this->betterNodeFinder->hasInstancesOfInFunctionLikeScoped($node, [Throw_::class]);
$hasNeverFuncCall = $this->hasNeverFuncCall($node);
if (! $hasNeverNodes && ! $hasNeverFuncCall) {