mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Add more info to mic drop code
This commit is contained in:
parent
d72e612223
commit
a79b7eeca3
@ -146,92 +146,22 @@ class IfAnalyzer
|
||||
} else {
|
||||
if (!$has_break_statement) {
|
||||
$if_scope->reasonable_clauses = [];
|
||||
}
|
||||
}
|
||||
|
||||
if ($has_leaving_statements && !$has_break_statement && !$stmt->else && !$stmt->elseifs) {
|
||||
// If we're assigning inside
|
||||
if ($if_conditional_scope->cond_assigned_var_ids
|
||||
&& $if_scope->mic_drop_context
|
||||
) {
|
||||
self::addConditionallyAssignedVarsToContext(
|
||||
$statements_analyzer,
|
||||
$stmt->cond,
|
||||
$if_scope->mic_drop_context,
|
||||
$outer_context,
|
||||
$if_conditional_scope->cond_assigned_var_ids
|
||||
);
|
||||
}
|
||||
if (!$stmt->else && !$stmt->elseifs) {
|
||||
$mic_drop = self::handleMicDrop(
|
||||
$statements_analyzer,
|
||||
$stmt->cond,
|
||||
$if_scope,
|
||||
$if_conditional_scope,
|
||||
$outer_context,
|
||||
$new_assigned_var_ids
|
||||
);
|
||||
|
||||
if ($if_scope->negated_types) {
|
||||
$changed_var_ids = [];
|
||||
|
||||
$outer_context_vars_reconciled = Reconciler::reconcileKeyedTypes(
|
||||
$if_scope->negated_types,
|
||||
[],
|
||||
$outer_context->vars_in_scope,
|
||||
$changed_var_ids,
|
||||
[],
|
||||
$statements_analyzer,
|
||||
$statements_analyzer->getTemplateTypeMap() ?: [],
|
||||
$outer_context->inside_loop,
|
||||
new CodeLocation(
|
||||
$statements_analyzer->getSource(),
|
||||
$stmt->cond instanceof PhpParser\Node\Expr\BooleanNot
|
||||
? $stmt->cond->expr
|
||||
: $stmt->cond,
|
||||
$outer_context->include_location,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
foreach ($changed_var_ids as $changed_var_id => $_) {
|
||||
$outer_context->removeVarFromConflictingClauses($changed_var_id);
|
||||
}
|
||||
|
||||
$changed_var_ids += $new_assigned_var_ids;
|
||||
|
||||
foreach ($changed_var_ids as $var_id => $_) {
|
||||
$if_scope->negated_clauses = Context::filterClauses(
|
||||
$var_id,
|
||||
$if_scope->negated_clauses
|
||||
$outer_context->clauses = Algebra::simplifyCNF(
|
||||
array_merge($outer_context->clauses, $if_scope->negated_clauses)
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($changed_var_ids as $var_id => $_) {
|
||||
$first_appearance = $statements_analyzer->getFirstAppearance($var_id);
|
||||
|
||||
if ($first_appearance
|
||||
&& isset($outer_context->vars_in_scope[$var_id])
|
||||
&& isset($outer_context_vars_reconciled[$var_id])
|
||||
&& $outer_context->vars_in_scope[$var_id]->hasMixed()
|
||||
&& !$outer_context_vars_reconciled[$var_id]->hasMixed()
|
||||
) {
|
||||
if (!$outer_context->collect_initializations
|
||||
&& !$outer_context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->decrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
IssueBuffer::remove(
|
||||
$statements_analyzer->getFilePath(),
|
||||
'MixedAssignment',
|
||||
$first_appearance->raw_file_start
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$outer_context->vars_in_scope = $outer_context_vars_reconciled;
|
||||
$mic_drop = true;
|
||||
}
|
||||
|
||||
$outer_context->clauses = Algebra::simplifyCNF(
|
||||
array_merge($outer_context->clauses, $if_scope->negated_clauses)
|
||||
);
|
||||
}
|
||||
|
||||
// update the parent context as necessary, but only if we can safely reason about type negation.
|
||||
@ -306,6 +236,104 @@ class IfAnalyzer
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles the situation when returning inside an
|
||||
* if block with no else or elseifs
|
||||
*
|
||||
* @param array<string, int> $new_assigned_var_ids
|
||||
*/
|
||||
private static function handleMicDrop(
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
PhpParser\Node\Expr $cond,
|
||||
IfScope $if_scope,
|
||||
IfConditionalScope $if_conditional_scope,
|
||||
Context $outer_context,
|
||||
array $new_assigned_var_ids
|
||||
) : bool {
|
||||
// If we're assigning inside
|
||||
if ($if_conditional_scope->cond_assigned_var_ids
|
||||
&& $if_scope->mic_drop_context
|
||||
) {
|
||||
self::addConditionallyAssignedVarsToContext(
|
||||
$statements_analyzer,
|
||||
$cond,
|
||||
$if_scope->mic_drop_context,
|
||||
$outer_context,
|
||||
$if_conditional_scope->cond_assigned_var_ids
|
||||
);
|
||||
}
|
||||
|
||||
if (!$if_scope->negated_types) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$changed_var_ids = [];
|
||||
|
||||
$outer_context_vars_reconciled = Reconciler::reconcileKeyedTypes(
|
||||
$if_scope->negated_types,
|
||||
[],
|
||||
$outer_context->vars_in_scope,
|
||||
$changed_var_ids,
|
||||
[],
|
||||
$statements_analyzer,
|
||||
$statements_analyzer->getTemplateTypeMap() ?: [],
|
||||
$outer_context->inside_loop,
|
||||
new CodeLocation(
|
||||
$statements_analyzer->getSource(),
|
||||
$cond instanceof PhpParser\Node\Expr\BooleanNot
|
||||
? $cond->expr
|
||||
: $cond,
|
||||
$outer_context->include_location,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
foreach ($changed_var_ids as $changed_var_id => $_) {
|
||||
$outer_context->removeVarFromConflictingClauses($changed_var_id);
|
||||
}
|
||||
|
||||
$changed_var_ids += $new_assigned_var_ids;
|
||||
|
||||
foreach ($changed_var_ids as $var_id => $_) {
|
||||
$if_scope->negated_clauses = Context::filterClauses(
|
||||
$var_id,
|
||||
$if_scope->negated_clauses
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($changed_var_ids as $var_id => $_) {
|
||||
$first_appearance = $statements_analyzer->getFirstAppearance($var_id);
|
||||
|
||||
if ($first_appearance
|
||||
&& isset($outer_context->vars_in_scope[$var_id])
|
||||
&& isset($outer_context_vars_reconciled[$var_id])
|
||||
&& $outer_context->vars_in_scope[$var_id]->hasMixed()
|
||||
&& !$outer_context_vars_reconciled[$var_id]->hasMixed()
|
||||
) {
|
||||
if (!$outer_context->collect_initializations
|
||||
&& !$outer_context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
$codebase->analyzer->decrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
IssueBuffer::remove(
|
||||
$statements_analyzer->getFilePath(),
|
||||
'MixedAssignment',
|
||||
$first_appearance->raw_file_start
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$outer_context->vars_in_scope = $outer_context_vars_reconciled;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, int> $cond_assigned_var_ids
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user