Skip to content

Commit d1970a3

Browse files
committed
Fixup
1 parent e4f10b6 commit d1970a3

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

tests/Unit/Type/Parser/LexingParserTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,14 @@ public function test_shaped_list_missing_shorthand_splat_closing_bracket_throws_
16091609
self::assertSame('Missing closing curly bracket in shaped list signature `list{string, ...list<float>`.', $type->message());
16101610
}
16111611

1612+
public function test_shaped_list_missing_closing_bracket_after_shorthand_splat_type_throws_exception(): void
1613+
{
1614+
$type = $this->parse('list{string, ...<float>');
1615+
1616+
self::assertInstanceOf(UnresolvableType::class, $type);
1617+
self::assertSame('Missing closing curly bracket in shaped list signature `list{string, ...list<float>`.', $type->message());
1618+
}
1619+
16121620
public function test_shaped_list_invalid_shorthand_splat_closing_bracket_throws_exception(): void
16131621
{
16141622
$type = $this->parse('list{string, ...<float int}');
@@ -1657,6 +1665,14 @@ public function test_shaped_list_typed_splat_with_unexpected_token_throws_except
16571665
self::assertSame('Unexpected `int` after sealed type in shaped array signature `array{0: string, ...floatint`, expected a `}`.', $type->message());
16581666
}
16591667

1668+
public function test_shaped_list_typed_splat_with_nested_list_missing_closing_bracket_throws_exception(): void
1669+
{
1670+
$type = $this->parse('list{string, ...list<float>');
1671+
1672+
self::assertInstanceOf(UnresolvableType::class, $type);
1673+
self::assertSame('Missing closing curly bracket in shaped list signature `list{string, list<float>`.', $type->message());
1674+
}
1675+
16601676
public function test_shaped_list_missing_element_type_throws_exception(): void
16611677
{
16621678
$type = $this->parse('list{0:');
@@ -1737,6 +1753,22 @@ public function test_shaped_array_with_duplicate_shorthand_splat_throws_exceptio
17371753
self::assertSame('A shaped array can only have one splat element in `array{0: int, ..., ...}`.', $type->message());
17381754
}
17391755

1756+
public function test_shaped_array_shorthand_splat_with_invalid_key_type_throws_exception(): void
1757+
{
1758+
$type = $this->parse('array{0: int, ...<float, string>}');
1759+
1760+
self::assertInstanceOf(UnresolvableType::class, $type);
1761+
self::assertSame('Invalid type `array<float, string>`: invalid array-key element(s) `float`, each element must be an integer or a string.', $type->message());
1762+
}
1763+
1764+
public function test_shaped_array_shorthand_splat_missing_final_closing_bracket_throws_exception(): void
1765+
{
1766+
$type = $this->parse('array{0: int, ...<string, float>');
1767+
1768+
self::assertInstanceOf(UnresolvableType::class, $type);
1769+
self::assertSame('Missing closing curly bracket in shaped array signature `array{0: int, ...array<string, float>`.', $type->message());
1770+
}
1771+
17401772
public function test_shaped_array_shorthand_splat_with_unexpected_token_after_comma_throws_exception(): void
17411773
{
17421774
$type = $this->parse('array{0: int, ...<int>, string}');
@@ -1745,6 +1777,14 @@ public function test_shaped_array_shorthand_splat_with_unexpected_token_after_co
17451777
self::assertSame('Unexpected `,string` after sealed type in shaped array signature `array{0: int, ...array<int>,string`, expected a `}`.', $type->message());
17461778
}
17471779

1780+
public function test_shaped_list_with_trailing_comma_can_be_followed_by_union(): void
1781+
{
1782+
$type = $this->parse('list{string,}|null');
1783+
1784+
self::assertInstanceOf(UnionType::class, $type);
1785+
self::assertSame('list{string}|null', $type->toString());
1786+
}
1787+
17481788
public function test_invalid_iterable_key_throws_exception(): void
17491789
{
17501790
$type = $this->parse('iterable<float, string>');

tests/Unit/Type/Types/ShapedListTypeTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,54 @@ public function test_does_not_infer_generics_from_non_shaped_list_type(): void
433433
self::assertSame([], $generics->items);
434434
}
435435

436+
public function test_infers_generics_from_matching_shaped_list_elements(): void
437+
{
438+
$type = ShapedListType::from(
439+
elements: [
440+
new ShapedArrayElement(new IntegerValueType(0), new GenericType('T', new NativeStringType())),
441+
new ShapedArrayElement(new IntegerValueType(1), new GenericType('U', new NativeIntegerType())),
442+
],
443+
isUnsealed: false,
444+
);
445+
446+
$other = ShapedListType::from(
447+
elements: [
448+
new ShapedArrayElement(new IntegerValueType(0), new NativeStringType()),
449+
new ShapedArrayElement(new IntegerValueType(1), new NativeIntegerType()),
450+
],
451+
isUnsealed: false,
452+
);
453+
454+
$generics = $type->inferGenericsFrom($other, new Generics());
455+
456+
self::assertSame(['T', 'U'], array_keys($generics->items));
457+
self::assertSame('string', $generics->items['T']->toString());
458+
self::assertSame('int', $generics->items['U']->toString());
459+
}
460+
461+
public function test_infer_generics_skips_missing_keys_and_keeps_later_matches(): void
462+
{
463+
$type = ShapedListType::from(
464+
elements: [
465+
new ShapedArrayElement(new IntegerValueType(0), new GenericType('T', new NativeStringType())),
466+
new ShapedArrayElement(new IntegerValueType(1), new GenericType('U', new NativeIntegerType())),
467+
],
468+
isUnsealed: false,
469+
);
470+
471+
$other = new ShapedListType(
472+
elements: [
473+
1 => new ShapedArrayElement(new IntegerValueType(1), new NativeIntegerType()),
474+
],
475+
isUnsealed: false,
476+
);
477+
478+
$generics = $type->inferGenericsFrom($other, new Generics());
479+
480+
self::assertSame(['U'], array_keys($generics->items));
481+
self::assertSame('int', $generics->items['U']->toString());
482+
}
483+
436484
public function test_native_type_is_list(): void
437485
{
438486
self::assertSame('list', $this->type->nativeType()->toString());

0 commit comments

Comments
 (0)