mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Fix #5298 - improve handling of method that may write properties
This commit is contained in:
parent
350df114f3
commit
7354ec9903
@ -366,12 +366,14 @@ class ElseIfAnalyzer
|
||||
$implied_outer_context = clone $elseif_context;
|
||||
$implied_outer_context->vars_in_scope = $leaving_vars_reconciled;
|
||||
|
||||
$updated_vars = [];
|
||||
|
||||
$outer_context->update(
|
||||
$elseif_context,
|
||||
$implied_outer_context,
|
||||
false,
|
||||
array_keys($negated_elseif_types),
|
||||
$if_scope->updated_vars
|
||||
$updated_vars
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -154,12 +154,15 @@ class MethodCallPurityAnalyzer
|
||||
if ($this_property_didnt_exist) {
|
||||
$context->vars_in_scope[$mutation_var_id] = Type::getMixed();
|
||||
} else {
|
||||
$context->vars_in_scope[$mutation_var_id] = AssignmentAnalyzer::getExpandedPropertyType(
|
||||
$new_type = AssignmentAnalyzer::getExpandedPropertyType(
|
||||
$codebase,
|
||||
$class_storage->name,
|
||||
$name,
|
||||
$class_storage
|
||||
) ?: Type::getMixed();
|
||||
|
||||
$context->vars_in_scope[$mutation_var_id] = $new_type;
|
||||
$context->possibly_assigned_var_ids[$mutation_var_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,10 @@ class AssignmentMapVisitor extends PhpParser\NodeVisitorAbstract
|
||||
return PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN;
|
||||
}
|
||||
|
||||
if ($node instanceof PhpParser\Node\Expr\FuncCall) {
|
||||
if ($node instanceof PhpParser\Node\Expr\FuncCall
|
||||
|| $node instanceof PhpParser\Node\Expr\MethodCall
|
||||
|| $node instanceof PhpParser\Node\Expr\StaticCall
|
||||
) {
|
||||
foreach ($node->args as $arg) {
|
||||
$arg_var_id = ExpressionIdentifier::getRootVarId($arg->value, $this->this_class_name);
|
||||
|
||||
@ -80,6 +83,12 @@ class AssignmentMapVisitor extends PhpParser\NodeVisitorAbstract
|
||||
$this->assignment_map[$arg_var_id][$arg_var_id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($node instanceof PhpParser\Node\Expr\MethodCall) {
|
||||
$var_id = ExpressionIdentifier::getRootVarId($node->var, $this->this_class_name);
|
||||
|
||||
$this->assignment_map[$var_id]['isset'] = true;
|
||||
}
|
||||
} elseif ($node instanceof PhpParser\Node\Stmt\Unset_) {
|
||||
foreach ($node->vars as $arg) {
|
||||
$arg_var_id = ExpressionIdentifier::getRootVarId($arg, $this->this_class_name);
|
||||
|
@ -660,6 +660,54 @@ class WhileTest extends \Psalm\Tests\TestCase
|
||||
return [];
|
||||
}'
|
||||
],
|
||||
'propertyTypeUpdatedInBranch' => [
|
||||
'<?php
|
||||
class A
|
||||
{
|
||||
public ?int $foo = null;
|
||||
|
||||
public function setFoo(): void
|
||||
{
|
||||
$this->foo = 5;
|
||||
}
|
||||
}
|
||||
|
||||
function bar(A $a): void {
|
||||
$a->foo = null;
|
||||
|
||||
while (rand(0, 1)) {
|
||||
if (rand(0, 1)) {
|
||||
$a->setFoo();
|
||||
} elseif ($a->foo !== null) {}
|
||||
}
|
||||
}'
|
||||
],
|
||||
'propertyTypeUpdatedInBranchWithBreak' => [
|
||||
'<?php
|
||||
class A
|
||||
{
|
||||
public ?int $foo = null;
|
||||
|
||||
public function setFoo(): void
|
||||
{
|
||||
$this->foo = 5;
|
||||
}
|
||||
}
|
||||
|
||||
function bar(A $a): void {
|
||||
$a->foo = null;
|
||||
|
||||
while (rand(0, 1)) {
|
||||
if (rand(0, 1)) {
|
||||
$a->setFoo();
|
||||
} elseif ($a->foo !== null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($a->foo !== null) {}
|
||||
}'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user