mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 05:41:20 +01:00
parent
9405773882
commit
25e022e77e
@ -393,7 +393,8 @@ class ArrayFetchAnalyzer
|
|||||||
$has_array_access = false;
|
$has_array_access = false;
|
||||||
$non_array_types = [];
|
$non_array_types = [];
|
||||||
|
|
||||||
$has_valid_offset = false;
|
$has_valid_expected_offset = false;
|
||||||
|
$has_valid_absolute_offset = false;
|
||||||
$expected_offset_types = [];
|
$expected_offset_types = [];
|
||||||
|
|
||||||
$key_values = [];
|
$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) {
|
foreach ($array_type->getAtomicTypes() as $type_string => $type) {
|
||||||
$original_type = $type;
|
$original_type = $type;
|
||||||
|
|
||||||
@ -477,7 +511,7 @@ class ArrayFetchAnalyzer
|
|||||||
$type
|
$type
|
||||||
);
|
);
|
||||||
|
|
||||||
$has_valid_offset = true;
|
$has_valid_expected_offset = true;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -557,7 +591,7 @@ class ArrayFetchAnalyzer
|
|||||||
$expected_offset_types,
|
$expected_offset_types,
|
||||||
$array_access_type,
|
$array_access_type,
|
||||||
$has_array_access,
|
$has_array_access,
|
||||||
$has_valid_offset
|
$has_valid_expected_offset
|
||||||
);
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -575,7 +609,7 @@ class ArrayFetchAnalyzer
|
|||||||
$offset_type,
|
$offset_type,
|
||||||
$expected_offset_types,
|
$expected_offset_types,
|
||||||
$array_access_type,
|
$array_access_type,
|
||||||
$has_valid_offset
|
$has_valid_expected_offset
|
||||||
);
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -707,9 +741,9 @@ class ArrayFetchAnalyzer
|
|||||||
$used_offset = 'using offset value of ' . implode('|', $key_values);
|
$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
|
// do nothing
|
||||||
} elseif ($has_valid_offset) {
|
} elseif ($has_valid_expected_offset && $has_valid_absolute_offset) {
|
||||||
if (!$context->inside_unset) {
|
if (!$context->inside_unset) {
|
||||||
if (IssueBuffer::accepts(
|
if (IssueBuffer::accepts(
|
||||||
new PossiblyInvalidArrayOffset(
|
new PossiblyInvalidArrayOffset(
|
||||||
|
@ -1065,15 +1065,6 @@ class ArrayAssignmentTest extends TestCase
|
|||||||
if (is_int($value["a"])) {}
|
if (is_int($value["a"])) {}
|
||||||
}'
|
}'
|
||||||
],
|
],
|
||||||
'falseArrayAssignment' => [
|
|
||||||
'<?php
|
|
||||||
function foo(): array {
|
|
||||||
$array = [];
|
|
||||||
$array[false] = "";
|
|
||||||
echo $array[0];
|
|
||||||
return $array;
|
|
||||||
}',
|
|
||||||
],
|
|
||||||
'coercePossiblyNullKeyToZero' => [
|
'coercePossiblyNullKeyToZero' => [
|
||||||
'<?php
|
'<?php
|
||||||
function int_or_null(): ?int {
|
function int_or_null(): ?int {
|
||||||
@ -1799,24 +1790,52 @@ class ArrayAssignmentTest extends TestCase
|
|||||||
',
|
',
|
||||||
'error_message' => 'InvalidArrayOffset'
|
'error_message' => 'InvalidArrayOffset'
|
||||||
],
|
],
|
||||||
|
'ArrayDimOffsetObject' => [
|
||||||
|
'<?php
|
||||||
|
$_a = [];
|
||||||
|
$_a[new stdClass] = "a";
|
||||||
|
',
|
||||||
|
'error_message' => 'InvalidArrayOffset'
|
||||||
|
],
|
||||||
'ArrayCreateOffsetResource' => [
|
'ArrayCreateOffsetResource' => [
|
||||||
'<?php
|
'<?php
|
||||||
$_a = [fopen("", "") => "a"];
|
$_a = [fopen("", "") => "a"];
|
||||||
',
|
',
|
||||||
'error_message' => 'InvalidArrayOffset'
|
'error_message' => 'InvalidArrayOffset'
|
||||||
],
|
],
|
||||||
|
'ArrayDimOffsetResource' => [
|
||||||
|
'<?php
|
||||||
|
$_a = [];
|
||||||
|
$_a[fopen("", "")] = "a";
|
||||||
|
',
|
||||||
|
'error_message' => 'InvalidArrayOffset'
|
||||||
|
],
|
||||||
'ArrayCreateOffsetBool' => [
|
'ArrayCreateOffsetBool' => [
|
||||||
'<?php
|
'<?php
|
||||||
$_a = [true => "a"];
|
$_a = [true => "a"];
|
||||||
',
|
',
|
||||||
'error_message' => 'InvalidArrayOffset'
|
'error_message' => 'InvalidArrayOffset'
|
||||||
],
|
],
|
||||||
|
'ArrayDimOffsetBool' => [
|
||||||
|
'<?php
|
||||||
|
$_a = [];
|
||||||
|
$_a[true] = "a";
|
||||||
|
',
|
||||||
|
'error_message' => 'InvalidArrayOffset'
|
||||||
|
],
|
||||||
'ArrayCreateOffsetStringable' => [
|
'ArrayCreateOffsetStringable' => [
|
||||||
'<?php
|
'<?php
|
||||||
$a = new class{public function __toString(){return "";}};
|
$a = new class{public function __toString(){return "";}};
|
||||||
$_a = [$a => "a"];',
|
$_a = [$a => "a"];',
|
||||||
'error_message' => 'InvalidArrayOffset',
|
'error_message' => 'InvalidArrayOffset',
|
||||||
],
|
],
|
||||||
|
'ArrayDimOffsetStringable' => [
|
||||||
|
'<?php
|
||||||
|
$_a = [];
|
||||||
|
$a = new class{public function __toString(){return "";}};
|
||||||
|
$_a[$a] = "a";',
|
||||||
|
'error_message' => 'InvalidArrayOffset',
|
||||||
|
],
|
||||||
'coerceListToArray' => [
|
'coerceListToArray' => [
|
||||||
'<?php
|
'<?php
|
||||||
/**
|
/**
|
||||||
@ -1876,7 +1895,17 @@ class ArrayAssignmentTest extends TestCase
|
|||||||
return $arr;
|
return $arr;
|
||||||
}',
|
}',
|
||||||
'error_message' => 'MixedArrayOffset'
|
'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