1
0
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:
Matt Brown 2021-05-23 16:22:52 -04:00
parent 350df114f3
commit 7354ec9903
4 changed files with 65 additions and 3 deletions

View File

@ -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
);
}
}

View File

@ -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;
}
}
}

View File

@ -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);

View File

@ -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) {}
}'
],
];
}