Skip to content

Commit

Permalink
date function can sometimes return numeric string
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Aug 25, 2020
1 parent 25da584 commit 1053ee7
Show file tree
Hide file tree
Showing 4 changed files with 80 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 @@ -790,6 +790,11 @@ services:
tags:
- phpstan.broker.dynamicFunctionReturnTypeExtension

-
class: PHPStan\Type\Php\DateFunctionReturnTypeExtension
tags:
- phpstan.broker.dynamicFunctionReturnTypeExtension

-
class: PHPStan\Type\Php\DsMapDynamicReturnTypeExtension
tags:
Expand Down
51 changes: 51 additions & 0 deletions src/Type/Php/DateFunctionReturnTypeExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?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\Accessory\AccessoryNumericStringType;
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeUtils;

class DateFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension
{

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

public function getTypeFromFunctionCall(
FunctionReflection $functionReflection,
FuncCall $functionCall,
Scope $scope
): Type
{
if (count($functionCall->args) === 0) {
return new StringType();
}
$argType = $scope->getType($functionCall->args[0]->value);
$constantStrings = TypeUtils::getConstantStrings($argType);
if (count($constantStrings) === 0) {
return new StringType();
}

foreach ($constantStrings as $constantString) {
$formattedDate = date($constantString->getValue());
if (!is_numeric($formattedDate)) {
return new StringType();
}
}

return new IntersectionType([
new StringType(),
new AccessoryNumericStringType(),
]);
}

}
6 changes: 6 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10043,6 +10043,11 @@ public function dataBug2550(): array
return $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/bug-2550.php');
}

public function dataBug2899(): array
{
return $this->gatherAssertTypes(__DIR__ . '/data/bug-2899.php');
}

/**
* @dataProvider dataBug2574
* @dataProvider dataBug2577
Expand Down Expand Up @@ -10110,6 +10115,7 @@ public function dataBug2550(): array
* @dataProvider dataNonEmptyArrayKeyType
* @dataProvider dataBug3133
* @dataProvider dataBug2550
* @dataProvider dataBug2899
* @param string $assertType
* @param string $file
* @param mixed ...$args
Expand Down
18 changes: 18 additions & 0 deletions tests/PHPStan/Analyser/data/bug-2899.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Bug2899;

use function PHPStan\Analyser\assertType;

class Foo
{

public function doFoo(string $s, $mixed)
{
assertType('string&numeric', date('Y'));
assertType('string', date('Y.m.d'));
assertType('string', date($s));
assertType('string', date($mixed));
}

}

0 comments on commit 1053ee7

Please sign in to comment.