Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix CatchWithUnthrownExceptionRule for $expr::foo()
  • Loading branch information
ondrejmirtes committed Apr 5, 2021
1 parent 8463afd commit 8c7cf85
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/Analyser/NodeScopeResolver.php
Expand Up @@ -1995,9 +1995,23 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
$hasYield = false;
$throwPoints = [];
if ($expr->class instanceof Expr) {
$objectClasses = TypeUtils::getDirectClassNames($scope->getType($expr->class));
if (count($objectClasses) !== 1) {
$objectClasses = TypeUtils::getDirectClassNames($scope->getType(new New_($expr->class)));
}
if (count($objectClasses) === 1) {
$objectExprResult = $this->processExprNode(new StaticCall(new Name($objectClasses[0]), $expr->name, []), $scope, static function (): void {
}, $context->enterDeep());
$additionalThrowPoints = $objectExprResult->getThrowPoints();
} else {
$additionalThrowPoints = [ThrowPoint::createImplicit($scope)];
}
$classResult = $this->processExprNode($expr->class, $scope, $nodeCallback, $context->enterDeep());
$hasYield = $classResult->hasYield();
$throwPoints = array_merge($throwPoints, $classResult->getThrowPoints());
foreach ($additionalThrowPoints as $throwPoint) {
$throwPoints[] = $throwPoint;
}
$scope = $classResult->getScope();
}

Expand Down
Expand Up @@ -68,4 +68,18 @@ public function testBug4806(): void
]);
}

public function testBug4805(): void
{
$this->analyse([__DIR__ . '/data/bug-4805.php'], [
[
'Dead catch - OutOfBoundsException is never thrown in the try block.',
44,
],
[
'Dead catch - OutOfBoundsException is never thrown in the try block.',
66,
],
]);
}

}
112 changes: 112 additions & 0 deletions tests/PHPStan/Rules/Exceptions/data/bug-4805.php
@@ -0,0 +1,112 @@
<?php

namespace Bug4805;

final class Foo
{
/**
* @throws \OutOfBoundsException
*/
public static function canThrow(bool $throw): self
{
if($throw){
throw new \OutOfBoundsException('Ooops');
}
return new self();
}

/**
* @throws void
*/
public static function cannotThrow(bool $throw): void
{

}
}

final class Bar
{
public static function doFoo(Foo $foo, bool $flag): bool
{
try{
$foo::canThrow($flag);
return true;
}catch(\OutOfBoundsException $e){
return false;
}
}

public static function doFoo2(Foo $foo, bool $flag): bool
{
try{
$foo::cannotThrow($flag);
return true;
}catch(\OutOfBoundsException $e){
return false;
}
}

/** @param class-string<Foo> $foo */
public static function doBar(string $foo, bool $flag): bool
{
try{
$foo::canThrow($flag);
return true;
} catch(\OutOfBoundsException $e){
return false;
}
}

/** @param class-string<Foo> $foo */
public static function doBar2(string $foo, bool $flag): bool
{
try{
$foo::cannotThrow($flag);
return true;
} catch(\OutOfBoundsException $e){
return false;
}
}

/** @param class-string $foo */
public static function doBaz(string $foo, bool $flag): bool
{
try{
$foo::canThrow($flag);
return true;
} catch(\OutOfBoundsException $e){
return false;
}
}

/** @param class-string $foo */
public static function doBaz2(string $foo, bool $flag): bool
{
try{
$foo::cannotThrow($flag);
return true;
} catch(\OutOfBoundsException $e){
return false;
}
}

public static function doLorem(string $foo, bool $flag): bool
{
try{
$foo::canThrow($flag);
return true;
} catch(\OutOfBoundsException $e){
return false;
}
}

public static function doLorem2(string $foo, bool $flag): bool
{
try{
$foo::cannotThrow($flag);
return true;
} catch(\OutOfBoundsException $e){
return false;
}
}
}

0 comments on commit 8c7cf85

Please sign in to comment.