Skip to content

Commit 0a888dc

Browse files
committed
refactor types
1 parent 6323610 commit 0a888dc

4 files changed

Lines changed: 68 additions & 19 deletions

File tree

src/Converters/ClosureConverter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public function convert(): ObjectSchema
5454
/**
5555
* Create a schema from a given type.
5656
*
57-
* @param array<array-key, array{name: string, type: string|null, description: string|null}> $docParams
57+
* @param array<array-key, array{name: string, types: array<array-key, string>, description: string|null}> $docParams
5858
*/
5959
protected static function getSchemaFromReflectionParameter(
6060
ReflectionParameter $parameter,

src/Support/DocParser.php

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66

77
use PHPStan\PhpDocParser\Lexer\Lexer;
88
use PHPStan\PhpDocParser\ParserConfig;
9+
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
910
use PHPStan\PhpDocParser\Parser\TypeParser;
1011
use PHPStan\PhpDocParser\Parser\PhpDocParser;
1112
use PHPStan\PhpDocParser\Parser\TokenIterator;
1213
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
14+
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
1315
use PHPStan\PhpDocParser\Parser\ConstExprParser;
1416
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode;
17+
use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
1518
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
1619
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
1720
use PHPStan\PhpDocParser\Ast\PhpDoc\TypelessParamTagValueNode;
@@ -36,14 +39,14 @@ public function description(): ?string
3639
/**
3740
* Get the parameters from the docblock.
3841
*
39-
* @return array<array-key, array{name: string, type: string|null, description: string|null}>
42+
* @return array<array-key, array{name: string, types: array<array-key, string>, description: string|null}>
4043
*/
4144
public function params(): array
4245
{
4346
return array_map(
4447
static fn(ParamTagValueNode|TypelessParamTagValueNode $param): array => [
4548
'name' => ltrim($param->parameterName, '$'),
46-
'type' => $param instanceof TypelessParamTagValueNode ? null : (string) $param->type,
49+
'types' => self::mapParamToTypes($param),
4750
'description' => empty($param->description) ? null : $param->description,
4851
],
4952
array_merge(
@@ -53,6 +56,30 @@ public function params(): array
5356
);
5457
}
5558

59+
/**
60+
* Map the parameter to its types.
61+
*
62+
* @return array<array-key, string>
63+
*/
64+
protected static function mapParamToTypes(ParamTagValueNode|TypelessParamTagValueNode $param): array
65+
{
66+
if ($param instanceof TypelessParamTagValueNode) {
67+
return [];
68+
}
69+
70+
return match (true) {
71+
$param->type instanceof UnionTypeNode => array_map(
72+
fn(TypeNode $type): string => (string) $type,
73+
$param->type->types,
74+
),
75+
$param->type instanceof NullableTypeNode => [
76+
(string) $param->type->type,
77+
'null',
78+
],
79+
default => [(string) $param->type],
80+
};
81+
}
82+
5683
/**
5784
* Parse the docblock into a PHPStan PhpDocNode.
5885
*/

tests/Unit/ConditionalSchemaTest.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Cortex\JsonSchema\Tests\Unit;
66

7+
use ArrayObject;
78
use Cortex\JsonSchema\Enums\SchemaFormat;
89
use Cortex\JsonSchema\Types\ObjectSchema;
910
use Cortex\JsonSchema\SchemaFactory as Schema;
@@ -45,7 +46,7 @@
4546
// Business type requires company_name and tax_id
4647
expect(fn() => $schema->validate([
4748
'type' => 'business',
48-
]))->toThrow(SchemaException::class);
49+
]))->toThrow(SchemaException::class, "The data is not valid on 'then' branch");
4950

5051
expect(fn() => $schema->validate([
5152
'type' => 'business',
@@ -57,7 +58,7 @@
5758
expect(fn() => $schema->validate([
5859
'type' => 'personal',
5960
'company_name' => 'Acme Inc',
60-
]))->toThrow(SchemaException::class);
61+
]))->toThrow(SchemaException::class, "const contains a value that doesn't match the type keyword");
6162

6263
expect(fn() => $schema->validate([
6364
'type' => 'personal',
@@ -202,9 +203,9 @@
202203

203204
expect(fn() => $schema->validate([
204205
'credit_card' => 'invalid',
205-
]))->toThrow(SchemaException::class);
206+
]))->toThrow(SchemaException::class, 'The data should match at least one schema');
206207

207-
expect(fn() => $schema->validate([]))->toThrow(SchemaException::class);
208+
expect(fn() => $schema->validate(new ArrayObject()))->toThrow(SchemaException::class, 'The data should match at least one schema');
208209
});
209210

210211
it('can create a schema with oneOf condition', function (): void {

tests/Unit/Support/DocParserTest.php

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,55 @@
2020
expect($parser->description())->toBeNull();
2121
});
2222

23-
it('can parse params', function (): void {
24-
$docblock = '/**
25-
@param ?string $nickname The nickname of the user
26-
@param ?int $age The age of the user
27-
@param float|int $price The price of the product
28-
@param $status
29-
*/';
23+
it('can parse params and description', function (): void {
24+
$docblock = <<<'EOD'
25+
/**
26+
* This is the description
27+
* @param ?string $nickname The nickname of the user
28+
* @param ?int $age The age of the user
29+
* @param float|int $price The price of the product
30+
* @param \Cortex\JsonSchema\Tests\Unit\Support\DocParserTest $test The test
31+
* @param $any
32+
*/
33+
EOD;
3034
$parser = new DocParser($docblock);
3135

36+
expect($parser->description())->toBe('This is the description');
3237
expect($parser->params())->toBe([
3338
[
3439
'name' => 'nickname',
35-
'type' => '?string',
40+
'types' => [
41+
'string',
42+
'null',
43+
],
3644
'description' => 'The nickname of the user',
3745
],
3846
[
3947
'name' => 'age',
40-
'type' => '?int',
48+
'types' => [
49+
'int',
50+
'null',
51+
],
4152
'description' => 'The age of the user',
4253
],
4354
[
4455
'name' => 'price',
45-
'type' => '(float | int)',
56+
'types' => [
57+
'float',
58+
'int',
59+
],
4660
'description' => 'The price of the product',
4761
],
4862
[
49-
'name' => 'status',
50-
'type' => null,
63+
'name' => 'test',
64+
'types' => [
65+
'\Cortex\JsonSchema\Tests\Unit\Support\DocParserTest',
66+
],
67+
'description' => 'The test',
68+
],
69+
[
70+
'name' => 'any',
71+
'types' => [],
5172
'description' => null,
5273
],
5374
]);

0 commit comments

Comments
 (0)