Skip to content

Commit

Permalink
When inside isset, array fetch can return null
Browse files Browse the repository at this point in the history
This prevents false positive for various types of issues inside empty,
such as RedundantConditionGivenDocblockType and TypeDoesNotContainType.
  • Loading branch information
edsrzf committed Feb 28, 2024
1 parent 9aa450b commit c1b1b7a
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public static function analyze(

$codebase = $statements_analyzer->getCodebase();

if ($keyed_array_var_id
if ($keyed_array_var_id !== null
&& $context->hasVariable($keyed_array_var_id)
&& !$context->vars_in_scope[$keyed_array_var_id]->possibly_undefined
&& $stmt_var_type
Expand Down Expand Up @@ -250,6 +250,10 @@ public static function analyze(
}
}

if ($context->inside_isset && !$stmt_type->hasMixed()) {
$stmt_type = Type::combineUnionTypes($stmt_type, Type::getNull());
}

$statements_analyzer->node_data->setType($stmt, $stmt_type);

if ($context->inside_isset
Expand Down Expand Up @@ -304,7 +308,7 @@ public static function analyze(
}
}

if ($keyed_array_var_id
if ($keyed_array_var_id !== null
&& $context->hasVariable($keyed_array_var_id)
&& (!($stmt_type = $statements_analyzer->node_data->getType($stmt)) || $stmt_type->isVanillaMixed())
) {
Expand Down
2 changes: 2 additions & 0 deletions tests/ArrayAssignmentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,8 @@ function takesList(array $arr) : void {
foreach ($arr[0] as $k => $v) {}
}
}',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
],
'nonEmptyAssignmentToListElement' => [
'code' => '<?php
Expand Down
1 change: 1 addition & 0 deletions tests/ArrayFunctionCallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2602,6 +2602,7 @@ function($val) { return (int)$val; },
'assertions' => [
'$line===' => 'array{0: int, ...<array-key, int>}',
],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
],
'arrayUnshiftOnEmptyArrayMeansNonEmptyList' => [
'code' => '<?php
Expand Down
13 changes: 13 additions & 0 deletions tests/TypeReconciliation/EmptyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ function _processScopes($scopes) : void {
function foo(array $o) : void {
if (empty($o[0]) && empty($o[1])) {}
}',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
],
'multipleEmptiesInConditionWithMixedOffset' => [
'code' => '<?php
Expand Down Expand Up @@ -315,6 +317,8 @@ function baz(array $data) : void {
if (empty($data[Foo::ONE])) {}
}
}',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
],
'doubleEmptyCheckTwoArrays' => [
'code' => '<?php
Expand All @@ -330,6 +334,8 @@ function foo(array $a, array $b) : void {
function foo(array $arr) : void {
if (empty($arr["a"]) && empty($arr["b"])) {}
}',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
],
'doubleEmptyCheckOnTKeyedArrayVariableOffsets' => [
'code' => '<?php
Expand All @@ -340,6 +346,8 @@ function foo(int $i, int $j) : void {
if (empty($arr[$i]) && empty($arr[$j])) {}
}',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
],
'checkArrayEmptyUnknownRoot' => [
'code' => '<?php
Expand Down Expand Up @@ -626,6 +634,11 @@ function test(string $s): void {
'$x===' => 'true',
],
],
'emptyArrayFetch' => [
'code' => '<?php
/** @var array<true> $a */
if (empty($a["a"])) {}',
],
];
}

Expand Down
2 changes: 2 additions & 0 deletions tests/TypeReconciliation/RedundantConditionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,8 @@ function foo(array $a) : void {
if (empty($a["foo"])) {}
}
}',
'assertions' => [],
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
],
'suppressRedundantConditionAfterAssertNonEmpty' => [
'code' => '<?php
Expand Down

0 comments on commit c1b1b7a

Please sign in to comment.