From 0c82b3a2675f636db920a0a3e077a45a87200766 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Feb 2022 13:28:24 +0100 Subject: [PATCH] Fix DatePeriod constructor extension in subclasses --- .../DatePeriodConstructorReturnTypeExtension.php | 11 +++++++++++ tests/PHPStan/Analyser/NodeScopeResolverTest.php | 2 ++ tests/PHPStan/Analyser/data/bug-6500.php | 14 ++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 tests/PHPStan/Analyser/data/bug-6500.php diff --git a/src/Type/Php/DatePeriodConstructorReturnTypeExtension.php b/src/Type/Php/DatePeriodConstructorReturnTypeExtension.php index ddcc4929d7..8b52604f48 100644 --- a/src/Type/Php/DatePeriodConstructorReturnTypeExtension.php +++ b/src/Type/Php/DatePeriodConstructorReturnTypeExtension.php @@ -6,6 +6,7 @@ use DateTime; use DateTimeInterface; use PhpParser\Node\Expr\StaticCall; +use PhpParser\Node\Name; use PHPStan\Analyser\Scope; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\DynamicStaticMethodReturnTypeExtension; @@ -15,6 +16,7 @@ use PHPStan\Type\ObjectType; use PHPStan\Type\StringType; use PHPStan\Type\Type; +use function strtolower; class DatePeriodConstructorReturnTypeExtension implements DynamicStaticMethodReturnTypeExtension { @@ -35,6 +37,15 @@ public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, return new ObjectType(DatePeriod::class); } + if (!$methodCall->class instanceof Name) { + return new ObjectType(DatePeriod::class); + } + + $className = $scope->resolveName($methodCall->class); + if (strtolower($className) !== 'dateperiod') { + return new ObjectType($className); + } + $firstArgType = $scope->getType($methodCall->getArgs()[0]->value); if ((new StringType())->isSuperTypeOf($firstArgType)->yes()) { $firstArgType = new ObjectType(DateTime::class); diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index ee750d68d8..e7d7639a99 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -678,6 +678,8 @@ public function dataFileAsserts(): iterable } else { yield from $this->gatherAssertTypes(__DIR__ . '/data/hash-functions-74.php'); } + + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6500.php'); } /** diff --git a/tests/PHPStan/Analyser/data/bug-6500.php b/tests/PHPStan/Analyser/data/bug-6500.php new file mode 100644 index 0000000000..d6a1be8fc1 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-6500.php @@ -0,0 +1,14 @@ +