mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 05:41:20 +01:00
Fix #2808 - improve yield type discernment
This commit is contained in:
parent
bacc7f254c
commit
d3bfb96431
@ -2,6 +2,7 @@
|
|||||||
namespace Psalm\Internal\Analyzer\FunctionLike;
|
namespace Psalm\Internal\Analyzer\FunctionLike;
|
||||||
|
|
||||||
use PhpParser;
|
use PhpParser;
|
||||||
|
use Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer;
|
||||||
use Psalm\Type;
|
use Psalm\Type;
|
||||||
use Psalm\Type\Atomic;
|
use Psalm\Type\Atomic;
|
||||||
use function array_merge;
|
use function array_merge;
|
||||||
@ -262,29 +263,9 @@ class ReturnTypeCollector
|
|||||||
$type = new Type\Atomic\TArray([Type::getInt(), $type->type_param]);
|
$type = new Type\Atomic\TArray([Type::getInt(), $type->type_param]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($type instanceof Type\Atomic\TArray
|
if ($type instanceof Type\Atomic\TArray) {
|
||||||
|| $type instanceof Type\Atomic\TIterable
|
$key_type_param = $type->type_params[0];
|
||||||
|| ($type instanceof Type\Atomic\TGenericObject
|
$value_type_param = $type->type_params[1];
|
||||||
&& ($codebase->classImplements(
|
|
||||||
$type->value,
|
|
||||||
'Iterator'
|
|
||||||
)
|
|
||||||
|| $codebase->classImplements(
|
|
||||||
$type->value,
|
|
||||||
'IteratorAggregate'
|
|
||||||
)
|
|
||||||
|| $type->value === 'Generator'))
|
|
||||||
) {
|
|
||||||
switch (count($type->type_params)) {
|
|
||||||
case 1:
|
|
||||||
$key_type_param = Type::getMixed();
|
|
||||||
$value_type_param = $type->type_params[0];
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
$key_type_param = $type->type_params[0];
|
|
||||||
$value_type_param = $type->type_params[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$key_type) {
|
if (!$key_type) {
|
||||||
$key_type = clone $key_type_param;
|
$key_type = clone $key_type_param;
|
||||||
@ -297,6 +278,15 @@ class ReturnTypeCollector
|
|||||||
} else {
|
} else {
|
||||||
$value_type = Type::combineUnionTypes($value_type_param, $value_type);
|
$value_type = Type::combineUnionTypes($value_type_param, $value_type);
|
||||||
}
|
}
|
||||||
|
} elseif ($type instanceof Type\Atomic\TIterable
|
||||||
|
|| $type instanceof Type\Atomic\TNamedObject
|
||||||
|
) {
|
||||||
|
ForeachAnalyzer::getKeyValueParamsForTraversableObject(
|
||||||
|
$type,
|
||||||
|
$codebase,
|
||||||
|
$key_type,
|
||||||
|
$value_type
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -938,9 +938,15 @@ class ForeachAnalyzer
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($iterator_atomic_type instanceof Type\Atomic\TNamedObject
|
if ($iterator_atomic_type instanceof Type\Atomic\TNamedObject
|
||||||
&& $codebase->classImplements(
|
&& (
|
||||||
$iterator_atomic_type->value,
|
$codebase->classImplements(
|
||||||
'Traversable'
|
$iterator_atomic_type->value,
|
||||||
|
'Traversable'
|
||||||
|
)
|
||||||
|
|| $codebase->interfaceExtends(
|
||||||
|
$iterator_atomic_type->value,
|
||||||
|
'Traversable'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
$generic_storage = $codebase->classlike_storage_provider->get(
|
$generic_storage = $codebase->classlike_storage_provider->get(
|
||||||
|
@ -2996,6 +2996,31 @@ class ClassTemplateExtendsTest extends TestCase
|
|||||||
}
|
}
|
||||||
}'
|
}'
|
||||||
],
|
],
|
||||||
|
'templateYieldFrom' => [
|
||||||
|
'<?php
|
||||||
|
/**
|
||||||
|
* @extends \IteratorAggregate<int, string>
|
||||||
|
*/
|
||||||
|
interface IStringList extends \IteratorAggregate
|
||||||
|
{
|
||||||
|
/** @return \Iterator<int, string> */
|
||||||
|
public function getIterator(): \Iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringListDecorator implements IStringList
|
||||||
|
{
|
||||||
|
private IStringList $decorated;
|
||||||
|
|
||||||
|
public function __construct(IStringList $decorated) {
|
||||||
|
$this->decorated = $decorated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIterator(): \Iterator
|
||||||
|
{
|
||||||
|
yield from $this->decorated;
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user