1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Fix #4547 - mark unused uses

This commit is contained in:
Matt Brown 2020-11-13 13:13:29 -05:00 committed by Daniil Gentili
parent c1d57ba6a5
commit ad840e4b7a
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
4 changed files with 42 additions and 10 deletions

View File

@ -123,8 +123,6 @@ class ClosureAnalyzer extends FunctionLikeAnalyzer
}
}
$byref_uses = [];
if ($stmt instanceof PhpParser\Node\Expr\Closure) {
foreach ($stmt->uses as $use) {
if (!is_string($use->var->name)) {
@ -133,10 +131,6 @@ class ClosureAnalyzer extends FunctionLikeAnalyzer
$use_var_id = '$' . $use->var->name;
if ($use->byRef) {
$byref_uses[$use_var_id] = true;
}
// insert the ref into the current context if passed by ref, as whatever we're passing
// the closure to could execute it straight away.
if (!$context->hasVariable($use_var_id) && $use->byRef) {
@ -206,7 +200,7 @@ class ClosureAnalyzer extends FunctionLikeAnalyzer
$use_context->calling_method_id = $context->calling_method_id;
$closure_analyzer->analyze($use_context, $statements_analyzer->node_data, $context, false, $byref_uses);
$closure_analyzer->analyze($use_context, $statements_analyzer->node_data, $context, false);
if ($closure_analyzer->inferred_impure
&& $statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer

View File

@ -144,8 +144,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
Context $context,
\Psalm\Internal\Provider\NodeDataProvider $type_provider,
?Context $global_context = null,
bool $add_mutations = false,
?array $byref_uses = null
bool $add_mutations = false
): ?bool {
$storage = $this->storage;
@ -403,7 +402,36 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
$statements_analyzer = new StatementsAnalyzer($this, $type_provider);
if ($byref_uses) {
if ($this->function instanceof Closure) {
$byref_uses = [];
foreach ($this->function->uses as $use) {
if (!\is_string($use->var->name)) {
continue;
}
$use_var_id = '$' . $use->var->name;
if ($use->byRef) {
$byref_uses[$use_var_id] = true;
} else {
$use_location = new CodeLocation($this, $use);
$statements_analyzer->registerVariable($use_var_id, $use_location, null);
if ($statements_analyzer->data_flow_graph && isset($context->vars_in_scope[$use_var_id])) {
$use_assignment = DataFlowNode::getForAssignment(
$use_var_id,
$use_location
);
$statements_analyzer->data_flow_graph->addNode($use_assignment);
$context->vars_in_scope[$use_var_id]->parent_nodes += [$use_assignment->id => $use_assignment];
}
}
}
$statements_analyzer->setByRefUses($byref_uses);
}

View File

@ -41,6 +41,7 @@ use Psalm\Type\Atomic\TTemplateParam;
use Psalm\Type\Atomic\TTrue;
use Psalm\Type\Atomic\TVoid;
use Psalm\Type\Union;
use function get_class;
use function stripos;
use function strlen;
use function strpos;

View File

@ -3060,6 +3060,15 @@ class UnusedVariableTest extends TestCase
}',
'error_message' => 'PossiblyNullArgument'
],
'useArrayAssignmentNeverUsed' => [
'<?php
$data = [];
return function () use ($data) {
$data[] = 1;
};',
'error_message' => 'UnusedVariable',
],
];
}
}