diff --git a/config.xsd b/config.xsd index 875d1e5be..53918684e 100644 --- a/config.xsd +++ b/config.xsd @@ -310,6 +310,8 @@ + + diff --git a/docs/running_psalm/issues.md b/docs/running_psalm/issues.md index edbae2e6a..6f7903fa6 100644 --- a/docs/running_psalm/issues.md +++ b/docs/running_psalm/issues.md @@ -1951,6 +1951,32 @@ echo $arr["b"]; ``` +### PossiblyUndefinedIntArrayOffset + +Emitted when the config flag `ensureArrayIntOffsetsExist` is set to `true` and an integer-keyed offset is not checked for existence + +```php +/** + * @param array $arr + */ +function foo(array $arr) : void { + echo $arr[0]; +} +``` + +### PossiblyUndefinedStringArrayOffset + +Emitted when the config flag `ensureArrayStringOffsetsExist` is set to `true` and an integer-keyed offset is not checked for existence + +```php +/** + * @param array $arr + */ +function foo(array $arr) : void { + echo $arr["hello"]; +} +``` + ### PossiblyUndefinedGlobalVariable Emitted when trying to access a variable in the global scope that may not be defined diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index 7cb836b6c..3812410b4 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -1272,6 +1272,12 @@ class Config */ public static function getParentIssueType($issue_type) { + if ($issue_type === 'PossiblyUndefinedIntArrayOffset' + || $issue_type === 'PossiblyUndefinedStringArrayOffset' + ) { + return 'PossiblyUndefinedArrayOffset'; + } + if (strpos($issue_type, 'Possibly') === 0) { $stripped_issue_type = preg_replace('/^Possibly(False|Null)?/', '', $issue_type); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php index 8ee531967..55fed3362 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php @@ -25,6 +25,8 @@ use Psalm\Issue\PossiblyNullArrayAccess; use Psalm\Issue\PossiblyNullArrayAssignment; use Psalm\Issue\PossiblyNullArrayOffset; use Psalm\Issue\PossiblyUndefinedArrayOffset; +use Psalm\Issue\PossiblyUndefinedIntArrayOffset; +use Psalm\Issue\PossiblyUndefinedStringArrayOffset; use Psalm\IssueBuffer; use Psalm\Type; use Psalm\Type\Atomic\ObjectLike; @@ -1263,7 +1265,7 @@ class ArrayFetchAnalyzer if (!$found_match) { if (IssueBuffer::accepts( - new PossiblyUndefinedArrayOffset( + new PossiblyUndefinedIntArrayOffset( 'Possibly undefined array offset \'' . $offset_type->getId() . '\' ' . 'is risky given expected type \'' @@ -1312,7 +1314,7 @@ class ArrayFetchAnalyzer if (!$found_match) { if (IssueBuffer::accepts( - new PossiblyUndefinedArrayOffset( + new PossiblyUndefinedStringArrayOffset( 'Possibly undefined array offset \'' . $offset_type->getId() . '\' ' . 'is risky given expected type \'' diff --git a/src/Psalm/Issue/PossiblyUndefinedIntArrayOffset.php b/src/Psalm/Issue/PossiblyUndefinedIntArrayOffset.php new file mode 100644 index 000000000..91116dd93 --- /dev/null +++ b/src/Psalm/Issue/PossiblyUndefinedIntArrayOffset.php @@ -0,0 +1,6 @@ +project_analyzer->trackUnusedSuppressions(); } + $is_array_offset_test = strpos($error_message, 'ArrayOffset') && strpos($error_message, 'PossiblyUndefined') !== false; + + $this->project_analyzer->getConfig()->ensure_array_string_offsets_exist = $is_array_offset_test; + $this->project_analyzer->getConfig()->ensure_array_int_offsets_exist = $is_array_offset_test; + + if (strpos($error_message, 'ArrayOffset')) { + + } + foreach ($error_levels as $error_level) { $this->project_analyzer->getCodebase()->config->setCustomErrorLevel($error_level, Config::REPORT_SUPPRESS); }