mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
parent
9405773882
commit
25e022e77e
@ -393,7 +393,8 @@ class ArrayFetchAnalyzer
|
||||
$has_array_access = false;
|
||||
$non_array_types = [];
|
||||
|
||||
$has_valid_offset = false;
|
||||
$has_valid_expected_offset = false;
|
||||
$has_valid_absolute_offset = false;
|
||||
$expected_offset_types = [];
|
||||
|
||||
$key_values = [];
|
||||
@ -461,6 +462,39 @@ class ArrayFetchAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
if ($array_type->isArray()) {
|
||||
foreach ($offset_type->getAtomicTypes() as $atomic_offset_type) {
|
||||
if ($atomic_offset_type instanceof Type\Atomic\TFalse &&
|
||||
$offset_type->ignore_falsable_issues === true
|
||||
) {
|
||||
//do nothing
|
||||
} elseif ($atomic_offset_type instanceof Type\Atomic\TNull &&
|
||||
$offset_type->ignore_nullable_issues === true
|
||||
) {
|
||||
//do nothing
|
||||
} elseif ($atomic_offset_type instanceof Type\Atomic\TString ||
|
||||
$atomic_offset_type instanceof Type\Atomic\TInt ||
|
||||
$atomic_offset_type instanceof Type\Atomic\TArrayKey ||
|
||||
$atomic_offset_type instanceof Type\Atomic\TMixed ||
|
||||
$atomic_offset_type instanceof Type\Atomic\TTemplateParam ||
|
||||
(
|
||||
$atomic_offset_type instanceof Type\Atomic\TObjectWithProperties
|
||||
&& isset($atomic_offset_type->methods['__toString'])
|
||||
)
|
||||
) {
|
||||
$has_valid_absolute_offset = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($has_valid_absolute_offset === false) {
|
||||
//we didn't find a single type that could be valid
|
||||
$expected_offset_types[] = 'array-key';
|
||||
}
|
||||
} else {
|
||||
//on not-arrays, the type is considered valid
|
||||
$has_valid_absolute_offset = true;
|
||||
}
|
||||
|
||||
foreach ($array_type->getAtomicTypes() as $type_string => $type) {
|
||||
$original_type = $type;
|
||||
|
||||
@ -477,7 +511,7 @@ class ArrayFetchAnalyzer
|
||||
$type
|
||||
);
|
||||
|
||||
$has_valid_offset = true;
|
||||
$has_valid_expected_offset = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
@ -557,7 +591,7 @@ class ArrayFetchAnalyzer
|
||||
$expected_offset_types,
|
||||
$array_access_type,
|
||||
$has_array_access,
|
||||
$has_valid_offset
|
||||
$has_valid_expected_offset
|
||||
);
|
||||
|
||||
continue;
|
||||
@ -575,7 +609,7 @@ class ArrayFetchAnalyzer
|
||||
$offset_type,
|
||||
$expected_offset_types,
|
||||
$array_access_type,
|
||||
$has_valid_offset
|
||||
$has_valid_expected_offset
|
||||
);
|
||||
|
||||
continue;
|
||||
@ -707,9 +741,9 @@ class ArrayFetchAnalyzer
|
||||
$used_offset = 'using offset value of ' . implode('|', $key_values);
|
||||
}
|
||||
|
||||
if ($has_valid_offset && $context->inside_isset) {
|
||||
if ($has_valid_expected_offset && $has_valid_absolute_offset && $context->inside_isset) {
|
||||
// do nothing
|
||||
} elseif ($has_valid_offset) {
|
||||
} elseif ($has_valid_expected_offset && $has_valid_absolute_offset) {
|
||||
if (!$context->inside_unset) {
|
||||
if (IssueBuffer::accepts(
|
||||
new PossiblyInvalidArrayOffset(
|
||||
|
@ -1065,15 +1065,6 @@ class ArrayAssignmentTest extends TestCase
|
||||
if (is_int($value["a"])) {}
|
||||
}'
|
||||
],
|
||||
'falseArrayAssignment' => [
|
||||
'<?php
|
||||
function foo(): array {
|
||||
$array = [];
|
||||
$array[false] = "";
|
||||
echo $array[0];
|
||||
return $array;
|
||||
}',
|
||||
],
|
||||
'coercePossiblyNullKeyToZero' => [
|
||||
'<?php
|
||||
function int_or_null(): ?int {
|
||||
@ -1799,24 +1790,52 @@ class ArrayAssignmentTest extends TestCase
|
||||
',
|
||||
'error_message' => 'InvalidArrayOffset'
|
||||
],
|
||||
'ArrayDimOffsetObject' => [
|
||||
'<?php
|
||||
$_a = [];
|
||||
$_a[new stdClass] = "a";
|
||||
',
|
||||
'error_message' => 'InvalidArrayOffset'
|
||||
],
|
||||
'ArrayCreateOffsetResource' => [
|
||||
'<?php
|
||||
$_a = [fopen("", "") => "a"];
|
||||
',
|
||||
'error_message' => 'InvalidArrayOffset'
|
||||
],
|
||||
'ArrayDimOffsetResource' => [
|
||||
'<?php
|
||||
$_a = [];
|
||||
$_a[fopen("", "")] = "a";
|
||||
',
|
||||
'error_message' => 'InvalidArrayOffset'
|
||||
],
|
||||
'ArrayCreateOffsetBool' => [
|
||||
'<?php
|
||||
$_a = [true => "a"];
|
||||
',
|
||||
'error_message' => 'InvalidArrayOffset'
|
||||
],
|
||||
'ArrayDimOffsetBool' => [
|
||||
'<?php
|
||||
$_a = [];
|
||||
$_a[true] = "a";
|
||||
',
|
||||
'error_message' => 'InvalidArrayOffset'
|
||||
],
|
||||
'ArrayCreateOffsetStringable' => [
|
||||
'<?php
|
||||
$a = new class{public function __toString(){return "";}};
|
||||
$_a = [$a => "a"];',
|
||||
'error_message' => 'InvalidArrayOffset',
|
||||
],
|
||||
'ArrayDimOffsetStringable' => [
|
||||
'<?php
|
||||
$_a = [];
|
||||
$a = new class{public function __toString(){return "";}};
|
||||
$_a[$a] = "a";',
|
||||
'error_message' => 'InvalidArrayOffset',
|
||||
],
|
||||
'coerceListToArray' => [
|
||||
'<?php
|
||||
/**
|
||||
@ -1876,7 +1895,17 @@ class ArrayAssignmentTest extends TestCase
|
||||
return $arr;
|
||||
}',
|
||||
'error_message' => 'MixedArrayOffset'
|
||||
]
|
||||
],
|
||||
'falseArrayAssignment' => [
|
||||
'<?php
|
||||
function foo(): array {
|
||||
$array = [];
|
||||
$array[false] = "";
|
||||
echo $array[0];
|
||||
return $array;
|
||||
}',
|
||||
'error_message' => 'InvalidArrayOffset'
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user