Skip to content

Commit

Permalink
Add NoncapturingCatchRule
Browse files Browse the repository at this point in the history
  • Loading branch information
paulbalandan committed Nov 9, 2023
1 parent 62107a9 commit 14d32de
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 0 deletions.
1 change: 1 addition & 0 deletions conf/config.level0.neon
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ rules:
- PHPStan\Rules\Constants\FinalConstantRule
- PHPStan\Rules\Constants\NativeTypedClassConstantRule
- PHPStan\Rules\EnumCases\EnumCaseAttributesRule
- PHPStan\Rules\Exceptions\NoncapturingCatchRule
- PHPStan\Rules\Exceptions\ThrowExpressionRule
- PHPStan\Rules\Functions\ArrowFunctionAttributesRule
- PHPStan\Rules\Functions\ArrowFunctionReturnNullsafeByRefRule
Expand Down
5 changes: 5 additions & 0 deletions src/Php/PhpVersion.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public function supportsReturnCovariance(): bool
return $this->versionId >= 70400;
}

public function supportsNoncapturingCatches(): bool
{
return $this->versionId >= 80000;
}

public function supportsNativeUnionTypes(): bool
{
return $this->versionId >= 80000;
Expand Down
46 changes: 46 additions & 0 deletions src/Rules/Exceptions/NoncapturingCatchRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Exceptions;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;

/**
* @implements Rule<Node\Stmt\Catch_>
*/
class NoncapturingCatchRule implements Rule
{

public function __construct(private PhpVersion $phpVersion)
{
}

public function getNodeType(): string
{
return Node\Stmt\Catch_::class;
}

/**
* @param Node\Stmt\Catch_ $node
*/
public function processNode(Node $node, Scope $scope): array
{
if ($this->phpVersion->supportsNoncapturingCatches()) {
return [];
}

if ($node->var !== null) {
return [];
}

return [
RuleErrorBuilder::message('Non-capturing catch is supported only on PHP 8.0 and later.')
->nonIgnorable()
->build(),
];
}

}
60 changes: 60 additions & 0 deletions tests/PHPStan/Rules/Exceptions/NoncapturingCatchRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Exceptions;

use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;

/**
* @extends RuleTestCase<NoncapturingCatchRule>
*/
class NoncapturingCatchRuleTest extends RuleTestCase
{

private PhpVersion $phpVersion;

protected function getRule(): Rule
{
return new NoncapturingCatchRule($this->phpVersion);
}

public function dataRule(): array
{
return [
[
70400,
[
[
'Non-capturing catch is supported only on PHP 8.0 and later.',
12,
],
[
'Non-capturing catch is supported only on PHP 8.0 and later.',
21,
],
],
],
[
80000,
[],
],
];
}

/**
* @dataProvider dataRule
*
* @param list<array{0: string, 1: int, 2?: string}> $expectedErrors
*/
public function testRule(int $phpVersion, array $expectedErrors): void
{
$this->phpVersion = new PhpVersion($phpVersion);

$this->analyse([
__DIR__ . '/data/noncapturing-catch.php',
__DIR__ . '/data/bug-8663.php',
], $expectedErrors);
}

}
25 changes: 25 additions & 0 deletions tests/PHPStan/Rules/Exceptions/data/bug-8663.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php // lint >= 8.0

namespace Bug8663;

/**
* Provides example to demonstrate an issue with PHPStan.
*/
class StanExample2
{

/**
* An exception is caught but not captured.
*
* That's OK for PHP 8 but not for 7.4 - PHPStan does not report the issue.
*/
public function catchExceptionsWithoutCapturing(): void
{
try {
print 'Lets do something nasty here.';
throw new \Exception('This is nasty');
} catch (\Exception) {
print 'Exception occured';
}
}
}
17 changes: 17 additions & 0 deletions tests/PHPStan/Rules/Exceptions/data/noncapturing-catch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php // lint >= 8.0

namespace NoncapturingCatch;

class HelloWorld
{

public function hello(): void
{
try {
throw new \Exception('Hello');
} catch (\Exception) {
echo 'Hi!';
}
}

}

0 comments on commit 14d32de

Please sign in to comment.