1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

more consistency

This commit is contained in:
orklah 2021-10-10 00:51:47 +02:00
parent 7c99878f58
commit df34daee52
5 changed files with 24 additions and 31 deletions

View File

@ -29,7 +29,7 @@ class DoAnalyzer
StatementsAnalyzer $statements_analyzer,
PhpParser\Node\Stmt\Do_ $stmt,
Context $context
): void {
): ?bool {
$do_context = clone $context;
$do_context->break_types[] = 'loop';
$do_context->inside_loop = true;
@ -89,20 +89,22 @@ class DoAnalyzer
$while_clauses = [new Clause([], $cond_id, $cond_id, true)];
}
LoopAnalyzer::analyze(
if (LoopAnalyzer::analyze(
$statements_analyzer,
$stmt->stmts,
[$stmt->cond],
WhileAnalyzer::getAndExpressions($stmt->cond),
[],
$loop_scope,
$inner_loop_context,
true,
true
);
) === false) {
return false;
}
// because it's a do {} while, inner loop vars belong to the main context
if (!$inner_loop_context) {
throw new \UnexpectedValueException('Should never be null');
throw new \UnexpectedValueException('There should be an inner loop context');
}
$negated_while_clauses = Algebra::negateFormula($while_clauses);
@ -113,8 +115,6 @@ class DoAnalyzer
)
);
//var_dump($do_context->vars_in_scope);
if ($negated_while_types) {
$changed_var_ids = [];
@ -132,22 +132,6 @@ class DoAnalyzer
);
}
foreach ($inner_loop_context->vars_in_scope as $var_id => $type) {
// if there are break statements in the loop it's not certain
// that the loop has finished executing, so the assertions at the end
// the loop in the while conditional may not hold
if (in_array(ScopeAnalyzer::ACTION_BREAK, $loop_scope->final_actions, true)) {
if (isset($loop_scope->possibly_defined_loop_parent_vars[$var_id])) {
$context->vars_in_scope[$var_id] = Type::combineUnionTypes(
$type,
$loop_scope->possibly_defined_loop_parent_vars[$var_id]
);
}
} else {
$context->vars_in_scope[$var_id] = $type;
}
}
$do_context->loop_scope = null;
$context->vars_possibly_in_scope = array_merge(
@ -163,6 +147,8 @@ class DoAnalyzer
if ($context->collect_exceptions) {
$context->mergeExceptions($inner_loop_context);
}
return null;
}
private static function analyzeDoNaively(

View File

@ -78,14 +78,16 @@ class ForAnalyzer
$context->protected_var_ids
);
LoopAnalyzer::analyze(
if (LoopAnalyzer::analyze(
$statements_analyzer,
$stmt->stmts,
$stmt->cond,
$stmt->loop,
$loop_scope,
$inner_loop_context
);
) === false) {
return false;
}
if (!$inner_loop_context) {
throw new \UnexpectedValueException('There should be an inner loop context');
@ -142,7 +144,8 @@ class ForAnalyzer
if ($always_enters_loop && $can_leave_loop) {
foreach ($inner_loop_context->vars_in_scope as $var_id => $type) {
// if there are break statements in the loop it's not certain
// that the loop has finished executing
// that the loop has finished executing, so the assertions at the end
// the loop in the while conditional may not hold
if (in_array(ScopeAnalyzer::ACTION_BREAK, $loop_scope->final_actions, true)
|| in_array(ScopeAnalyzer::ACTION_CONTINUE, $loop_scope->final_actions, true)
) {

View File

@ -309,7 +309,7 @@ class ForeachAnalyzer
$loop_scope->protected_var_ids = $context->protected_var_ids;
LoopAnalyzer::analyze(
if (LoopAnalyzer::analyze(
$statements_analyzer,
$stmt->stmts,
[],
@ -318,7 +318,9 @@ class ForeachAnalyzer
$inner_loop_context,
false,
$always_non_empty_array
);
) === false) {
return false;
}
if (!$inner_loop_context) {
throw new \UnexpectedValueException('There should be an inner loop context');

View File

@ -60,7 +60,7 @@ class WhileAnalyzer
}
if (!$inner_loop_context) {
throw new \UnexpectedValueException('Should always enter loop');
throw new \UnexpectedValueException('There should be an inner loop context');
}
$always_enters_loop = false;
@ -122,7 +122,7 @@ class WhileAnalyzer
/**
* @return list<PhpParser\Node\Expr>
*/
private static function getAndExpressions(
public static function getAndExpressions(
PhpParser\Node\Expr $expr
) : array {
if ($expr instanceof PhpParser\Node\Expr\BinaryOp\BooleanAnd) {

View File

@ -509,7 +509,9 @@ class StatementsAnalyzer extends SourceAnalyzer
return false;
}
} elseif ($stmt instanceof PhpParser\Node\Stmt\Do_) {
DoAnalyzer::analyze($statements_analyzer, $stmt, $context);
if (DoAnalyzer::analyze($statements_analyzer, $stmt, $context) === false) {
return false;
}
} elseif ($stmt instanceof PhpParser\Node\Stmt\Const_) {
ConstFetchAnalyzer::analyzeConstAssignment($statements_analyzer, $stmt, $context);
} elseif ($stmt instanceof PhpParser\Node\Stmt\Unset_) {