Skip to content

Commit a1d83a2

Browse files
committed
Option for reporting all unused catch statements
1 parent 0077d82 commit a1d83a2

File tree

7 files changed

+145
-7
lines changed

7 files changed

+145
-7
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ includes:
4444
4545
parameters:
4646
exceptionRules:
47+
reportUnusedCatchesOfUncheckedExceptions: false
4748
checkedExceptions:
4849
- RuntimeException
4950
```

extension.neon

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
parameters:
22
exceptionRules:
3-
reportMaybes: true
3+
reportUnusedCatchesOfUncheckedExceptions: false
44
checkedExceptions: []
55
methodThrowTypeDeclarations: []
66
functionThrowTypeDeclarations: []
@@ -21,6 +21,8 @@ services:
2121

2222
-
2323
class: Pepakriz\PHPStanExceptionRules\Rules\ThrowsPhpDocRule
24+
arguments:
25+
reportUnusedCatchesOfUncheckedExceptions: %exceptionRules.reportUnusedCatchesOfUncheckedExceptions%
2426
tags: [phpstan.rules.rule]
2527

2628
-

phpstan.neon.dist

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,15 @@ parameters:
1212
- %rootDir%/../../../tests/*/data/*
1313

1414
exceptionRules:
15+
reportUnusedCatchesOfUncheckedExceptions: true
1516
checkedExceptions:
1617
- Pepakriz\PHPStanExceptionRules\RuntimeException
18+
methodThrowTypeDeclarations:
19+
PHPStan\Broker\Broker:
20+
getClass:
21+
- PHPStan\Broker\ClassNotFoundException
22+
getFunction:
23+
- PHPStan\Broker\FunctionNotFoundException
24+
PHPStan\Reflection\ClassReflection:
25+
getMethod:
26+
- PHPStan\Reflection\MissingMethodFromReflectionException

src/Rules/ThrowsPhpDocRule.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,23 @@ class ThrowsPhpDocRule implements Rule
6565
*/
6666
private $throwsScope;
6767

68+
/**
69+
* @var bool
70+
*/
71+
private $reportUnusedCatchesOfUncheckedExceptions;
72+
6873
public function __construct(
6974
CheckedExceptionService $checkedExceptionService,
7075
DynamicThrowTypeService $dynamicThrowTypeService,
71-
Broker $broker
76+
Broker $broker,
77+
bool $reportUnusedCatchesOfUncheckedExceptions
7278
)
7379
{
7480
$this->checkedExceptionService = $checkedExceptionService;
7581
$this->dynamicThrowTypeService = $dynamicThrowTypeService;
7682
$this->broker = $broker;
7783
$this->throwsScope = new ThrowsScope();
84+
$this->reportUnusedCatchesOfUncheckedExceptions = $reportUnusedCatchesOfUncheckedExceptions;
7885
}
7986

8087
public function getNodeType(): string
@@ -378,13 +385,19 @@ private function processCatch(Catch_ $node): array
378385
}
379386
}
380387

381-
$caughtExceptions = $this->checkedExceptionService->filterCheckedExceptions($caughtExceptions);
382-
if (count($caughtExceptions) > 0) {
388+
$exceptionClass = $type->toString();
389+
if (
390+
!$this->reportUnusedCatchesOfUncheckedExceptions
391+
&& !$this->checkedExceptionService->isCheckedException($exceptionClass)
392+
) {
383393
continue;
384394
}
385395

386-
$exceptionClass = $type->toString();
387-
if (!$this->checkedExceptionService->isCheckedException($exceptionClass)) {
396+
if (!$this->reportUnusedCatchesOfUncheckedExceptions) {
397+
$caughtExceptions = $this->checkedExceptionService->filterCheckedExceptions($caughtExceptions);
398+
}
399+
400+
if (count($caughtExceptions) > 0) {
388401
continue;
389402
}
390403

tests/src/Rules/ThrowsPhpDocRuleTest.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
class ThrowsPhpDocRuleTest extends RuleTestCase
1616
{
1717

18+
/**
19+
* @var bool
20+
*/
21+
private $reportUnusedCatchesOfUncheckedExceptions = false;
22+
1823
protected function getRule(): Rule
1924
{
2025
$throwsRule = new ThrowsPhpDocRule(
@@ -31,7 +36,8 @@ protected function getRule(): Rule
3136
], [
3237
new DynamicFunctionExtension(),
3338
]),
34-
$this->createBroker()
39+
$this->createBroker(),
40+
$this->reportUnusedCatchesOfUncheckedExceptions
3541
);
3642

3743
return $throwsRule;
@@ -57,6 +63,12 @@ public function testUnusedCatches(): void
5763
$this->analyse(__DIR__ . '/data/unused-catches.php');
5864
}
5965

66+
public function testAllUnusedCatches(): void
67+
{
68+
$this->reportUnusedCatchesOfUncheckedExceptions = true;
69+
$this->analyse(__DIR__ . '/data/unused-catches-all.php');
70+
}
71+
6072
public function testIterators(): void
6173
{
6274
$this->analyse(__DIR__ . '/data/iterators.php');
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Pepakriz\PHPStanExceptionRules\Rules\UnusedCatchesAll;
4+
5+
use LogicException;
6+
use RuntimeException;
7+
8+
class FooException extends RuntimeException
9+
{
10+
11+
}
12+
13+
class UnusedCatches
14+
{
15+
16+
public function nestedUnusedCatch(): void
17+
{
18+
try {
19+
try {
20+
throw new FooException();
21+
} catch (LogicException $e) { // error: LogicException is never thrown in the corresponding try block
22+
23+
} catch (RuntimeException $e) {
24+
25+
}
26+
} catch (FooException $e) { // error: Pepakriz\PHPStanExceptionRules\Rules\UnusedCatchesAll\FooException is never thrown in the corresponding try block
27+
28+
}
29+
}
30+
31+
public function correctCatchMethodCall(): void
32+
{
33+
try {
34+
$this->someVoidMethod();
35+
} catch (LogicException $e) { // error: LogicException is never thrown in the corresponding try block
36+
37+
} catch (RuntimeException $e) { // error: RuntimeException is never thrown in the corresponding try block
38+
39+
}
40+
}
41+
42+
public function correctCatchMethodCallWithThrows(): void
43+
{
44+
try {
45+
$this->throwLogic();
46+
} catch (LogicException $e) {
47+
48+
} catch (RuntimeException $e) { // error: RuntimeException is never thrown in the corresponding try block
49+
50+
}
51+
}
52+
53+
private function someVoidMethod(): void
54+
{
55+
}
56+
57+
/**
58+
* @throws LogicException
59+
*/
60+
private function throwLogic(): void // error: Unused @throws LogicException annotation
61+
{
62+
throw new LogicException();
63+
}
64+
65+
}
66+

tests/src/Rules/data/unused-catches.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,39 @@ public function nestedUnusedCatch(): void
7171
}
7272
}
7373

74+
public function correctCatchMethodCall(): void
75+
{
76+
try {
77+
$this->someVoidMethod();
78+
} catch (LogicException $e) {
79+
80+
} catch (RuntimeException $e) { // error: RuntimeException is never thrown in the corresponding try block
81+
82+
}
83+
}
84+
85+
public function correctCatchMethodCallWithThrows(): void
86+
{
87+
try {
88+
$this->throwLogic();
89+
} catch (LogicException $e) {
90+
91+
} catch (RuntimeException $e) { // error: RuntimeException is never thrown in the corresponding try block
92+
93+
}
94+
}
95+
96+
private function someVoidMethod(): void
97+
{
98+
}
99+
100+
/**
101+
* @throws LogicException
102+
*/
103+
private function throwLogic(): void // error: Unused @throws LogicException annotation
104+
{
105+
throw new LogicException();
106+
}
107+
74108
}
75109

0 commit comments

Comments
 (0)