1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Allow empty offset sets on arrayaccess objects

This commit is contained in:
Brown 2019-04-10 17:25:25 -04:00
parent 7f8b47c5cf
commit 8f1dbc072d
3 changed files with 114 additions and 22 deletions

View File

@ -225,7 +225,7 @@ class ArrayAssignmentAnalyzer
true,
$array_var_id,
$context,
$child_stmts ? null : $assign_value,
$assign_value,
$child_stmts ? null : $assignment_type
);

View File

@ -792,8 +792,14 @@ class ArrayFetchAnalyzer
$iterator_class_type = $fake_method_call->inferredType ?? null;
$array_access_type = $iterator_class_type ?: Type::getMixed();
} else {
$suppressed_issues = $statements_analyzer->getSuppressedIssues();
if (!in_array('PossiblyInvalidMethodCall', $suppressed_issues, true)) {
$statements_analyzer->addSuppressedIssues(['PossiblyInvalidMethodCall']);
}
if ($in_assignment) {
$fake_method_call = new PhpParser\Node\Expr\MethodCall(
$fake_set_method_call = new PhpParser\Node\Expr\MethodCall(
$stmt->var,
new PhpParser\Node\Identifier('offsetSet', $stmt->var->getAttributes()),
[
@ -814,41 +820,43 @@ class ArrayFetchAnalyzer
),
]
);
} else {
$fake_method_call = new PhpParser\Node\Expr\MethodCall(
\Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze(
$statements_analyzer,
$fake_set_method_call,
$context
);
}
if ($stmt->dim) {
$fake_get_method_call = new PhpParser\Node\Expr\MethodCall(
$stmt->var,
new PhpParser\Node\Identifier('offsetGet', $stmt->var->getAttributes()),
[
new PhpParser\Node\Arg(
$stmt->dim
? $stmt->dim
: new PhpParser\Node\Expr\ConstFetch(
new PhpParser\Node\Name('null'),
$stmt->var->getAttributes()
)
)
]
);
\Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze(
$statements_analyzer,
$fake_get_method_call,
$context
);
$iterator_class_type = $fake_get_method_call->inferredType ?? null;
} else {
$iterator_class_type = Type::getVoid();
}
$suppressed_issues = $statements_analyzer->getSuppressedIssues();
$has_array_access = true;
if (!in_array('PossiblyInvalidMethodCall', $suppressed_issues, true)) {
$statements_analyzer->addSuppressedIssues(['PossiblyInvalidMethodCall']);
}
\Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze(
$statements_analyzer,
$fake_method_call,
$context
);
$array_access_type = $iterator_class_type ?: Type::getMixed();
if (!in_array('PossiblyInvalidMethodCall', $suppressed_issues, true)) {
$statements_analyzer->removeSuppressedIssues(['PossiblyInvalidMethodCall']);
}
$iterator_class_type = $fake_method_call->inferredType ?? null;
$array_access_type = $iterator_class_type ?: Type::getMixed();
}
} elseif (!$array_type->hasMixed()) {
$non_array_types[] = (string)$type;

View File

@ -353,6 +353,90 @@ class ArrayAccessTest extends TestCase
[],
['MixedArrayAccess', 'MixedArgument'],
],
'arrayAccessOnObjectWithNullGet' => [
'<?php
class C implements ArrayAccess
{
/**
* @var array<C|scalar>
*/
protected $data = [];
/**
* @param array<scalar|array> $array
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedTypeCoercion
*/
public function __construct(array $array)
{
foreach ($array as $key => $value) {
if (is_array($value)) {
$this->data[$key] = new static($value);
} else {
$this->data[$key] = $value;
}
}
}
/**
* @param string $name
* @return C|scalar
*/
public function offsetGet($name)
{
return $this->data[$name];
}
/**
* @param ?string $name
* @param scalar|array $value
* @psalm-suppress MixedTypeCoercion
*/
public function offsetSet($name, $value) : void
{
if (is_array($value)) {
$value = new static($value);
}
if (null === $name) {
$this->data[] = $value;
} else {
$this->data[$name] = $value;
}
}
public function __isset(string $name) : bool
{
return isset($this->data[$name]);
}
public function __unset(string $name) : void
{
unset($this->data[$name]);
}
/**
* @psalm-suppress MixedArgument
*/
public function offsetExists($offset) : bool
{
return $this->__isset($offset);
}
/**
* @psalm-suppress MixedArgument
*/
public function offsetUnset($offset) : void
{
$this->__unset($offset);
}
}
$array = new C([]);
$array["key"] = [];
/** @psalm-suppress PossiblyInvalidArrayAssignment */
$array["key"][] = "testing";'
],
];
}