Skip to content

Commit 93af1e7

Browse files
author
Ivan Kurnosov
committed
Added different message to distinguish between two cases:
a) the value at the path is of the wrong type b) the path does not exist .
1 parent 6683d60 commit 93af1e7

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

src/Psl/Type/Exception/AssertException.php

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,28 @@ final class AssertException extends Exception
1717
/**
1818
* @param list<string> $paths
1919
*/
20-
private function __construct(string $actual, string $expected, array $paths = [], ?Throwable $previous = null)
20+
private function __construct(?string $actual, string $expected, array $paths = [], ?Throwable $previous = null)
2121
{
2222
$first = $previous instanceof Exception ? $previous->getFirstFailingActualType() : $actual;
2323

24-
parent::__construct(
25-
Str\format(
24+
if ($first !== null) {
25+
$message = Str\format(
2626
'Expected "%s", got "%s"%s.',
2727
$expected,
2828
$first,
29-
$paths ? ' at path "' . Str\join($paths, '.') . '"' : ''
30-
),
31-
$actual,
29+
$paths ? ' at path "' . Str\join($paths, '.') . '"' : '',
30+
);
31+
} else {
32+
$message = Str\format(
33+
'Expected "%s", received no value at path "%s".',
34+
$expected,
35+
Str\join($paths, '.'),
36+
);
37+
}
38+
39+
parent::__construct(
40+
$message,
41+
$actual ?? 'null',
3242
$paths,
3343
$previous
3444
);
@@ -51,4 +61,14 @@ public static function withValue(
5161

5262
return new self(get_debug_type($value), $expected_type, Vec\filter_nulls($paths), $previous);
5363
}
64+
65+
public static function withoutValue(
66+
string $expected_type,
67+
?string $path = null,
68+
?Throwable $previous = null
69+
): self {
70+
$paths = $previous instanceof Exception ? [$path, ...$previous->getPaths()] : [$path];
71+
72+
return new self(null, $expected_type, Vec\filter_nulls($paths), $previous);
73+
}
5474
}

src/Psl/Type/Exception/CoercionException.php

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,30 @@ final class CoercionException extends Exception
1717
/**
1818
* @param list<string> $paths
1919
*/
20-
private function __construct(string $actual, string $target, array $paths = [], ?Throwable $previous = null)
20+
private function __construct(?string $actual, string $target, array $paths = [], ?Throwable $previous = null)
2121
{
2222
$first = $previous instanceof Exception ? $previous->getFirstFailingActualType() : $actual;
2323

24-
parent::__construct(
25-
Str\format(
24+
if ($first !== null) {
25+
$message = Str\format(
2626
'Could not coerce "%s" to type "%s"%s%s.',
2727
$first,
2828
$target,
2929
$paths ? ' at path "' . Str\join($paths, '.') . '"' : '',
3030
$previous && !$previous instanceof self ? ': ' . $previous->getMessage() : '',
31-
),
32-
$actual,
31+
);
32+
} else {
33+
$message = Str\format(
34+
'Could not coerce to type "%s" at path "%s" as the value was not passed%s.',
35+
$target,
36+
Str\join($paths, '.'),
37+
$previous && !$previous instanceof self ? ': ' . $previous->getMessage() : '',
38+
);
39+
}
40+
41+
parent::__construct(
42+
$message,
43+
$actual ?? 'null',
3344
$paths,
3445
$previous
3546
);
@@ -52,4 +63,14 @@ public static function withValue(
5263

5364
return new self(get_debug_type($value), $target, Vec\filter_nulls($paths), $previous);
5465
}
66+
67+
public static function withoutValue(
68+
string $target,
69+
?string $path = null,
70+
?Throwable $previous = null
71+
): self {
72+
$paths = $previous instanceof Exception ? [$path, ...$previous->getPaths()] : [$path];
73+
74+
return new self(null, $target, Vec\filter_nulls($paths), $previous);
75+
}
5576
}

src/Psl/Type/Internal/ShapeType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ private function coerceIterable(mixed $value): array
144144
continue;
145145
}
146146

147-
throw CoercionException::withValue(null, $this->toString(), PathExpression::path($element));
147+
throw CoercionException::withoutValue($this->toString(), PathExpression::path($element));
148148
}
149149
} catch (CoercionException $e) {
150150
throw match (true) {
@@ -196,7 +196,7 @@ public function assert(mixed $value): array
196196
continue;
197197
}
198198

199-
throw AssertException::withValue(null, $this->toString(), PathExpression::path($element));
199+
throw AssertException::withoutValue($this->toString(), PathExpression::path($element));
200200
}
201201
} catch (AssertException $e) {
202202
throw match (true) {

tests/unit/Type/ShapeTypeTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public static function provideAssertExceptionExpectations(): iterable
216216
'name' => Type\string(),
217217
]),
218218
[],
219-
'Expected "array{\'name\': string}", got "null" at path "name".'
219+
'Expected "array{\'name\': string}", received no value at path "name".'
220220
];
221221
yield 'invalid key' => [
222222
Type\shape([
@@ -247,7 +247,7 @@ public static function provideCoerceExceptionExpectations(): iterable
247247
'name' => Type\string(),
248248
]),
249249
[],
250-
'Could not coerce "null" to type "array{\'name\': string}" at path "name".'
250+
'Could not coerce to type "array{\'name\': string}" at path "name" as the value was not passed.'
251251
];
252252
yield 'invalid key' => [
253253
Type\shape([
@@ -295,7 +295,7 @@ public static function provideCoerceExceptionExpectations(): iterable
295295
(static function () {
296296
yield null => 'nope';
297297
})(),
298-
'Could not coerce "null" to type "array{\'id\': int}" at path "id".'
298+
'Could not coerce to type "array{\'id\': int}" at path "id" as the value was not passed.'
299299
];
300300
yield 'iterator yielding object key' => [
301301
Type\shape([
@@ -305,7 +305,7 @@ public static function provideCoerceExceptionExpectations(): iterable
305305
yield (new class () {
306306
}) => 'nope';
307307
})(),
308-
'Could not coerce "null" to type "array{\'id\': int}" at path "id".'
308+
'Could not coerce to type "array{\'id\': int}" at path "id" as the value was not passed.'
309309
];
310310
}
311311

0 commit comments

Comments
 (0)