From 84ea0e143ccfd200dbeda9af1ee6ae35941ae4aa Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sun, 16 May 2021 18:31:07 +0200 Subject: [PATCH] Add DateInterval extension --- conf/config.neon | 5 +++ ...eIntervalConstructorThrowTypeExtension.php | 44 +++++++++++++++++++ .../CatchWithUnthrownExceptionRuleTest.php | 4 ++ .../Exceptions/data/unthrown-exception.php | 32 ++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 src/Type/Php/DateIntervalConstructorThrowTypeExtension.php diff --git a/conf/config.neon b/conf/config.neon index ec7c856c02..f3356e36c0 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -1027,6 +1027,11 @@ services: tags: - phpstan.broker.dynamicFunctionReturnTypeExtension + - + class: PHPStan\Type\Php\DateIntervalConstructorThrowTypeExtension + tags: + - phpstan.dynamicStaticMethodThrowTypeExtension + - class: PHPStan\Type\Php\DateTimeDynamicReturnTypeExtension tags: diff --git a/src/Type/Php/DateIntervalConstructorThrowTypeExtension.php b/src/Type/Php/DateIntervalConstructorThrowTypeExtension.php new file mode 100644 index 0000000000..ee6dbe9cbc --- /dev/null +++ b/src/Type/Php/DateIntervalConstructorThrowTypeExtension.php @@ -0,0 +1,44 @@ +getName() === '__construct' && $methodReflection->getDeclaringClass()->getName() === DateInterval::class; + } + + public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): ?Type + { + if (count($methodCall->args) === 0) { + return $methodReflection->getThrowType(); + } + + $arg = $methodCall->args[0]->value; + $constantStrings = TypeUtils::getConstantStrings($scope->getType($arg)); + if (count($constantStrings) === 0) { + return $methodReflection->getThrowType(); + } + + foreach ($constantStrings as $constantString) { + try { + new \DateInterval($constantString->getValue()); + } catch (\Exception $e) { // phpcs:ignore + return $methodReflection->getThrowType(); + } + } + + return null; + } + +} diff --git a/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php b/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php index d54f183ba3..cc5d38d567 100644 --- a/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php +++ b/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php @@ -59,6 +59,10 @@ public function testRule(): void 'Dead catch - Exception is never thrown in the try block.', 180, ], + [ + 'Dead catch - Exception is never thrown in the try block.', + 212, + ], ]); } diff --git a/tests/PHPStan/Rules/Exceptions/data/unthrown-exception.php b/tests/PHPStan/Rules/Exceptions/data/unthrown-exception.php index 7b3b4a1289..b8abd13e60 100644 --- a/tests/PHPStan/Rules/Exceptions/data/unthrown-exception.php +++ b/tests/PHPStan/Rules/Exceptions/data/unthrown-exception.php @@ -192,3 +192,35 @@ public function doBaz(string $s): void } } + +class TestDateInterval +{ + + public function doFoo(): void + { + try { + new \DateInterval('invalid format'); + } catch (\Exception $e) { + + } + } + + public function doBar(): void + { + try { + new \DateInterval('P10D'); + } catch (\Exception $e) { + + } + } + + public function doBaz(string $s): void + { + try { + new \DateInterval($s); + } catch (\Exception $e) { + + } + } + +}