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

fix non-empty reconciliation

This commit is contained in:
orklah 2022-12-29 00:49:31 +01:00
parent 9770e113c3
commit 5a002c448b
2 changed files with 29 additions and 2 deletions

View File

@ -2239,9 +2239,14 @@ class SimpleAssertionReconciler extends Reconciler
$existing_var_atomic_types = $existing_var_type->getAtomicTypes();
if ($existing_var_type->hasMixed()) {
if ($assertion->getAtomicType()) {
return new Union([$assertion->getAtomicType()]);
}
return Type::getArray();
}
$atomic_assertion_type = $assertion->getAtomicType();
$array_types = [];
$did_remove_type = false;
@ -2249,7 +2254,21 @@ class SimpleAssertionReconciler extends Reconciler
if ($type instanceof TList) {
$type = $type->getKeyedArray();
}
if ($type instanceof TArray || $type instanceof TKeyedArray) {
if ($type instanceof TArray) {
if ($atomic_assertion_type instanceof TNonEmptyArray) {
$array_types[] = new TNonEmptyArray(
$type->type_params,
$atomic_assertion_type->count,
$atomic_assertion_type->min_count,
'non-empty-array',
$type->from_docblock,
);
} else {
$array_types[] = $type;
}
} elseif ($type instanceof TKeyedArray) {
//we don't currently have "definitely defined" shapes so we keep the one we have even if we have
//a non-empty-array assertion
$array_types[] = $type;
} elseif ($type instanceof TCallable) {
$array_types[] = new TCallableKeyedArray([
@ -2365,7 +2384,7 @@ class SimpleAssertionReconciler extends Reconciler
if ($type->type_params[0]->hasArrayKey()
|| $type->type_params[0]->hasInt()
) {
if ($type instanceof TNonEmptyArray) {
if ($type instanceof TNonEmptyArray || $is_non_empty) {
$array_types[] = Type::getNonEmptyListAtomic($type->type_params[1]);
} else {
$array_types[] = Type::getListAtomic($type->type_params[1]);

View File

@ -21,6 +21,7 @@ use Psalm\Storage\Assertion\Truthy;
use Psalm\Tests\TestCase;
use Psalm\Type;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TArrayKey;
use Psalm\Type\Atomic\TClassConstant;
use Psalm\Type\Atomic\TFalse;
use Psalm\Type\Atomic\TFloat;
@ -28,7 +29,9 @@ use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TIterable;
use Psalm\Type\Atomic\TKeyedArray;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Atomic\TMixed;
use Psalm\Type\Atomic\TNamedObject;
use Psalm\Type\Atomic\TNonEmptyArray;
use Psalm\Type\Atomic\TNull;
use Psalm\Type\Atomic\TNumeric;
use Psalm\Type\Atomic\TObject;
@ -176,6 +179,11 @@ class ReconcilerTest extends TestCase
'SimpleXMLIteratorNotAlwaysTruthy2' => ['SimpleXMLIterator', new Falsy(), 'SimpleXMLIterator'],
'stringWithAny' => ['string', new Any(), 'string'],
'IsNotAClassReconciliation' => ['int', new Assertion\IsNotAClass(new TNamedObject('IDObject'), true), 'int|IDObject'],
'nonEmptyArray' => ['non-empty-array<array-key, mixed>', new IsType(new TNonEmptyArray([
new Union([new TArrayKey()]),
new Union([new TMixed()]),
])), 'array'],
'nonEmptyList' => ['non-empty-list<mixed>', new IsType(Type::getNonEmptyListAtomic(Type::getMixed())), 'array'],
];
}