1: | <?php declare(strict_types = 1); |
2: | |
3: | namespace PHPStan\Rules\Exceptions; |
4: | |
5: | use Nette\Utils\Strings; |
6: | use PHPStan\Analyser\Scope; |
7: | use PHPStan\Reflection\ReflectionProvider; |
8: | use function count; |
9: | |
10: | |
11: | class DefaultExceptionTypeResolver implements ExceptionTypeResolver |
12: | { |
13: | |
14: | |
15: | |
16: | |
17: | |
18: | |
19: | |
20: | public function __construct( |
21: | private ReflectionProvider $reflectionProvider, |
22: | private array $uncheckedExceptionRegexes, |
23: | private array $uncheckedExceptionClasses, |
24: | private array $checkedExceptionRegexes, |
25: | private array $checkedExceptionClasses, |
26: | ) |
27: | { |
28: | } |
29: | |
30: | public function isCheckedException(string $className, Scope $scope): bool |
31: | { |
32: | foreach ($this->uncheckedExceptionRegexes as $regex) { |
33: | if (Strings::match($className, $regex) !== null) { |
34: | return false; |
35: | } |
36: | } |
37: | |
38: | foreach ($this->uncheckedExceptionClasses as $uncheckedExceptionClass) { |
39: | if ($className === $uncheckedExceptionClass) { |
40: | return false; |
41: | } |
42: | } |
43: | |
44: | if (!$this->reflectionProvider->hasClass($className)) { |
45: | return $this->isCheckedExceptionInternal($className); |
46: | } |
47: | |
48: | $classReflection = $this->reflectionProvider->getClass($className); |
49: | foreach ($this->uncheckedExceptionClasses as $uncheckedExceptionClass) { |
50: | if ($classReflection->getName() === $uncheckedExceptionClass) { |
51: | return false; |
52: | } |
53: | |
54: | if (!$classReflection->isSubclassOf($uncheckedExceptionClass)) { |
55: | continue; |
56: | } |
57: | |
58: | return false; |
59: | } |
60: | |
61: | return $this->isCheckedExceptionInternal($className); |
62: | } |
63: | |
64: | private function isCheckedExceptionInternal(string $className): bool |
65: | { |
66: | foreach ($this->checkedExceptionRegexes as $regex) { |
67: | if (Strings::match($className, $regex) !== null) { |
68: | return true; |
69: | } |
70: | } |
71: | |
72: | foreach ($this->checkedExceptionClasses as $checkedExceptionClass) { |
73: | if ($className === $checkedExceptionClass) { |
74: | return true; |
75: | } |
76: | } |
77: | |
78: | if (!$this->reflectionProvider->hasClass($className)) { |
79: | return count($this->checkedExceptionRegexes) === 0 && count($this->checkedExceptionClasses) === 0; |
80: | } |
81: | |
82: | $classReflection = $this->reflectionProvider->getClass($className); |
83: | foreach ($this->checkedExceptionClasses as $checkedExceptionClass) { |
84: | if ($classReflection->getName() === $checkedExceptionClass) { |
85: | return true; |
86: | } |
87: | |
88: | if (!$classReflection->isSubclassOf($checkedExceptionClass)) { |
89: | continue; |
90: | } |
91: | |
92: | return true; |
93: | } |
94: | |
95: | return count($this->checkedExceptionRegexes) === 0 && count($this->checkedExceptionClasses) === 0; |
96: | } |
97: | |
98: | } |
99: | |