Skip to content

Commit

Permalink
Improve Exception::getCode() type
Browse files Browse the repository at this point in the history
See discussion: #795 (comment)
  • Loading branch information
ondrejmirtes committed Jan 6, 2022
1 parent cae07c8 commit 1181717
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 4 deletions.
35 changes: 34 additions & 1 deletion src/Type/Php/ThrowableReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@

namespace PHPStan\Type\Php;

use PDOException;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\BenevolentUnionType;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\ErrorType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeUtils;
use Throwable;
use function count;
use function in_array;
use function strtolower;

final class ThrowableReturnTypeExtension implements DynamicMethodReturnTypeExtension
{
Expand All @@ -27,7 +35,32 @@ public function isMethodSupported(MethodReflection $methodReflection): bool

public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
{
return new BenevolentUnionType([new IntegerType(), new StringType()]);
$type = $scope->getType($methodCall->var);
$types = [];
$pdoException = new ObjectType(PDOException::class);
foreach (TypeUtils::getDirectClassNames($type) as $class) {
$classType = new ObjectType($class);
if ($pdoException->isSuperTypeOf($classType)->yes()) {
$types[] = new StringType();
continue;
}

if (in_array(strtolower($class), [
'throwable',
'exception',
], true)) {
$types[] = new BenevolentUnionType([new IntegerType(), new StringType()]);
continue;
}

$types[] = new IntegerType();
}

if (count($types) === 0) {
return new ErrorType();
}

return TypeCombinator::union(...$types);
}

}
34 changes: 31 additions & 3 deletions tests/PHPStan/Analyser/data/bug-6001.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,36 @@

use function PHPStan\Testing\assertType;

assertType('(int|string)', (new \Exception())->getCode());
class Foo
{

assertType('(int|string)', (new \RuntimeException())->getCode());
public function doFoo(\Throwable $t): void
{
assertType('(int|string)', (new \Exception())->getCode());
assertType('(int|string)', $t->getCode());
assertType('int', (new \RuntimeException())->getCode());
assertType('string', (new \PDOException())->getCode());
assertType('int', (new MyException())->getCode());
assertType('string', (new SubPDOException())->getCode());
}

assertType('(int|string)', (new \PDOException())->getCode());
/**
* @param \PDOException|MyException $exception
* @return void
*/
public function doBar($exception): void
{
assertType('int|string', $exception->getCode());
}

}

class MyException extends \Exception
{

}

class SubPDOException extends \PDOException
{

}

0 comments on commit 1181717

Please sign in to comment.