1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-13 17:57:37 +01:00
psalm/src/Psalm/Internal/Analyzer/Statements/ContinueAnalyzer.php

99 lines
3.4 KiB
PHP
Raw Normal View History

2020-05-19 18:56:23 +02:00
<?php
2020-05-19 18:56:23 +02:00
namespace Psalm\Internal\Analyzer\Statements;
use PhpParser;
use Psalm\CodeLocation;
use Psalm\Context;
2021-06-08 04:55:21 +02:00
use Psalm\Internal\Analyzer\ScopeAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
2020-05-19 18:56:23 +02:00
use Psalm\Issue\ContinueOutsideLoop;
use Psalm\IssueBuffer;
use Psalm\Type;
2021-12-03 21:07:25 +01:00
use function end;
2022-01-03 07:55:32 +01:00
/**
* @internal
*/
2020-05-19 18:56:23 +02:00
class ContinueAnalyzer
{
public static function analyze(
StatementsAnalyzer $statements_analyzer,
PhpParser\Node\Stmt\Continue_ $stmt,
Context $context
2021-06-10 18:09:46 +02:00
): void {
2021-09-26 22:25:15 +02:00
$count = $stmt->num instanceof PhpParser\Node\Scalar\LNumber? $stmt->num->value : 1;
2020-10-24 18:23:59 +02:00
2020-05-19 18:56:23 +02:00
$loop_scope = $context->loop_scope;
2020-10-24 18:23:59 +02:00
if ($count === 2 && isset($loop_scope->loop_parent_context->loop_scope)) {
$loop_scope = $loop_scope->loop_parent_context->loop_scope;
}
if ($count === 3 && isset($loop_scope->loop_parent_context->loop_scope)) {
$loop_scope = $loop_scope->loop_parent_context->loop_scope;
}
2020-05-19 18:56:23 +02:00
if ($loop_scope === null) {
if (!$context->break_types) {
if (IssueBuffer::accepts(
new ContinueOutsideLoop(
'Continue call outside loop context',
2022-12-18 17:15:15 +01:00
new CodeLocation($statements_analyzer, $stmt),
2020-05-19 18:56:23 +02:00
),
2022-12-18 17:15:15 +01:00
$statements_analyzer->getSource()->getSuppressedIssues(),
2020-05-19 18:56:23 +02:00
)) {
2021-06-10 18:09:46 +02:00
return;
2020-05-19 18:56:23 +02:00
}
}
} else {
if ($context->break_types
2021-12-03 21:07:25 +01:00
&& end($context->break_types) === 'switch'
2020-10-24 18:23:59 +02:00
&& $count < 2
2020-05-19 18:56:23 +02:00
) {
$loop_scope->final_actions[] = ScopeAnalyzer::ACTION_LEAVE_SWITCH;
} else {
$loop_scope->final_actions[] = ScopeAnalyzer::ACTION_CONTINUE;
}
$redefined_vars = $context->getRedefinedVars($loop_scope->loop_parent_context->vars_in_scope);
foreach ($loop_scope->redefined_loop_vars as $redefined_var => $type) {
if (!isset($redefined_vars[$redefined_var])) {
unset($loop_scope->redefined_loop_vars[$redefined_var]);
} else {
$loop_scope->redefined_loop_vars[$redefined_var] = Type::combineUnionTypes(
$redefined_vars[$redefined_var],
2022-12-18 17:15:15 +01:00
$type,
);
2020-05-19 18:56:23 +02:00
}
}
foreach ($redefined_vars as $var => $type) {
2021-09-25 04:30:19 +02:00
$loop_scope->possibly_redefined_loop_vars[$var] = Type::combineUnionTypes(
$type,
2022-12-18 17:15:15 +01:00
$loop_scope->possibly_redefined_loop_vars[$var] ?? null,
2021-09-25 04:30:19 +02:00
);
2020-05-19 18:56:23 +02:00
}
if ($context->finally_scope) {
foreach ($context->vars_in_scope as $var_id => &$type) {
if (isset($context->finally_scope->vars_in_scope[$var_id])) {
2021-09-25 04:30:19 +02:00
$context->finally_scope->vars_in_scope[$var_id] = Type::combineUnionTypes(
$context->finally_scope->vars_in_scope[$var_id],
$type,
2022-12-18 17:15:15 +01:00
$statements_analyzer->getCodebase(),
2021-09-25 04:30:19 +02:00
);
} else {
$type = $type->setPossiblyUndefined(true, true);
$context->finally_scope->vars_in_scope[$var_id] = $type;
}
}
}
2020-05-19 18:56:23 +02:00
}
$context->has_returned = true;
}
}