Skip to content

Commit

Permalink
Merge pull request #9021 from orklah/nonempty-reconcile
Browse files Browse the repository at this point in the history
Non empty reconciliation
  • Loading branch information
orklah committed Dec 29, 2022
2 parents 2efa6ae + 907729d commit 6353143
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
23 changes: 21 additions & 2 deletions src/Psalm/Internal/Type/SimpleAssertionReconciler.php
Original file line number Diff line number Diff line change
Expand Up @@ -2239,17 +2239,36 @@ private static function reconcileArray(
$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;

foreach ($existing_var_atomic_types as $type) {
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([
Expand Down Expand Up @@ -2365,7 +2384,7 @@ private static function reconcileList(
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]);
Expand Down
3 changes: 3 additions & 0 deletions tests/TypeReconciliation/ReconcilerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Psalm\Storage\Assertion\Truthy;
use Psalm\Tests\TestCase;
use Psalm\Type;
use Psalm\Type\Atomic;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TClassConstant;
use Psalm\Type\Atomic\TFalse;
Expand Down Expand Up @@ -176,6 +177,8 @@ public function providerTestReconcilation(): array
'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(Atomic::create('non-empty-array')), 'array'],
'nonEmptyList' => ['non-empty-list<mixed>', new IsType(Atomic::create('non-empty-list')), 'array'],
];
}

Expand Down

0 comments on commit 6353143

Please sign in to comment.