Skip to content

Commit dc34f6c

Browse files
authored
[type-declaration] Add AddReturnTypeFromTryCatchTypeRector (#7099)
* [type-declaration] Add AddReturnTypeFromTryCatchTypeRector * use ClassMethodReturnTypeOverrideGuard * skip silent void * finalize classes * [ci] fail on missed final class
1 parent 8242866 commit dc34f6c

17 files changed

Lines changed: 354 additions & 25 deletions

File tree

.github/workflows/code_analysis.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050

5151
-
5252
name: 'Finalize classes'
53-
run: vendor/bin/swiss-knife finalize-classes src tests
53+
run: vendor/bin/swiss-knife finalize-classes src tests --dry-run
5454

5555
-
5656
name: 'Detect composer dependency issues'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddReturnTypeFromTryCatchTypeRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class AddReturnTypeFromTryCatchTypeRectorTest extends AbstractRectorTestCase
12+
{
13+
#[DataProvider('provideData')]
14+
public function test(string $filePath): void
15+
{
16+
$this->doTestFile($filePath);
17+
}
18+
19+
public static function provideData(): Iterator
20+
{
21+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
22+
}
23+
24+
public function provideConfigFilePath(): string
25+
{
26+
return __DIR__ . '/config/configured_rule.php';
27+
}
28+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddReturnTypeFromTryCatchTypeRector\Fixture;
4+
5+
final class SimpleTryCatch
6+
{
7+
public function run()
8+
{
9+
try {
10+
return 1;
11+
} catch (\Exception $e) {
12+
return 2;
13+
}
14+
}
15+
}
16+
17+
?>
18+
-----
19+
<?php
20+
21+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddReturnTypeFromTryCatchTypeRector\Fixture;
22+
23+
final class SimpleTryCatch
24+
{
25+
public function run(): int
26+
{
27+
try {
28+
return 1;
29+
} catch (\Exception $e) {
30+
return 2;
31+
}
32+
}
33+
}
34+
35+
?>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddReturnTypeFromTryCatchTypeRector\Fixture;
4+
5+
final class SimpleTryCatch
6+
{
7+
public function run()
8+
{
9+
try {
10+
return 1;
11+
} catch (\Exception $e) {
12+
return $this->getIntDoc();
13+
}
14+
}
15+
16+
/**
17+
* @return int
18+
*/
19+
private function getIntDoc()
20+
{
21+
return mt_rand(0, 1) ? 'string' : 1;
22+
}
23+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddReturnTypeFromTryCatchTypeRector\Fixture;
4+
5+
final class SkipIfNoCatch
6+
{
7+
public function run()
8+
{
9+
try {
10+
return 1;
11+
} finally {
12+
return 5;
13+
}
14+
}
15+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddReturnTypeFromTryCatchTypeRector\Fixture;
4+
5+
interface SkipInterface
6+
{
7+
public function run();
8+
}
9+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddReturnTypeFromTryCatchTypeRector\Fixture;
4+
5+
final class SkipKnownType
6+
{
7+
public function run(): int
8+
{
9+
try {
10+
11+
return 1;
12+
13+
} catch (\Exception $e) {
14+
15+
return 2;
16+
17+
}
18+
}
19+
}
20+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddReturnTypeFromTryCatchTypeRector\Fixture;
4+
5+
final class SkipSilentVoid
6+
{
7+
public function run()
8+
{
9+
try {
10+
if (rand(0, 1)) {
11+
return;
12+
}
13+
14+
return 1;
15+
} catch (\Exception $e) {
16+
return 2;
17+
}
18+
}
19+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeFromTryCatchTypeRector;
7+
8+
return static function (RectorConfig $rectorConfig): void {
9+
$rectorConfig->rule(AddReturnTypeFromTryCatchTypeRector::class);
10+
};

rules/Transform/Rector/ArrayDimFetch/ArrayDimFetchToMethodCallRector.php

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
/**
2929
* @see \Rector\Tests\Transform\Rector\ArrayDimFetch\ArrayDimFetchToMethodCallRector\ArrayDimFetchToMethodCallRectorTest
3030
*/
31-
class ArrayDimFetchToMethodCallRector extends AbstractRector implements ConfigurableRectorInterface
31+
final class ArrayDimFetchToMethodCallRector extends AbstractRector implements ConfigurableRectorInterface
3232
{
3333
/**
3434
* @var ArrayDimFetchToMethodCall[]
@@ -101,16 +101,16 @@ public function configure(array $configuration): void
101101
$this->arrayDimFetchToMethodCalls = $configuration;
102102
}
103103

104-
private function handleIsset(Isset_ $node): Expr|int|null
104+
private function handleIsset(Isset_ $isset): Expr|int|null
105105
{
106106
$issets = [];
107107
$exprs = [];
108108

109-
foreach ($node->vars as $var) {
109+
foreach ($isset->vars as $var) {
110110
if ($var instanceof ArrayDimFetch) {
111111
$methodCall = $this->getMethodCall($var, 'exists');
112112

113-
if ($methodCall !== null) {
113+
if ($methodCall instanceof MethodCall) {
114114
$exprs[] = $methodCall;
115115
continue;
116116
}
@@ -124,30 +124,30 @@ private function handleIsset(Isset_ $node): Expr|int|null
124124
}
125125

126126
if ($issets !== []) {
127-
$node->vars = $issets;
128-
array_unshift($exprs, $node);
127+
$isset->vars = $issets;
128+
array_unshift($exprs, $isset);
129129
}
130130

131131
return array_reduce(
132132
$exprs,
133-
fn (?Expr $carry, Expr $expr) => $carry === null ? $expr : new BooleanAnd($carry, $expr),
133+
fn (?Expr $carry, Expr $expr): Isset_|MethodCall|BooleanAnd => $carry instanceof Expr ? new BooleanAnd($carry, $expr) : $expr,
134134
null,
135135
);
136136
}
137137

138138
/**
139139
* @return Stmt[]|int
140140
*/
141-
private function handleUnset(Unset_ $node): array|int
141+
private function handleUnset(Unset_ $unset): array|int
142142
{
143143
$unsets = [];
144144
$stmts = [];
145145

146-
foreach ($node->vars as $var) {
146+
foreach ($unset->vars as $var) {
147147
if ($var instanceof ArrayDimFetch) {
148148
$methodCall = $this->getMethodCall($var, 'unset');
149149

150-
if ($methodCall !== null) {
150+
if ($methodCall instanceof MethodCall) {
151151
$stmts[] = new Expression($methodCall);
152152
continue;
153153
}
@@ -161,8 +161,8 @@ private function handleUnset(Unset_ $node): array|int
161161
}
162162

163163
if ($unsets !== []) {
164-
$node->vars = $unsets;
165-
array_unshift($stmts, $node);
164+
$unset->vars = $unsets;
165+
array_unshift($stmts, $unset);
166166
}
167167

168168
return $stmts;
@@ -171,14 +171,14 @@ private function handleUnset(Unset_ $node): array|int
171171
/**
172172
* @param 'get'|'set'|'exists'|'unset' $action
173173
*/
174-
private function getMethodCall(ArrayDimFetch $fetch, string $action, ?Expr $value = null): ?MethodCall
174+
private function getMethodCall(ArrayDimFetch $arrayDimFetch, string $action, ?Expr $expr = null): ?MethodCall
175175
{
176-
if (!$fetch->dim instanceof Node) {
176+
if (!$arrayDimFetch->dim instanceof Node) {
177177
return null;
178178
}
179179

180180
foreach ($this->arrayDimFetchToMethodCalls as $arrayDimFetchToMethodCall) {
181-
if (!$this->isObjectType($fetch->var, $arrayDimFetchToMethodCall->getObjectType())) {
181+
if (!$this->isObjectType($arrayDimFetch->var, $arrayDimFetchToMethodCall->getObjectType())) {
182182
continue;
183183
}
184184

@@ -193,13 +193,13 @@ private function getMethodCall(ArrayDimFetch $fetch, string $action, ?Expr $valu
193193
continue;
194194
}
195195

196-
$args = [new Arg($fetch->dim)];
196+
$args = [new Arg($arrayDimFetch->dim)];
197197

198-
if ($value instanceof Expr) {
199-
$args[] = new Arg($value);
198+
if ($expr instanceof Expr) {
199+
$args[] = new Arg($expr);
200200
}
201201

202-
return new MethodCall($fetch->var, $method, $args);
202+
return new MethodCall($arrayDimFetch->var, $method, $args);
203203
}
204204

205205
return null;

0 commit comments

Comments
 (0)