From 5741440cd18f56080691cd26e1bf47ac83c93bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Birkl=C3=A9?= Date: Tue, 2 Jul 2024 17:37:31 +0200 Subject: [PATCH 1/2] Fix Parsing of Complex Type Annotations in DataIterableAnnotation --- .../Annotations/DataIterableAnnotationReader.php | 3 ++- tests/Fakes/CollectionDataAnnotationsData.php | 8 ++++++++ tests/Fakes/CollectionNonDataAnnotationsData.php | 8 ++++++++ .../DataIterableAnnotationReaderTest.php | 14 ++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/Support/Annotations/DataIterableAnnotationReader.php b/src/Support/Annotations/DataIterableAnnotationReader.php index 4868d532..98835f64 100644 --- a/src/Support/Annotations/DataIterableAnnotationReader.php +++ b/src/Support/Annotations/DataIterableAnnotationReader.php @@ -51,6 +51,7 @@ protected function get( $kindPattern = '(?:@property|@var|@param)\s*'; $fqsenPattern = '[\\\\a-z0-9_\|]+'; $typesPattern = '[\\\\a-z0-9_\\|\\[\\]]+'; + $optionalTypesPattern = '(?:'.$typesPattern.')*'; $keyPattern = '(?int|string|int\|string|string\|int|array-key)'; $parameterPattern = '\s*\$?(?[a-z0-9_]+)?'; @@ -61,7 +62,7 @@ protected function get( ); preg_match_all( - "/{$kindPattern}(?{$fqsenPattern})<(?:{$keyPattern}\s*?,\s*?)?(?{$fqsenPattern})>{$parameterPattern}/i", + "/{$kindPattern}(?{$fqsenPattern})<(?:{$keyPattern}\s*?,\s*?)?(?{$fqsenPattern})>{$optionalTypesPattern}{$parameterPattern}/i", $comment, $collectionMatches, ); diff --git a/tests/Fakes/CollectionDataAnnotationsData.php b/tests/Fakes/CollectionDataAnnotationsData.php index 186b00a3..05f72ed4 100644 --- a/tests/Fakes/CollectionDataAnnotationsData.php +++ b/tests/Fakes/CollectionDataAnnotationsData.php @@ -14,6 +14,7 @@ * @property array<\Spatie\LaravelData\Tests\Fakes\SimpleData> $propertyQ * @property \Spatie\LaravelData\Tests\Fakes\SimpleData[] $propertyR * @property array $propertyS + * @property \Illuminate\Support\Collection<\Spatie\LaravelData\Tests\Fakes\SimpleData>|null $propertyT */ class CollectionDataAnnotationsData { @@ -67,6 +68,11 @@ class CollectionDataAnnotationsData public array $propertyS; + public ?array $propertyT; + + /** @var \Illuminate\Support\Collection<\Spatie\LaravelData\Tests\Fakes\SimpleData>|null */ + public ?array $propertyU; + /** * @param \Spatie\LaravelData\Tests\Fakes\SimpleData[]|null $paramA * @param null|\Spatie\LaravelData\Tests\Fakes\SimpleData[] $paramB @@ -78,6 +84,7 @@ class CollectionDataAnnotationsData * @param array $paramH * @param array $paramJ * @param array $paramI + * @param \Spatie\LaravelData\DataCollection<\Spatie\LaravelData\Tests\Fakes\SimpleData>|null $paramK */ public function method( array $paramA, @@ -89,6 +96,7 @@ public function method( array $paramG, array $paramJ, array $paramI, + ?array $paramK, ) { } diff --git a/tests/Fakes/CollectionNonDataAnnotationsData.php b/tests/Fakes/CollectionNonDataAnnotationsData.php index fc6b3bd9..1e858f7f 100644 --- a/tests/Fakes/CollectionNonDataAnnotationsData.php +++ b/tests/Fakes/CollectionNonDataAnnotationsData.php @@ -11,6 +11,7 @@ * @property \Spatie\LaravelData\Tests\Fakes\Enums\DummyBackedEnum[] $propertyM * @property array<\Spatie\LaravelData\Tests\Fakes\Enums\DummyBackedEnum> $propertyN * @property array $propertyO + * @property array|null $propertyQ */ class CollectionNonDataAnnotationsData { @@ -58,6 +59,11 @@ class CollectionNonDataAnnotationsData /** @var \Illuminate\Support\Collection */ public Collection $propertyP; + public array $propertyQ; + + /** @var \Illuminate\Support\Collection|null */ + public ?Collection $propertyR; + /** * @param \Spatie\LaravelData\Tests\Fakes\Enums\DummyBackedEnum[]|null $paramA * @param null|\Spatie\LaravelData\Tests\Fakes\Enums\DummyBackedEnum[] $paramB @@ -69,6 +75,7 @@ class CollectionNonDataAnnotationsData * @param array $paramH * @param array $paramJ * @param array $paramI + * @param \Spatie\LaravelData\DataCollection<\Spatie\LaravelData\Tests\Fakes\Enums\DummyBackedEnum>|null $paramK */ public function method( array $paramA, @@ -80,6 +87,7 @@ public function method( array $paramG, array $paramJ, array $paramI, + ?array $paramK, ) { } diff --git a/tests/Support/Annotations/DataIterableAnnotationReaderTest.php b/tests/Support/Annotations/DataIterableAnnotationReaderTest.php index ee6b528f..4af7b80f 100644 --- a/tests/Support/Annotations/DataIterableAnnotationReaderTest.php +++ b/tests/Support/Annotations/DataIterableAnnotationReaderTest.php @@ -81,6 +81,11 @@ function (string $property, ?DataIterableAnnotation $expected) { 'property' => 'propertyM', 'expected' => new DataIterableAnnotation(SimpleData::class, isData: true), ]; + + yield 'propertyU' => [ + 'property' => 'propertyU', + 'expected' => new DataIterableAnnotation(SimpleData::class, isData: true), + ]; }); it('can get the data class for a data collection by class annotation', function () { @@ -93,6 +98,7 @@ function (string $property, ?DataIterableAnnotation $expected) { new DataIterableAnnotation(SimpleData::class, isData: true, property: 'propertyQ'), new DataIterableAnnotation(SimpleData::class, isData: true, property: 'propertyR'), new DataIterableAnnotation(SimpleData::class, isData: true, property: 'propertyS'), + new DataIterableAnnotation(SimpleData::class, isData: true, property: 'propertyT'), ]); }); @@ -110,6 +116,7 @@ function (string $property, ?DataIterableAnnotation $expected) { new DataIterableAnnotation(SimpleData::class, isData: true, property: 'paramH'), new DataIterableAnnotation(SimpleData::class, isData: true, keyType: 'int', property: 'paramJ'), new DataIterableAnnotation(SimpleData::class, isData: true, keyType: 'int', property: 'paramI'), + new DataIterableAnnotation(SimpleData::class, isData: true, property: 'paramK'), ]); }); @@ -185,6 +192,11 @@ function (string $property, ?DataIterableAnnotation $expected) { 'property' => 'propertyP', 'expected' => new DataIterableAnnotation(Error::class, isData: true), ]; + + yield 'propertyR' => [ + 'property' => 'propertyR', + 'expected' => new DataIterableAnnotation(Error::class, isData: true), + ]; }); it('can get the iterable class for a collection by class annotation', function () { @@ -194,6 +206,7 @@ function (string $property, ?DataIterableAnnotation $expected) { new DataIterableAnnotation(DummyBackedEnum::class, isData: false, property: 'propertyM'), new DataIterableAnnotation(DummyBackedEnum::class, isData: false, property: 'propertyN'), new DataIterableAnnotation(DummyBackedEnum::class, isData: false, property: 'propertyO'), + new DataIterableAnnotation(DummyBackedEnum::class, isData: false, property: 'propertyQ'), ]); }); @@ -211,6 +224,7 @@ function (string $property, ?DataIterableAnnotation $expected) { new DataIterableAnnotation(DummyBackedEnum::class, isData: false, property: 'paramH'), new DataIterableAnnotation(DummyBackedEnum::class, isData: false, keyType: 'int', property: 'paramJ'), new DataIterableAnnotation(DummyBackedEnum::class, isData: false, keyType: 'int', property: 'paramI'), + new DataIterableAnnotation(DummyBackedEnum::class, isData: false, property: 'paramK'), ]); }); From 478c669ed5a293a863c7920c83b60366c472809d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Birkl=C3=A9?= Date: Wed, 3 Jul 2024 08:32:01 +0200 Subject: [PATCH 2/2] Cleanup: eliminate redundant optionalTypesPattern in preg_match_all for collections --- src/Support/Annotations/DataIterableAnnotationReader.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Support/Annotations/DataIterableAnnotationReader.php b/src/Support/Annotations/DataIterableAnnotationReader.php index 98835f64..c3a63308 100644 --- a/src/Support/Annotations/DataIterableAnnotationReader.php +++ b/src/Support/Annotations/DataIterableAnnotationReader.php @@ -51,7 +51,6 @@ protected function get( $kindPattern = '(?:@property|@var|@param)\s*'; $fqsenPattern = '[\\\\a-z0-9_\|]+'; $typesPattern = '[\\\\a-z0-9_\\|\\[\\]]+'; - $optionalTypesPattern = '(?:'.$typesPattern.')*'; $keyPattern = '(?int|string|int\|string|string\|int|array-key)'; $parameterPattern = '\s*\$?(?[a-z0-9_]+)?'; @@ -62,7 +61,7 @@ protected function get( ); preg_match_all( - "/{$kindPattern}(?{$fqsenPattern})<(?:{$keyPattern}\s*?,\s*?)?(?{$fqsenPattern})>{$optionalTypesPattern}{$parameterPattern}/i", + "/{$kindPattern}(?{$fqsenPattern})<(?:{$keyPattern}\s*?,\s*?)?(?{$fqsenPattern})>(?:{$typesPattern})*{$parameterPattern}/i", $comment, $collectionMatches, );