mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 12:24:49 +01:00
Fix #285 - add PossiblyInvalidArrayAccess
This commit is contained in:
parent
4f2a200b45
commit
a0a9128375
@ -156,6 +156,7 @@
|
||||
<xs:element name="PossiblyFalseArgument" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="PossiblyFalseReference" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="PossiblyInvalidArgument" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="PossiblyInvalidArrayAccess" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="PossiblyNullArgument" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="PossiblyNullArrayAccess" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="PossiblyNullFunctionCall" type="IssueHandlerType" minOccurs="0" />
|
||||
|
@ -187,7 +187,7 @@ class CommentChecker
|
||||
&& preg_match('/^(\.\.\.)?&?\$[A-Za-z0-9_]+,?$/', $line_parts[1])
|
||||
&& !strpos($line_parts[0], '::')
|
||||
&& $line_parts[0][0] !== '{'
|
||||
&& !in_array($line_parts[0], ['null', 'false', 'true'])
|
||||
&& !in_array($line_parts[0], ['null', 'false', 'true'], true)
|
||||
) {
|
||||
if ($line_parts[1][0] === '&') {
|
||||
$line_parts[1] = substr($line_parts[1], 1);
|
||||
@ -199,8 +199,6 @@ class CommentChecker
|
||||
|
||||
$line_parts[1] = preg_replace('/,$/', '', $line_parts[1]);
|
||||
|
||||
|
||||
|
||||
$info->params[] = [
|
||||
'name' => $line_parts[1],
|
||||
'type' => $line_parts[0],
|
||||
|
@ -26,6 +26,7 @@ use Psalm\Issue\NullArrayAccess;
|
||||
use Psalm\Issue\NullPropertyFetch;
|
||||
use Psalm\Issue\NullReference;
|
||||
use Psalm\Issue\ParentNotFound;
|
||||
use Psalm\Issue\PossiblyInvalidArrayAccess;
|
||||
use Psalm\Issue\PossiblyNullArrayAccess;
|
||||
use Psalm\Issue\PossiblyNullPropertyFetch;
|
||||
use Psalm\Issue\PossiblyNullReference;
|
||||
@ -907,6 +908,9 @@ class FetchChecker
|
||||
return;
|
||||
}
|
||||
|
||||
$has_array_access = false;
|
||||
$non_array_types = [];
|
||||
|
||||
foreach ($var_type->types as &$type) {
|
||||
if ($type instanceof TNull) {
|
||||
if (IssueBuffer::accepts(
|
||||
@ -931,6 +935,7 @@ class FetchChecker
|
||||
|
||||
if ($type instanceof Type\Atomic\TArray || $type instanceof Type\Atomic\ObjectLike) {
|
||||
$value_index = null;
|
||||
$has_array_access = true;
|
||||
|
||||
if ($type instanceof Type\Atomic\TArray) {
|
||||
// create a union type to pass back to the statement
|
||||
@ -1174,17 +1179,36 @@ class FetchChecker
|
||||
!ClassChecker::classImplements($project_checker, $type->value, 'ArrayAccess')
|
||||
)
|
||||
) {
|
||||
$non_array_types[] = $var_type;
|
||||
}
|
||||
}
|
||||
|
||||
if ($non_array_types) {
|
||||
if ($has_array_access) {
|
||||
if (IssueBuffer::accepts(
|
||||
new PossiblyInvalidArrayAccess(
|
||||
'Cannot access array value on non-array variable ' .
|
||||
$array_var_id . ' of type ' . $non_array_types[0],
|
||||
new CodeLocation($statements_checker->getSource(), $stmt)
|
||||
),
|
||||
$statements_checker->getSuppressedIssues()
|
||||
)
|
||||
) {
|
||||
// do nothing
|
||||
}
|
||||
} else {
|
||||
if (IssueBuffer::accepts(
|
||||
new InvalidArrayAccess(
|
||||
'Cannot access array value on non-array variable ' .
|
||||
$array_var_id . ' of type ' . $var_type,
|
||||
$array_var_id . ' of type ' . $non_array_types[0],
|
||||
new CodeLocation($statements_checker->getSource(), $stmt)
|
||||
),
|
||||
$statements_checker->getSuppressedIssues()
|
||||
)) {
|
||||
$stmt->inferredType = Type::getMixed();
|
||||
break;
|
||||
// fall through
|
||||
}
|
||||
|
||||
$stmt->inferredType = Type::getMixed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
6
src/Psalm/Issue/PossiblyInvalidArrayAccess.php
Normal file
6
src/Psalm/Issue/PossiblyInvalidArrayAccess.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace Psalm\Issue;
|
||||
|
||||
class PossiblyInvalidArrayAccess extends CodeError
|
||||
{
|
||||
}
|
@ -100,6 +100,12 @@ class ArrayAccessTest extends TestCase
|
||||
echo $a[0];',
|
||||
'error_message' => 'InvalidArrayAccess',
|
||||
],
|
||||
'possiblyInvalidArrayAccess' => [
|
||||
'<?php
|
||||
$a = rand(0, 10) > 5 ? 5 : ["hello"];
|
||||
echo $a[0];',
|
||||
'error_message' => 'PossiblyInvalidArrayAccess',
|
||||
],
|
||||
'mixedArrayAccess' => [
|
||||
'<?php
|
||||
/** @var mixed */
|
||||
|
@ -266,7 +266,7 @@ class FunctionCallTest extends TestCase
|
||||
|
||||
foo($a3);',
|
||||
'assertions' => [
|
||||
'$a3' => 'array{bye:int, hi:int}'
|
||||
'$a3' => 'array{bye:int, hi:int}',
|
||||
],
|
||||
],
|
||||
'goodByRef' => [
|
||||
|
Loading…
Reference in New Issue
Block a user