From 8fd671bdc4535b320785a8d1d3b7f54d3934e4b3 Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Wed, 28 Jun 2017 23:37:02 -0400 Subject: [PATCH] Fix #167 - prevent Empty type in assignment --- config.xsd | 1 + .../Statements/Expression/AssignmentChecker.php | 3 ++- .../Statements/Expression/FetchChecker.php | 13 +++++++++++++ src/Psalm/Issue/EmptyArrayAccess.php | 6 ++++++ tests/ArrayAccessTest.php | 15 ++++++++++++--- 5 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/Psalm/Issue/EmptyArrayAccess.php diff --git a/config.xsd b/config.xsd index 232cff023..d4120c3af 100644 --- a/config.xsd +++ b/config.xsd @@ -91,6 +91,7 @@ + diff --git a/src/Psalm/Checker/Statements/Expression/AssignmentChecker.php b/src/Psalm/Checker/Statements/Expression/AssignmentChecker.php index cee3f7a4a..3bb4ea333 100644 --- a/src/Psalm/Checker/Statements/Expression/AssignmentChecker.php +++ b/src/Psalm/Checker/Statements/Expression/AssignmentChecker.php @@ -546,7 +546,8 @@ class AssignmentChecker ($lhs_type_part instanceof TNamedObject && in_array( strtolower($lhs_type_part->value), - ['stdclass', 'simplexmlelement', 'dateinterval', 'domdocument', 'domnode'], true + ['stdclass', 'simplexmlelement', 'dateinterval', 'domdocument', 'domnode'], + true ) ) ) { diff --git a/src/Psalm/Checker/Statements/Expression/FetchChecker.php b/src/Psalm/Checker/Statements/Expression/FetchChecker.php index 8ca632ace..169b36139 100644 --- a/src/Psalm/Checker/Statements/Expression/FetchChecker.php +++ b/src/Psalm/Checker/Statements/Expression/FetchChecker.php @@ -12,6 +12,7 @@ use Psalm\Checker\TraitChecker; use Psalm\CodeLocation; use Psalm\Context; use Psalm\Issue\DeprecatedProperty; +use Psalm\Issue\EmptyArrayAccess; use Psalm\Issue\InaccessibleClassConstant; use Psalm\Issue\InvalidArrayAccess; use Psalm\Issue\InvalidArrayAssignment; @@ -1064,6 +1065,18 @@ class FetchChecker } } elseif ($type instanceof Type\Atomic\TArray && $value_index !== null) { $stmt->inferredType = $type->type_params[$value_index]; + if ($stmt->inferredType->isEmpty()) { + if (IssueBuffer::accepts( + new EmptyArrayAccess( + 'Cannot access value on empty array variable ' . $var_id, + new CodeLocation($statements_checker->getSource(), $stmt) + ), + $statements_checker->getSuppressedIssues() + )) { + return false; + } + $stmt->inferredType = Type::getMixed(); + } } elseif ($type instanceof Type\Atomic\ObjectLike) { $object_like_keys = array_keys($type->properties); if ($object_like_keys) { diff --git a/src/Psalm/Issue/EmptyArrayAccess.php b/src/Psalm/Issue/EmptyArrayAccess.php new file mode 100644 index 000000000..e1b312282 --- /dev/null +++ b/src/Psalm/Issue/EmptyArrayAccess.php @@ -0,0 +1,6 @@ + [], 'error_levels' => ['PossiblyNullArrayAccess'], ], + 'ignorePossiblyNullArrayAccess' => [ + ' [ + ['mixed' => '$x'], + ], + 'error_levels' => ['EmptyArrayAccess', 'MixedAssignment'], + ], ]; }