Skip to content

Commit

Permalink
Dynamic "assert" throw type extension
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickkusebauch committed May 31, 2023
1 parent 36fb382 commit fd3aa73
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 0 deletions.
5 changes: 5 additions & 0 deletions conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,11 @@ services:
tags:
- phpstan.broker.dynamicFunctionReturnTypeExtension

-
class: PHPStan\Type\Php\AssertThrowTypeExtension
tags:
- phpstan.dynamicFunctionThrowTypeExtension

-
class: PHPStan\Type\Php\BackedEnumFromMethodDynamicReturnTypeExtension
tags:
Expand Down
36 changes: 36 additions & 0 deletions src/Type/Php/AssertThrowTypeExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php declare(strict_types = 1);

namespace PHPStan\Type\Php;

use PhpParser\Node\Expr\FuncCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\DynamicFunctionThrowTypeExtension;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Throwable;
use function count;

class AssertThrowTypeExtension implements DynamicFunctionThrowTypeExtension
{

public function isFunctionSupported(FunctionReflection $functionReflection): bool
{
return $functionReflection->getName() === 'assert';
}

public function getThrowTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, Scope $scope): ?Type
{
if (count($funcCall->getArgs()) < 2) {
return $functionReflection->getThrowType();
}

$customThrow = $scope->getType($funcCall->getArgs()[1]->value);
if ((new ObjectType(Throwable::class))->isSuperTypeOf($customThrow)->yes()) {
return $customThrow;
}

return $functionReflection->getThrowType();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -475,4 +475,18 @@ public function testMagicMethods(): void
]);
}

public function testBug5650(): void
{
$this->analyse([__DIR__ . '/data/bug-5650.php'], [
[
'Dead catch - RuntimeException is never thrown in the try block.',
24,
],
[
'Dead catch - RuntimeException is never thrown in the try block.',
32,
],
]);
}

}
35 changes: 35 additions & 0 deletions tests/PHPStan/Rules/Exceptions/data/bug-5650.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Bug5650;

function (): void {
try {
assert(false, new RuntimeException("I am being thrown"));
} catch (\RuntimeException $e) {

}
};

function (): void {
try {
assert(true, new RuntimeException("I could be but this time am not being thrown"));
} catch (\RuntimeException $e) {

}
};

function (): void {
try {
assert(false);
} catch (\RuntimeException $e) {

}
};

function (): void {
try {
assert(true);
} catch (\RuntimeException $e) {

}
};

0 comments on commit fd3aa73

Please sign in to comment.