Skip to content
Permalink
Browse files

array_push shouldn’t change list type

  • Loading branch information
muglug committed Dec 29, 2019
1 parent ca31931 commit 26876b9a1393f08364007901a1ef0f8d05f23167
Showing with 55 additions and 15 deletions.
  1. +41 −15 src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php
  2. +14 −0 tests/ArrayAccessTest.php
@@ -364,7 +364,7 @@ protected static function checkFunctionArguments(
&& isset($args[0])
&& isset($args[1])
) {
if (self::handleArrayAddition($statements_analyzer, $args, $context) === false) {
if (self::handleArrayAddition($statements_analyzer, $args, $context, $method_id === 'array_push') === false) {
return false;
}

@@ -822,7 +822,8 @@ private static function handleByRefFunctionArg(
private static function handleArrayAddition(
StatementsAnalyzer $statements_analyzer,
array $args,
Context $context
Context $context,
bool $is_push
) {
$array_arg = $args[0]->value;

@@ -855,7 +856,13 @@ private static function handleArrayAddition(
*/
$array_type = $array_arg_type->getTypes()['array'];

$objectlike_list = null;

if ($array_type instanceof ObjectLike) {
if ($array_type->is_list) {
$objectlike_list = clone $array_type;
}

$array_type = $array_type->getGenericArrayType();
}

@@ -887,19 +894,38 @@ private static function handleArrayAddition(
clone $arg_value_type
);
} else {
$by_ref_type = Type::combineUnionTypes(
$by_ref_type,
new Type\Union(
[
new TArray(
[
Type::getInt(),
clone $arg_value_type
]
),
]
)
);
if ($objectlike_list) {
if ($is_push) {
array_push($objectlike_list->properties, $arg_value_type);
} else {
array_unshift($objectlike_list->properties, $arg_value_type);
}

$by_ref_type = new Type\Union([$objectlike_list]);
} elseif ($array_type instanceof TList) {
$by_ref_type = Type::combineUnionTypes(
$by_ref_type,
new Type\Union(
[
new TNonEmptyList(clone $arg_value_type),
]
)
);
} else {
$by_ref_type = Type::combineUnionTypes(
$by_ref_type,
new Type\Union(
[
new TNonEmptyArray(
[
Type::getInt(),
clone $arg_value_type
]
),
]
)
);
}
}
}

@@ -229,6 +229,20 @@ function takesList(array $arr) : void {
$this->analyzeFile('somefile.php', new \Psalm\Context());
}

public function testEnsureOffsetExistsAfterArrayPush() : void
{
\Psalm\Config::getInstance()->ensure_array_int_offsets_exist = true;

$this->addFile(
'somefile.php',
'<?php
$a = [1, 2, 3];
array_push($a, 4);
echo $a[3];'
);
$this->analyzeFile('somefile.php', new \Psalm\Context());
}

/**
* @return void
*/

0 comments on commit 26876b9

Please sign in to comment.
You can’t perform that action at this time.