-
-
Notifications
You must be signed in to change notification settings - Fork 336
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[TypeDeclaration] Add ReturnTypeFromReturnCastRector (#5905)
* [TypeDeclaration] Add ReturnTypeFromReturnCastRector * [TypeDeclaration] Add ReturnTypeFromReturnCastRector * register * only specific type * final touch: skip no return * skip multiple casts as union type and covered by ReturnUnionTypeRector * [ci-review] Rector Rectify --------- Co-authored-by: GitHub Action <actions@github.com>
- Loading branch information
1 parent
d1eb62e
commit b8847be
Showing
10 changed files
with
338 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...ector/ClassMethod/ReturnTypeFromReturnCastRector/Fixture/add_return_array_by_cast.php.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector\Fixture; | ||
|
||
final class AddReturnArrayByCast | ||
{ | ||
public function getArray($data) | ||
{ | ||
try { | ||
return (array) $data; | ||
} catch (\Exception $e) { | ||
throw $e; | ||
} | ||
} | ||
} | ||
|
||
?> | ||
----- | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector\Fixture; | ||
|
||
final class AddReturnArrayByCast | ||
{ | ||
public function getArray($data): array | ||
{ | ||
try { | ||
return (array) $data; | ||
} catch (\Exception $e) { | ||
throw $e; | ||
} | ||
} | ||
} | ||
|
||
?> |
39 changes: 39 additions & 0 deletions
39
...ctor/ClassMethod/ReturnTypeFromReturnCastRector/Fixture/add_return_object_by_cast.php.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector\Fixture; | ||
|
||
final class AddReturnObjectByCast | ||
{ | ||
public function getObject($data) | ||
{ | ||
try { | ||
return (object) $data; | ||
} catch (\Exception $e) { | ||
throw $e; | ||
} | ||
} | ||
} | ||
|
||
?> | ||
----- | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector\Fixture; | ||
|
||
final class AddReturnObjectByCast | ||
{ | ||
public function getObject($data): \stdClass | ||
{ | ||
try { | ||
return (object) $data; | ||
} catch (\Exception $e) { | ||
throw $e; | ||
} | ||
} | ||
} | ||
|
||
?> |
17 changes: 17 additions & 0 deletions
17
...tion/Rector/ClassMethod/ReturnTypeFromReturnCastRector/Fixture/skip_multiple_cast.php.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector\Fixture; | ||
|
||
final class SkipMultipleCasts | ||
{ | ||
public function run($data) | ||
{ | ||
if (rand(0, 1)) { | ||
return (string) $data; | ||
} | ||
|
||
return (bool) $data; | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...laration/Rector/ClassMethod/ReturnTypeFromReturnCastRector/Fixture/skip_no_return.php.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector\Fixture; | ||
|
||
final class SkipNoReturn | ||
{ | ||
public function run($data) | ||
{ | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
...aration/Rector/ClassMethod/ReturnTypeFromReturnCastRector/Fixture/skip_not_casted.php.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector\Fixture; | ||
|
||
final class SkipNotCasted | ||
{ | ||
public function returnNotCasted($data) | ||
{ | ||
try { | ||
return $data; | ||
} catch (\Exception $e) { | ||
throw $e; | ||
} | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
.../Rector/ClassMethod/ReturnTypeFromReturnCastRector/ReturnTypeFromReturnCastRectorTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector; | ||
|
||
use Iterator; | ||
use PHPUnit\Framework\Attributes\DataProvider; | ||
use Rector\Testing\PHPUnit\AbstractRectorTestCase; | ||
|
||
final class ReturnTypeFromReturnCastRectorTest extends AbstractRectorTestCase | ||
{ | ||
#[DataProvider('provideData')] | ||
public function test(string $filePath): void | ||
{ | ||
$this->doTestFile($filePath); | ||
} | ||
|
||
public static function provideData(): Iterator | ||
{ | ||
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); | ||
} | ||
|
||
public function provideConfigFilePath(): string | ||
{ | ||
return __DIR__ . '/config/configured_rule.php'; | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
...eDeclaration/Rector/ClassMethod/ReturnTypeFromReturnCastRector/config/configured_rule.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
use Rector\Config\RectorConfig; | ||
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector; | ||
|
||
return RectorConfig::configure() | ||
->withRules([ReturnTypeFromReturnCastRector::class]); |
127 changes: 127 additions & 0 deletions
127
rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromReturnCastRector.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\TypeDeclaration\Rector\ClassMethod; | ||
|
||
use PhpParser\Node; | ||
use PhpParser\Node\Expr\Cast; | ||
use PhpParser\Node\Expr\Closure; | ||
use PhpParser\Node\Stmt\ClassMethod; | ||
use PhpParser\Node\Stmt\Function_; | ||
use PhpParser\Node\Stmt\Return_; | ||
use PHPStan\Analyser\Scope; | ||
use PHPStan\Type\UnionType; | ||
use Rector\PhpParser\Node\BetterNodeFinder; | ||
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; | ||
use Rector\Rector\AbstractScopeAwareRector; | ||
use Rector\StaticTypeMapper\StaticTypeMapper; | ||
use Rector\TypeDeclaration\TypeInferer\ReturnTypeInferer; | ||
use Rector\ValueObject\PhpVersionFeature; | ||
use Rector\VendorLocker\NodeVendorLocker\ClassMethodReturnTypeOverrideGuard; | ||
use Rector\VersionBonding\Contract\MinPhpVersionInterface; | ||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; | ||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; | ||
|
||
/** | ||
* @see \Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnCastRector\ReturnTypeFromReturnCastRectorTest | ||
*/ | ||
final class ReturnTypeFromReturnCastRector extends AbstractScopeAwareRector implements MinPhpVersionInterface | ||
{ | ||
public function __construct( | ||
private readonly ClassMethodReturnTypeOverrideGuard $classMethodReturnTypeOverrideGuard, | ||
private readonly ReturnTypeInferer $returnTypeInferer, | ||
private readonly BetterNodeFinder $betterNodeFinder, | ||
private readonly StaticTypeMapper $staticTypeMapper | ||
) { | ||
} | ||
|
||
public function getRuleDefinition(): RuleDefinition | ||
{ | ||
return new RuleDefinition('Add return type to function like with return cast', [ | ||
new CodeSample( | ||
<<<'CODE_SAMPLE' | ||
final class SomeClass | ||
{ | ||
public function action($param) | ||
{ | ||
try { | ||
return (array) $param; | ||
} catch (Exception $exception) { | ||
// some logging | ||
throw $exception; | ||
} | ||
} | ||
} | ||
CODE_SAMPLE | ||
, | ||
<<<'CODE_SAMPLE' | ||
final class SomeClass | ||
{ | ||
public function action($param): array | ||
{ | ||
try { | ||
return (array) $param; | ||
} catch (Exception $exception) { | ||
// some logging | ||
throw $exception; | ||
} | ||
} | ||
} | ||
CODE_SAMPLE | ||
), | ||
]); | ||
} | ||
|
||
/** | ||
* @return array<class-string<Node>> | ||
*/ | ||
public function getNodeTypes(): array | ||
{ | ||
return [ClassMethod::class, Function_::class, Closure::class]; | ||
} | ||
|
||
/** | ||
* @param ClassMethod|Function_|Closure $node | ||
*/ | ||
public function refactorWithScope(Node $node, Scope $scope): ?Node | ||
{ | ||
if ($node->returnType !== null) { | ||
return null; | ||
} | ||
|
||
if ($node instanceof ClassMethod && $this->classMethodReturnTypeOverrideGuard->shouldSkipClassMethod( | ||
$node, | ||
$scope | ||
)) { | ||
return null; | ||
} | ||
|
||
$hasNonCastReturn = (bool) $this->betterNodeFinder->findFirstInFunctionLikeScoped( | ||
$node, | ||
static fn (Node $subNode): bool => $subNode instanceof Return_ && ! $subNode->expr instanceof Cast | ||
); | ||
|
||
if ($hasNonCastReturn) { | ||
return null; | ||
} | ||
|
||
$returnType = $this->returnTypeInferer->inferFunctionLike($node); | ||
if ($returnType instanceof UnionType || $returnType->isVoid()->yes()) { | ||
return null; | ||
} | ||
|
||
$returnTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($returnType, TypeKind::RETURN); | ||
if (! $returnTypeNode instanceof Node) { | ||
return null; | ||
} | ||
|
||
$node->returnType = $returnTypeNode; | ||
return $node; | ||
} | ||
|
||
public function provideMinPhpVersion(): int | ||
{ | ||
return PhpVersionFeature::SCALAR_TYPES; | ||
} | ||
} |
Oops, something went wrong.