Skip to content

Commit 5e8a5a9

Browse files
veeweeondrejmirtes
authored andcommitted
Fix nullish support for older PSL versions and expand CI matrix
- Use string literal instead of NullishType::class to avoid class-not-found errors on PSL versions without NullishType - Move nullish tests to separate fixtures, gated by class_exists() - Add PHP 8.2, 8.3, 8.4, 8.5 to CI matrix
1 parent fb47a48 commit 5e8a5a9

9 files changed

Lines changed: 141 additions & 95 deletions

File tree

.github/workflows/build.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ jobs:
1919
- "7.4"
2020
- "8.0"
2121
- "8.1"
22+
- "8.2"
23+
- "8.3"
24+
- "8.4"
25+
- "8.5"
2226

2327
steps:
2428
- name: "Checkout"
@@ -77,6 +81,10 @@ jobs:
7781
- "7.4"
7882
- "8.0"
7983
- "8.1"
84+
- "8.2"
85+
- "8.3"
86+
- "8.4"
87+
- "8.5"
8088
dependencies:
8189
- "lowest"
8290
- "highest"
@@ -113,6 +121,10 @@ jobs:
113121
- "7.4"
114122
- "8.0"
115123
- "8.1"
124+
- "8.2"
125+
- "8.3"
126+
- "8.4"
127+
- "8.5"
116128
dependencies:
117129
- "lowest"
118130
- "highest"

src/Type/TypeShapeReturnTypeExtension.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use PHPStan\Type\Generic\GenericObjectType;
1313
use PHPStan\Type\Type;
1414
use PHPStan\Type\TypeCombinator;
15-
use Psl\Type\Internal\NullishType;
1615
use Psl\Type\Internal\OptionalType;
1716
use Psl\Type\TypeInterface;
1817
use function count;
@@ -71,7 +70,7 @@ private function createResult(ConstantArrayType $arrayType): Type
7170
*/
7271
private function extractNullish(Type $type): array
7372
{
74-
$nullishType = $type->getTemplateType(NullishType::class, 'T');
73+
$nullishType = $type->getTemplateType('Psl\Type\Internal\NullishType', 'T');
7574
if ($nullishType instanceof ErrorType) {
7675
return [$type, false];
7776
}

tests/Type/PslTypeSpecifyingExtensionTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ public function dataFileAsserts(): iterable
1717
yield from $this->gatherAssertTypes(__DIR__ . '/data/coerce.php');
1818
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert.php');
1919
yield from $this->gatherAssertTypes(__DIR__ . '/data/matches.php');
20+
if (class_exists(\Psl\Type\Internal\NullishType::class)) {
21+
yield from $this->gatherAssertTypes(__DIR__ . '/data/nullishCoerce.php');
22+
yield from $this->gatherAssertTypes(__DIR__ . '/data/nullishAssert.php');
23+
yield from $this->gatherAssertTypes(__DIR__ . '/data/nullishMatches.php');
24+
}
2025
if (InstalledVersions::satisfies(new VersionParser(), 'azjezz/psl', '<2.0.0')) {
2126
yield from $this->gatherAssertTypes(__DIR__ . '/data/complexTypev1.php');
2227
} else {

tests/Type/data/assert.php

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,37 +29,6 @@ public function assertShape(array $a): void
2929
assertType('array{name: string, age: int, location?: array{city: string, state: string, country: string}}', $b);
3030
}
3131

32-
/**
33-
* @param array<mixed> $a
34-
*/
35-
public function assertNullishShape(array $a): void
36-
{
37-
$specification = Type\shape([
38-
'name' => Type\string(),
39-
'bio' => Type\nullish(Type\string()),
40-
]);
41-
42-
$b = $specification->assert($a);
43-
44-
assertType('array{name: string, bio: string|null}', $a);
45-
assertType('array{name: string, bio: string|null}', $b);
46-
}
47-
48-
/**
49-
* @param array<mixed> $a
50-
*/
51-
public function assertOptionalNullishShape(array $a): void
52-
{
53-
$specification = Type\shape([
54-
'bio' => Type\optional(Type\nullish(Type\string())),
55-
]);
56-
57-
$b = $specification->assert($a);
58-
59-
assertType('array{bio?: string|null}', $a);
60-
assertType('array{bio?: string|null}', $b);
61-
}
62-
6332
public function assertInt($i): void
6433
{
6534
$spec = Type\int();

tests/Type/data/coerce.php

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,35 +29,6 @@ public function coerceShape(array $input): void
2929
assertType('array<mixed>', $input);
3030
}
3131

32-
/**
33-
* @param array<mixed> $input
34-
*/
35-
public function coerceNullishShape(array $input): void
36-
{
37-
$specification = Type\shape([
38-
'name' => Type\string(),
39-
'bio' => Type\nullish(Type\string()),
40-
]);
41-
42-
$output = $specification->coerce($input);
43-
44-
assertType('array{name: string, bio: string|null}', $output);
45-
}
46-
47-
/**
48-
* @param array<mixed> $input
49-
*/
50-
public function coerceOptionalNullishShape(array $input): void
51-
{
52-
$specification = Type\shape([
53-
'bio' => Type\optional(Type\nullish(Type\string())),
54-
]);
55-
56-
$output = $specification->coerce($input);
57-
58-
assertType('array{bio?: string|null}', $output);
59-
}
60-
6132
public function coerceInt($i): void
6233
{
6334
$spec = Type\int();

tests/Type/data/matches.php

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -30,39 +30,6 @@ public function matchesShape(array $a): void
3030
}
3131
}
3232

33-
/**
34-
* @param array<mixed> $a
35-
*/
36-
public function matchesNullishShape(array $a): void
37-
{
38-
$specification = Type\shape([
39-
'name' => Type\string(),
40-
'bio' => Type\nullish(Type\string()),
41-
]);
42-
43-
if ($specification->matches($a)) {
44-
assertType('array{name: string, bio: string|null}', $a);
45-
} else {
46-
assertType('array<mixed>', $a);
47-
}
48-
}
49-
50-
/**
51-
* @param array<mixed> $a
52-
*/
53-
public function matchesOptionalNullishShape(array $a): void
54-
{
55-
$specification = Type\shape([
56-
'bio' => Type\optional(Type\nullish(Type\string())),
57-
]);
58-
59-
if ($specification->matches($a)) {
60-
assertType('array{bio?: string|null}', $a);
61-
} else {
62-
assertType('non-empty-array<mixed>', $a);
63-
}
64-
}
65-
6633
public function matchesInt($i): void
6734
{
6835
$spec = Type\int();

tests/Type/data/nullishAssert.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace PslShapeTest;
4+
5+
use Psl\Type;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
class NullishAssertTest
10+
{
11+
/**
12+
* @param array<mixed> $a
13+
*/
14+
public function assertNullishShape(array $a): void
15+
{
16+
$specification = Type\shape([
17+
'name' => Type\string(),
18+
'bio' => Type\nullish(Type\string()),
19+
]);
20+
21+
$b = $specification->assert($a);
22+
23+
assertType('array{name: string, bio: string|null}', $a);
24+
assertType('array{name: string, bio: string|null}', $b);
25+
}
26+
27+
/**
28+
* @param array<mixed> $a
29+
*/
30+
public function assertOptionalNullishShape(array $a): void
31+
{
32+
$specification = Type\shape([
33+
'bio' => Type\optional(Type\nullish(Type\string())),
34+
]);
35+
36+
$b = $specification->assert($a);
37+
38+
assertType('array{bio?: string|null}', $a);
39+
assertType('array{bio?: string|null}', $b);
40+
}
41+
}

tests/Type/data/nullishCoerce.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace PslShapeTest;
4+
5+
use Psl\Type;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
class NullishCoerceTest
10+
{
11+
/**
12+
* @param array<mixed> $input
13+
*/
14+
public function coerceNullishShape(array $input): void
15+
{
16+
$specification = Type\shape([
17+
'name' => Type\string(),
18+
'bio' => Type\nullish(Type\string()),
19+
]);
20+
21+
$output = $specification->coerce($input);
22+
23+
assertType('array{name: string, bio: string|null}', $output);
24+
}
25+
26+
/**
27+
* @param array<mixed> $input
28+
*/
29+
public function coerceOptionalNullishShape(array $input): void
30+
{
31+
$specification = Type\shape([
32+
'bio' => Type\optional(Type\nullish(Type\string())),
33+
]);
34+
35+
$output = $specification->coerce($input);
36+
37+
assertType('array{bio?: string|null}', $output);
38+
}
39+
}

tests/Type/data/nullishMatches.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace PslShapeTest;
4+
5+
use Psl\Type;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
class NullishMatchesTest
10+
{
11+
/**
12+
* @param array<mixed> $a
13+
*/
14+
public function matchesNullishShape(array $a): void
15+
{
16+
$specification = Type\shape([
17+
'name' => Type\string(),
18+
'bio' => Type\nullish(Type\string()),
19+
]);
20+
21+
if ($specification->matches($a)) {
22+
assertType('array{name: string, bio: string|null}', $a);
23+
} else {
24+
assertType('array<mixed>', $a);
25+
}
26+
}
27+
28+
/**
29+
* @param array<mixed> $a
30+
*/
31+
public function matchesOptionalNullishShape(array $a): void
32+
{
33+
$specification = Type\shape([
34+
'bio' => Type\optional(Type\nullish(Type\string())),
35+
]);
36+
37+
if ($specification->matches($a)) {
38+
assertType('array{bio?: string|null}', $a);
39+
} else {
40+
assertType('non-empty-array<mixed>', $a);
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)