mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Add PossiblyUndefinedVariable warning when using possibly undefined array key
This commit is contained in:
parent
61af2a924c
commit
4175d1a887
@ -23,6 +23,8 @@ use Psalm\Issue\PossiblyInvalidArrayOffset;
|
||||
use Psalm\Issue\PossiblyNullArrayAccess;
|
||||
use Psalm\Issue\PossiblyNullArrayAssignment;
|
||||
use Psalm\Issue\PossiblyNullArrayOffset;
|
||||
use Psalm\Issue\PossiblyUndefinedGlobalVariable;
|
||||
use Psalm\Issue\PossiblyUndefinedVariable;
|
||||
use Psalm\IssueBuffer;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic\ObjectLike;
|
||||
@ -130,6 +132,30 @@ class ArrayFetchChecker
|
||||
|
||||
if (!isset($stmt->inferredType)) {
|
||||
$stmt->inferredType = Type::getMixed();
|
||||
} else {
|
||||
if ($stmt->inferredType->possibly_undefined && !$context->inside_isset && !$context->inside_unset) {
|
||||
if ($context->is_global) {
|
||||
if (IssueBuffer::accepts(
|
||||
new PossiblyUndefinedGlobalVariable(
|
||||
'Possibly undefined array key ' . $keyed_array_var_id,
|
||||
new CodeLocation($statements_checker->getSource(), $stmt)
|
||||
),
|
||||
$statements_checker->getSuppressedIssues()
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (IssueBuffer::accepts(
|
||||
new PossiblyUndefinedVariable(
|
||||
'Possibly undefined array key ' . $keyed_array_var_id,
|
||||
new CodeLocation($statements_checker->getSource(), $stmt)
|
||||
),
|
||||
$statements_checker->getSuppressedIssues()
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -361,8 +361,9 @@ class Context
|
||||
$redefined_var_ids = [];
|
||||
|
||||
foreach ($new_context->vars_in_scope as $var_id => $context_type) {
|
||||
if (!isset($original_context->vars_in_scope[$var_id]) ||
|
||||
$original_context->vars_in_scope[$var_id]->getId() !== $context_type->getId()
|
||||
if (!isset($original_context->vars_in_scope[$var_id])
|
||||
|| $original_context->vars_in_scope[$var_id]->getId() !== $context_type->getId()
|
||||
|| $original_context->vars_in_scope[$var_id]->possibly_undefined !== $context_type->possibly_undefined
|
||||
) {
|
||||
$redefined_var_ids[] = $var_id;
|
||||
}
|
||||
|
@ -92,6 +92,7 @@ class Reconciler
|
||||
|
||||
$failed_reconciliation = false;
|
||||
$from_docblock = $result_type && $result_type->from_docblock;
|
||||
$possibly_undefined = $result_type && $result_type->possibly_undefined;
|
||||
|
||||
foreach ($new_type_parts as $new_type_part) {
|
||||
$new_type_part_parts = explode('|', $new_type_part);
|
||||
@ -123,6 +124,7 @@ class Reconciler
|
||||
|
||||
if ($result_type->getId() !== $before_adjustment
|
||||
|| $result_type->from_docblock !== $from_docblock
|
||||
|| $result_type->possibly_undefined !== $possibly_undefined
|
||||
|| $failed_reconciliation
|
||||
) {
|
||||
$changed_var_ids[] = $key;
|
||||
@ -482,6 +484,8 @@ class Reconciler
|
||||
return Type::getMixed();
|
||||
}
|
||||
|
||||
$existing_var_type->possibly_undefined = false;
|
||||
|
||||
return $existing_var_type;
|
||||
}
|
||||
|
||||
|
@ -838,6 +838,18 @@ class ArrayAssignmentTest extends TestCase
|
||||
'MixedArrayAccess', 'MixedAssignment', 'MixedArrayOffset', 'MixedArrayAssignment', 'MixedArgument',
|
||||
],
|
||||
],
|
||||
'possiblyUndefinedArrayAccessWithIsset' => [
|
||||
'<?php
|
||||
if (rand(0,1)) {
|
||||
$a = ["a" => 1];
|
||||
} else {
|
||||
$a = [2, 3];
|
||||
}
|
||||
|
||||
if (isset($a[0])) {
|
||||
echo $a[0];
|
||||
}',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@ -859,6 +871,17 @@ class ArrayAssignmentTest extends TestCase
|
||||
$a[0] = 5;',
|
||||
'error_message' => 'InvalidArrayAssignment',
|
||||
],
|
||||
'possiblyUndefinedArrayAccess' => [
|
||||
'<?php
|
||||
if (rand(0,1)) {
|
||||
$a = ["a" => 1];
|
||||
} else {
|
||||
$a = [2, 3];
|
||||
}
|
||||
|
||||
echo $a[0];',
|
||||
'error_message' => 'PossiblyUndefinedGlobalVariable',
|
||||
],
|
||||
'mixedStringOffsetAssignment' => [
|
||||
'<?php
|
||||
/** @var mixed */
|
||||
|
Loading…
Reference in New Issue
Block a user