1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Fix #2012 - count(callable-array) is fine and always equals 2

This commit is contained in:
Brown 2019-08-12 16:17:55 -04:00
parent 10b8a94564
commit 58b6d8bed4
3 changed files with 39 additions and 13 deletions

View File

@ -112,19 +112,23 @@ class FunctionAnalyzer extends FunctionLikeAnalyzer
if (isset($call_args[0]->value->inferredType)) { if (isset($call_args[0]->value->inferredType)) {
$atomic_types = $call_args[0]->value->inferredType->getTypes(); $atomic_types = $call_args[0]->value->inferredType->getTypes();
if (count($atomic_types) === 1 && isset($atomic_types['array'])) { if (count($atomic_types) === 1) {
if ($atomic_types['array'] instanceof Type\Atomic\TNonEmptyArray) { if (isset($atomic_types['array'])) {
return new Type\Union([ if ($atomic_types['array'] instanceof Type\Atomic\TNonEmptyArray) {
$atomic_types['array']->count !== null return new Type\Union([
? new Type\Atomic\TLiteralInt($atomic_types['array']->count) $atomic_types['array']->count !== null
: new Type\Atomic\TInt ? new Type\Atomic\TLiteralInt($atomic_types['array']->count)
]); : new Type\Atomic\TInt
} elseif ($atomic_types['array'] instanceof Type\Atomic\ObjectLike ]);
&& $atomic_types['array']->sealed } elseif ($atomic_types['array'] instanceof Type\Atomic\ObjectLike
) { && $atomic_types['array']->sealed
return new Type\Union([ ) {
new Type\Atomic\TLiteralInt(count($atomic_types['array']->properties)) return new Type\Union([
]); new Type\Atomic\TLiteralInt(count($atomic_types['array']->properties))
]);
}
} elseif (isset($atomic_types['callable-array'])) {
return Type::getInt(false, 2);
} }
} }
} }

View File

@ -724,6 +724,8 @@ class TypeAnalyzer
} }
if ($input_type_part->shallowEquals($container_type_part) if ($input_type_part->shallowEquals($container_type_part)
|| ($input_type_part instanceof Type\Atomic\TCallableObjectLikeArray
&& $container_type_part instanceof TArray)
|| (($input_type_part instanceof TNamedObject || (($input_type_part instanceof TNamedObject
|| ($input_type_part instanceof TTemplateParam || ($input_type_part instanceof TTemplateParam
&& $input_type_part->as->hasObjectType()) && $input_type_part->as->hasObjectType())

View File

@ -1698,6 +1698,15 @@ class FunctionCallTest extends TestCase
$xml = new SimpleXMLElement("<?xml version=\"1.0\"?><a><b></b><b></b></a>"); $xml = new SimpleXMLElement("<?xml version=\"1.0\"?><a><b></b><b></b></a>");
echo count($xml);', echo count($xml);',
], ],
'countableCallableArray' => [
'<?php
/** @param callable|false $x */
function example($x) : void {
if (is_array($x)) {
echo "Count is: " . count($x);
}
}'
],
'refineWithTraitExists' => [ 'refineWithTraitExists' => [
'<?php '<?php
function foo(string $s) : void { function foo(string $s) : void {
@ -2358,6 +2367,17 @@ class FunctionCallTest extends TestCase
}', }',
'error_message' => 'UndefinedVariable', 'error_message' => 'UndefinedVariable',
], ],
'countCallableArrayShouldBeTwo' => [
'<?php
/** @param callable|false $x */
function example($x) : void {
if (is_array($x)) {
$c = count($x);
if ($c !== 2) {}
}
}',
'error_message' => 'TypeDoesNotContainType',
],
]; ];
} }
} }