1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-10 06:58:41 +01:00
psalm/src/Psalm/Internal/Analyzer/Statements/Expression/YieldFromAnalyzer.php

86 lines
2.7 KiB
PHP
Raw Normal View History

2020-05-18 21:13:27 +02:00
<?php
2020-05-18 21:13:27 +02:00
namespace Psalm\Internal\Analyzer\Statements\Expression;
use PhpParser;
use Psalm\Context;
use Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer;
2021-06-08 04:55:21 +02:00
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
2020-05-18 21:13:27 +02:00
use Psalm\Type;
2021-12-13 04:45:57 +01:00
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TGenericObject;
use Psalm\Type\Atomic\TKeyedArray;
2021-06-08 04:55:21 +02:00
2020-05-18 21:13:27 +02:00
use function strtolower;
2022-01-03 07:55:32 +01:00
/**
* @internal
*/
2020-05-18 21:13:27 +02:00
class YieldFromAnalyzer
{
public static function analyze(
StatementsAnalyzer $statements_analyzer,
PhpParser\Node\Expr\YieldFrom $stmt,
Context $context
): bool {
2020-05-18 21:13:27 +02:00
$was_inside_call = $context->inside_call;
$context->inside_call = true;
if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === false) {
$context->inside_call = $was_inside_call;
return false;
}
if ($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr)) {
$key_type = null;
$value_type = null;
$always_non_empty_array = true;
if (ForeachAnalyzer::checkIteratorType(
$statements_analyzer,
$stmt,
$stmt->expr,
$stmt_expr_type,
$statements_analyzer->getCodebase(),
$context,
$key_type,
$value_type,
$always_non_empty_array
) === false
) {
$context->inside_call = $was_inside_call;
return false;
}
2020-05-18 21:13:27 +02:00
$yield_from_type = null;
foreach ($stmt_expr_type->getAtomicTypes() as $atomic_type) {
if ($yield_from_type === null) {
2021-12-13 04:45:57 +01:00
if ($atomic_type instanceof TGenericObject
2020-05-18 21:13:27 +02:00
&& strtolower($atomic_type->value) === 'generator'
&& isset($atomic_type->type_params[3])
) {
$yield_from_type = $atomic_type->type_params[3];
2021-12-13 04:45:57 +01:00
} elseif ($atomic_type instanceof TArray) {
$yield_from_type = $atomic_type->type_params[1];
2021-12-13 04:45:57 +01:00
} elseif ($atomic_type instanceof TKeyedArray) {
2020-05-18 21:13:27 +02:00
$yield_from_type = $atomic_type->getGenericValueType();
}
} else {
$yield_from_type = Type::getMixed();
}
}
// this should be whatever the generator above returns, but *not* the return type
$statements_analyzer->node_data->setType($stmt, $yield_from_type ?: Type::getMixed());
}
$context->inside_call = $was_inside_call;
return true;
}
}