2
2
3
3
namespace PHPStan \Type \Php ;
4
4
5
+ use PDOException ;
5
6
use PhpParser \Node \Expr \MethodCall ;
6
7
use PHPStan \Analyser \Scope ;
7
8
use PHPStan \Reflection \MethodReflection ;
8
9
use PHPStan \Type \BenevolentUnionType ;
9
10
use PHPStan \Type \DynamicMethodReturnTypeExtension ;
11
+ use PHPStan \Type \ErrorType ;
10
12
use PHPStan \Type \IntegerType ;
13
+ use PHPStan \Type \ObjectType ;
11
14
use PHPStan \Type \StringType ;
12
15
use PHPStan \Type \Type ;
16
+ use PHPStan \Type \TypeCombinator ;
17
+ use PHPStan \Type \TypeUtils ;
13
18
use Throwable ;
19
+ use function count ;
20
+ use function in_array ;
21
+ use function strtolower ;
14
22
15
23
final class ThrowableReturnTypeExtension implements DynamicMethodReturnTypeExtension
16
24
{
@@ -27,7 +35,32 @@ public function isMethodSupported(MethodReflection $methodReflection): bool
27
35
28
36
public function getTypeFromMethodCall (MethodReflection $ methodReflection , MethodCall $ methodCall , Scope $ scope ): Type
29
37
{
30
- return new BenevolentUnionType ([new IntegerType (), new StringType ()]);
38
+ $ type = $ scope ->getType ($ methodCall ->var );
39
+ $ types = [];
40
+ $ pdoException = new ObjectType (PDOException::class);
41
+ foreach (TypeUtils::getDirectClassNames ($ type ) as $ class ) {
42
+ $ classType = new ObjectType ($ class );
43
+ if ($ pdoException ->isSuperTypeOf ($ classType )->yes ()) {
44
+ $ types [] = new StringType ();
45
+ continue ;
46
+ }
47
+
48
+ if (in_array (strtolower ($ class ), [
49
+ 'throwable ' ,
50
+ 'exception ' ,
51
+ ], true )) {
52
+ $ types [] = new BenevolentUnionType ([new IntegerType (), new StringType ()]);
53
+ continue ;
54
+ }
55
+
56
+ $ types [] = new IntegerType ();
57
+ }
58
+
59
+ if (count ($ types ) === 0 ) {
60
+ return new ErrorType ();
61
+ }
62
+
63
+ return TypeCombinator::union (...$ types );
31
64
}
32
65
33
66
}
0 commit comments