1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Merge pull request #9375 from jsanahuja/support_sizeof_alias

This commit is contained in:
Bruce Weirdan 2023-02-22 22:04:17 -04:00 committed by GitHub
commit 2cf3db6ae3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 35 additions and 12 deletions

View File

@ -11334,7 +11334,7 @@ return [
'SimpleXMLElement::xpath' => ['SimpleXMLElement[]|false', 'path'=>'string'],
'sin' => ['float', 'num'=>'float'],
'sinh' => ['float', 'num'=>'float'],
'sizeof' => ['int', 'value'=>'Countable|array', 'mode='=>'int'],
'sizeof' => ['int<0, max>', 'value'=>'Countable|array', 'mode='=>'int'],
'sleep' => ['int', 'seconds'=>'0|positive-int'],
'snmp2_get' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
'snmp2_getnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],

View File

@ -497,6 +497,10 @@ return [
'old' => ['int<0, max>', 'value'=>'Countable|array|SimpleXMLElement', 'mode='=>'int'],
'new' => ['int<0, max>', 'value'=>'Countable|array', 'mode='=>'int'],
],
'sizeof' => [
'old' => ['int<0, max>', 'value'=>'Countable|array|SimpleXMLElement', 'mode='=>'int'],
'new' => ['int<0, max>', 'value'=>'Countable|array', 'mode='=>'int'],
],
'count_chars' => [
'old' => ['array<int,int>|false', 'input'=>'string', 'mode='=>'0|1|2'],
'new' => ['array<int,int>', 'input'=>'string', 'mode='=>'0|1|2'],

View File

@ -14030,7 +14030,7 @@ return [
'simplexml_load_string' => ['SimpleXMLElement|false', 'data'=>'string', 'class_name='=>'?string', 'options='=>'int', 'namespace_or_prefix='=>'string', 'is_prefix='=>'bool'],
'sin' => ['float', 'num'=>'float'],
'sinh' => ['float', 'num'=>'float'],
'sizeof' => ['int', 'value'=>'Countable|array', 'mode='=>'int'],
'sizeof' => ['int<0, max>', 'value'=>'Countable|array|SimpleXMLElement', 'mode='=>'int'],
'sleep' => ['int|false', 'seconds'=>'0|positive-int'],
'snmp2_get' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
'snmp2_getnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],

View File

@ -1542,7 +1542,7 @@ class AssertionFinder
) {
if ($conditional->left instanceof PhpParser\Node\Expr\FuncCall
&& $conditional->left->name instanceof PhpParser\Node\Name
&& strtolower($conditional->left->name->parts[0]) === 'count'
&& in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof'])
&& $conditional->left->getArgs()
&& ($conditional instanceof BinaryOp\Greater || $conditional instanceof BinaryOp\GreaterOrEqual)
) {
@ -1551,7 +1551,7 @@ class AssertionFinder
$comparison_adjustment = $conditional instanceof BinaryOp\Greater ? 1 : 0;
} elseif ($conditional->right instanceof PhpParser\Node\Expr\FuncCall
&& $conditional->right->name instanceof PhpParser\Node\Name
&& strtolower($conditional->right->name->parts[0]) === 'count'
&& in_array(strtolower($conditional->right->name->parts[0]), ['count', 'sizeof'])
&& $conditional->right->getArgs()
&& ($conditional instanceof BinaryOp\Smaller || $conditional instanceof BinaryOp\SmallerOrEqual)
) {
@ -1584,7 +1584,7 @@ class AssertionFinder
) {
$left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall
&& $conditional->left->name instanceof PhpParser\Node\Name
&& strtolower($conditional->left->name->parts[0]) === 'count'
&& in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof'])
&& $conditional->left->getArgs();
$operator_less_than_or_equal =
@ -1603,7 +1603,7 @@ class AssertionFinder
$right_count = $conditional->right instanceof PhpParser\Node\Expr\FuncCall
&& $conditional->right->name instanceof PhpParser\Node\Name
&& strtolower($conditional->right->name->parts[0]) === 'count'
&& in_array(strtolower($conditional->right->name->parts[0]), ['count', 'sizeof'])
&& $conditional->right->getArgs();
$operator_greater_than_or_equal =
@ -1633,7 +1633,7 @@ class AssertionFinder
) {
$left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall
&& $conditional->left->name instanceof PhpParser\Node\Name
&& strtolower($conditional->left->name->parts[0]) === 'count'
&& in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof'])
&& $conditional->left->getArgs();
if ($left_count && $conditional->right instanceof PhpParser\Node\Scalar\LNumber) {
@ -1644,7 +1644,7 @@ class AssertionFinder
$right_count = $conditional->right instanceof PhpParser\Node\Expr\FuncCall
&& $conditional->right->name instanceof PhpParser\Node\Name
&& strtolower($conditional->right->name->parts[0]) === 'count'
&& in_array(strtolower($conditional->right->name->parts[0]), ['count', 'sizeof'])
&& $conditional->right->getArgs();
if ($right_count && $conditional->left instanceof PhpParser\Node\Scalar\LNumber) {
@ -1785,7 +1785,7 @@ class AssertionFinder
) {
$left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall
&& $conditional->left->name instanceof PhpParser\Node\Name
&& strtolower($conditional->left->name->parts[0]) === 'count';
&& in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof']);
$right_number = $conditional->right instanceof PhpParser\Node\Scalar\LNumber
&& $conditional->right->value === (
@ -2044,7 +2044,8 @@ class AssertionFinder
protected static function hasNonEmptyCountCheck(PhpParser\Node\Expr\FuncCall $stmt): bool
{
return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'count';
return $stmt->name instanceof PhpParser\Node\Name &&
in_array(strtolower($stmt->name->parts[0]), ['count', 'sizeof']);
}
protected static function hasArrayKeyExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool

View File

@ -354,6 +354,7 @@ class FunctionCallReturnTypeFetcher
} else {
switch ($call_map_key) {
case 'count':
case 'sizeof':
if (($first_arg_type = $statements_analyzer->node_data->getType($call_args[0]->value))) {
$atomic_types = $first_arg_type->getAtomicTypes();

View File

@ -81,7 +81,8 @@ class MatchAnalyzer
&& ($stmt->cond->name->parts === ['get_class']
|| $stmt->cond->name->parts === ['gettype']
|| $stmt->cond->name->parts === ['get_debug_type']
|| $stmt->cond->name->parts === ['count'])
|| $stmt->cond->name->parts === ['count']
|| $stmt->cond->name->parts === ['sizeof'])
&& $stmt->cond->getArgs()
) {
$first_arg = $stmt->cond->getArgs()[0];

View File

@ -555,7 +555,7 @@ class Functions
return true;
}
if ($function_id === 'count' && isset($args[0]) && $type_provider) {
if (in_array($function_id, ['count', 'sizeof']) && isset($args[0]) && $type_provider) {
$count_type = $type_provider->getType($args[0]->value);
if ($count_type) {

View File

@ -145,6 +145,22 @@ class ArrayAccessTest extends TestCase
$this->analyzeFile('somefile.php', new Context());
}
public function testNoIssueWhenUsingArrayValuesOnNonEmptyArrayCheckedWithSizeof(): void
{
Config::getInstance()->ensure_array_int_offsets_exist = true;
$this->addFile(
'somefile.php',
'<?php
/** @param string[][] $arr */
function foo(array $arr) : void {
if (sizeof($arr) === 1 && sizeof(array_values($arr)[0]) === 1) {}
}',
);
$this->analyzeFile('somefile.php', new Context());
}
public function testNoIssueAfterManyIssets(): void
{
Config::getInstance()->ensure_array_int_offsets_exist = true;