mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Improve return types of explode() with limit (#2286)
This commit is contained in:
parent
a82e35a59f
commit
b229ac875d
@ -249,20 +249,30 @@ class FunctionAnalyzer extends FunctionLikeAnalyzer
|
||||
break;
|
||||
|
||||
case 'explode':
|
||||
if (count($call_args) === 2) {
|
||||
if (count($call_args) >= 2) {
|
||||
$can_return_empty = isset($call_args[2])
|
||||
&& (
|
||||
!$call_args[2]->value instanceof PhpParser\Node\Scalar\LNumber
|
||||
|| $call_args[2]->value->value < 0
|
||||
);
|
||||
|
||||
if ($call_args[0]->value instanceof PhpParser\Node\Scalar\String_) {
|
||||
if ($call_args[0]->value->value === '') {
|
||||
return Type::getFalse();
|
||||
}
|
||||
|
||||
return new Type\Union([
|
||||
new Type\Atomic\TNonEmptyList(Type::getString())
|
||||
$can_return_empty
|
||||
? new Type\Atomic\TList(Type::getString())
|
||||
: new Type\Atomic\TNonEmptyList(Type::getString())
|
||||
]);
|
||||
} elseif (isset($call_args[0]->value->inferredType)
|
||||
&& $call_args[0]->value->inferredType->hasString()
|
||||
) {
|
||||
$falsable_array = new Type\Union([
|
||||
new Type\Atomic\TNonEmptyList(Type::getString()),
|
||||
$can_return_empty
|
||||
? new Type\Atomic\TList(Type::getString())
|
||||
: new Type\Atomic\TNonEmptyList(Type::getString()),
|
||||
new Type\Atomic\TFalse
|
||||
]);
|
||||
|
||||
|
@ -945,19 +945,93 @@ class FunctionCallTest extends TestCase
|
||||
'$c' => 'int',
|
||||
],
|
||||
],
|
||||
'explode' => [
|
||||
'<?php
|
||||
/** @var string $string */
|
||||
$elements = explode(" ", $string);',
|
||||
'assertions' => [
|
||||
'$elements' => 'non-empty-list<string>',
|
||||
],
|
||||
],
|
||||
'explodeWithPositiveLimit' => [
|
||||
'<?php
|
||||
/** @var string $string */
|
||||
$elements = explode(" ", $string, 5);',
|
||||
'assertions' => [
|
||||
'$elements' => 'non-empty-list<string>',
|
||||
],
|
||||
],
|
||||
'explodeWithNegativeLimit' => [
|
||||
'<?php
|
||||
/** @var string $string */
|
||||
$elements = explode(" ", $string, -5);',
|
||||
'assertions' => [
|
||||
'$elements' => 'list<string>',
|
||||
],
|
||||
],
|
||||
'explodeWithDynamicLimit' => [
|
||||
'<?php
|
||||
/**
|
||||
* @var string $string
|
||||
* @var int $limit
|
||||
*/
|
||||
$elements = explode(" ", $string, $limit);',
|
||||
'assertions' => [
|
||||
'$elements' => 'list<string>',
|
||||
],
|
||||
],
|
||||
'explodeWithDynamicDelimiter' => [
|
||||
'<?php
|
||||
/**
|
||||
* @var string $delim
|
||||
* @var string $string
|
||||
*/
|
||||
$elements = explode($delim, $string);',
|
||||
'assertions' => [
|
||||
'$elements' => 'false|non-empty-list<string>',
|
||||
],
|
||||
],
|
||||
'explodeWithDynamicDelimiterAndPositiveLimit' => [
|
||||
'<?php
|
||||
/**
|
||||
* @var string $delim
|
||||
* @var string $string
|
||||
*/
|
||||
$elements = explode($delim, $string, 5);',
|
||||
'assertions' => [
|
||||
'$elements' => 'false|non-empty-list<string>',
|
||||
],
|
||||
],
|
||||
'explodeWithDynamicDelimiterAndNegativeLimit' => [
|
||||
'<?php
|
||||
/**
|
||||
* @var string $delim
|
||||
* @var string $string
|
||||
*/
|
||||
$elements = explode($delim, $string, -5);',
|
||||
'assertions' => [
|
||||
'$elements' => 'false|list<string>',
|
||||
],
|
||||
],
|
||||
'explodeWithDynamicDelimiterAndLimit' => [
|
||||
'<?php
|
||||
/**
|
||||
* @var string $delim
|
||||
* @var string $string
|
||||
* @var int $limit
|
||||
*/
|
||||
$elements = explode($delim, $string, $limit);',
|
||||
'assertions' => [
|
||||
'$elements' => 'false|list<string>',
|
||||
],
|
||||
],
|
||||
'explodeWithPossiblyFalse' => [
|
||||
'<?php
|
||||
/** @return array<int, string> */
|
||||
function exploder(string $s) : array {
|
||||
return explode(" ", $s);
|
||||
/** @return non-empty-list<string> */
|
||||
function exploder(string $d, string $s) : array {
|
||||
return explode($d, $s);
|
||||
}',
|
||||
],
|
||||
'explodeWithThirdArg' => [
|
||||
'<?php
|
||||
$elements = explode("_", "", -1);
|
||||
$element = array_shift($elements);
|
||||
assert(null !== $element);'
|
||||
],
|
||||
'allowPossiblyUndefinedClassInClassExists' => [
|
||||
'<?php
|
||||
if (class_exists(Foo::class)) {}',
|
||||
|
Loading…
Reference in New Issue
Block a user