Skip to content

Commit

Permalink
add stubs for min/max (#5353)
Browse files Browse the repository at this point in the history
  • Loading branch information
orklah authored Mar 11, 2021
1 parent 9793f92 commit 0a4ad57
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public function __construct()
$this->registerClass(ReturnTypeProvider\GetClassMethodsReturnTypeProvider::class);
$this->registerClass(ReturnTypeProvider\FirstArgStringReturnTypeProvider::class);
$this->registerClass(ReturnTypeProvider\HexdecReturnTypeProvider::class);
$this->registerClass(ReturnTypeProvider\MinMaxReturnTypeProvider::class);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php declare(strict_types=1);

namespace Psalm\Internal\Provider\ReturnTypeProvider;

use Psalm\Plugin\EventHandler\Event\FunctionReturnTypeProviderEvent;
use Psalm\Plugin\EventHandler\FunctionReturnTypeProviderInterface;
use function count;
use Psalm\Internal\Type\ArrayType;
use Psalm\Type;

class MinMaxReturnTypeProvider implements FunctionReturnTypeProviderInterface
{
/**
* @return array<lowercase-string>
*/
public static function getFunctionIds(): array
{
return ['min', 'max'];
}

public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $event): ?Type\Union
{
$call_args = $event->getCallArgs();
if (count($call_args) === 0) {
return null;
}

$statements_source = $event->getStatementsSource();
$nodeTypeProvider = $statements_source->getNodeTypeProvider();

if (count($call_args) === 1
&& ($array_arg_type = $nodeTypeProvider->getType($call_args[0]->value))
&& $array_arg_type->isSingle()
&& $array_arg_type->hasArray()
&& ($array_type = ArrayType::infer($array_arg_type->getAtomicTypes()['array']))
) {
return $array_type->value;
}

$atomics = [];
foreach ($call_args as $arg) {
if ($array_arg_type = $nodeTypeProvider->getType($arg->value)) {
foreach ($array_arg_type->getAtomicTypes() as $atomicType) {
$atomics[] = $atomicType;
}
} else {
return Type::getMixed();
}
}

if ($atomics === []) {
return Type::getMixed();
}

return new Type\Union($atomics);
}
}
30 changes: 30 additions & 0 deletions tests/FunctionCallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,29 @@ function safe_float(mixed $val): bool {
[],
'8.0'
],
'maxWithFloats' => [
'<?php
function foo(float $_float): void
{}
foo(max(1.1, 1.2));',
],
'maxWithObjects' => [
'<?php
function foo(DateTimeImmutable $fooDate): string
{
return $fooDate->format("Y");
}
foo(max(new DateTimeImmutable(), new DateTimeImmutable()));',
],
'maxWithMisc' => [
'<?php
$a = max(new DateTimeImmutable(), 1.2);',
[
'$a' => 'DateTimeImmutable|float',
],
],
];
}

Expand Down Expand Up @@ -2055,6 +2078,13 @@ function foo(string $s) {
}',
'error_message' => 'InvalidReturnStatement'
],
'maxWithMixed' => [
'<?php
/** @var mixed $b */;
/** @var mixed $c */;
$a = max($b, $c);',
'error_message' => 'MixedAssignment'
],
];
}
}

0 comments on commit 0a4ad57

Please sign in to comment.