Skip to content

Commit

Permalink
Bleeding edge - teach CatchWithUnthrownExceptionRule everything what …
Browse files Browse the repository at this point in the history
…DeadCatchRule does
  • Loading branch information
ondrejmirtes committed Sep 11, 2021
1 parent 8cc6e7e commit 165504c
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 5 deletions.
8 changes: 7 additions & 1 deletion conf/config.level4.neon
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ rules:
- PHPStan\Rules\Comparison\NumberComparisonOperatorsConstantConditionRule
- PHPStan\Rules\DeadCode\NoopRule
- PHPStan\Rules\DeadCode\UnreachableStatementRule
- PHPStan\Rules\Exceptions\DeadCatchRule
- PHPStan\Rules\Functions\CallToFunctionStamentWithoutSideEffectsRule
- PHPStan\Rules\Methods\CallToConstructorStatementWithoutSideEffectsRule
- PHPStan\Rules\Methods\CallToMethodStamentWithoutSideEffectsRule
Expand Down Expand Up @@ -153,6 +152,13 @@ services:
-
class: PHPStan\Rules\Exceptions\CatchWithUnthrownExceptionRule

-
class: PHPStan\Rules\Exceptions\DeadCatchRule
arguments:
bleedingEdge: %featureToggles.bleedingEdge%
tags:
- phpstan.rules.rule

-
class: PHPStan\Rules\Exceptions\OverwrittenExitPointByFinallyRule

Expand Down
2 changes: 1 addition & 1 deletion src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -1233,7 +1233,7 @@ private function processStmtNode(
}

if (count($throwableThrowPoints) === 0) {
$nodeCallback(new CatchWithUnthrownExceptionNode($catchNode, $catchType), $scope);
$nodeCallback(new CatchWithUnthrownExceptionNode($catchNode, $catchType, $originalCatchType), $scope);
continue;
}

Expand Down
10 changes: 9 additions & 1 deletion src/Node/CatchWithUnthrownExceptionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ class CatchWithUnthrownExceptionNode extends NodeAbstract implements VirtualNode

private Type $caughtType;

public function __construct(Catch_ $originalNode, Type $caughtType)
private Type $originalCaughtType;

public function __construct(Catch_ $originalNode, Type $caughtType, Type $originalCaughtType)
{
parent::__construct($originalNode->getAttributes());
$this->originalNode = $originalNode;
$this->caughtType = $caughtType;
$this->originalCaughtType = $originalCaughtType;
}

public function getOriginalNode(): Catch_
Expand All @@ -31,6 +34,11 @@ public function getCaughtType(): Type
return $this->caughtType;
}

public function getOriginalCaughtType(): Type
{
return $this->originalCaughtType;
}

public function getType(): string
{
return 'PHPStan_Node_CatchWithUnthrownExceptionNode';
Expand Down
9 changes: 9 additions & 0 deletions src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PHPStan\Node\CatchWithUnthrownExceptionNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\NeverType;
use PHPStan\Type\VerbosityLevel;

/**
Expand All @@ -22,6 +23,14 @@ public function getNodeType(): string

public function processNode(Node $node, Scope $scope): array
{
if ($node->getCaughtType() instanceof NeverType) {
return [
RuleErrorBuilder::message(
sprintf('Dead catch - %s is already caught above.', $node->getOriginalCaughtType()->describe(VerbosityLevel::typeOnly()))
)->line($node->getLine())->build(),
];
}

return [
RuleErrorBuilder::message(
sprintf('Dead catch - %s is never thrown in the try block.', $node->getCaughtType()->describe(VerbosityLevel::typeOnly()))
Expand Down
11 changes: 11 additions & 0 deletions src/Rules/Exceptions/DeadCatchRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,24 @@
class DeadCatchRule implements Rule
{

private bool $bleedingEdge;

public function __construct(bool $bleedingEdge = false)
{
$this->bleedingEdge = $bleedingEdge;
}

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

public function processNode(Node $node, Scope $scope): array
{
if ($this->bleedingEdge) {
return [];
}

$catchTypes = array_map(static function (Node\Stmt\Catch_ $catch): Type {
return TypeCombinator::union(...array_map(static function (Node\Name $className): ObjectType {
return new ObjectType($className->toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,14 @@ public function testThrowExpression(): void
]);
}

public function testDeadCatch(): void
{
$this->analyse([__DIR__ . '/data/dead-catch.php'], [
[
'Dead catch - TypeError is already caught above.',
27,
],
]);
}

}
4 changes: 2 additions & 2 deletions tests/PHPStan/Rules/Exceptions/data/dead-catch.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Foo
public function doFoo()
{
try {

doFoo();
} catch (\Exception $e) {

} catch (\TypeError $e) {
Expand All @@ -21,7 +21,7 @@ public function doFoo()
public function doBar()
{
try {

doFoo();
} catch (\Throwable $e) {

} catch (\TypeError $e) {
Expand Down

0 comments on commit 165504c

Please sign in to comment.