From 259e50c3b4f2d356bdcd80cbc4bd2e6e12008b09 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Fri, 28 Jul 2023 15:30:46 -0500 Subject: [PATCH 1/8] Update Php82LanguageFeaturesTest.php Signed-off-by: Nathanael Esayeas --- .../Unit/PHP82/Php82LanguageFeaturesTest.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/Unit/PHP82/Php82LanguageFeaturesTest.php b/tests/Unit/PHP82/Php82LanguageFeaturesTest.php index ca195269f..f83c69463 100644 --- a/tests/Unit/PHP82/Php82LanguageFeaturesTest.php +++ b/tests/Unit/PHP82/Php82LanguageFeaturesTest.php @@ -4,6 +4,7 @@ use Generator; use Mockery\Adapter\Phpunit\MockeryTestCase; +use Mockery\Reflector; use ReflectionType; /** @@ -82,6 +83,25 @@ public static function returnCoVarianceDataProvider(): Generator yield $fixture => [$fixture]; } } + + public function testTypeHintIterableObject(): void + { + $refClass = new \ReflectionClass(ExampleClass::class); + $refMethod = $refClass->getMethods()[0]; + $refParam = $refMethod->getParameters()[0]; + + self::assertSame( + 'iterable|object', + Reflector::getTypeHint($refParam) + ); + } +} + +class ExampleClass +{ + public function __invoke(iterable|object $arg): void + { + } } /** From 77262fc17172d21f27da374e035219627efe7e0a Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Fri, 28 Jul 2023 15:32:08 -0500 Subject: [PATCH 2/8] Update MethodDefinitionPass.php Signed-off-by: Nathanael Esayeas --- library/Mockery/Reflector.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/Mockery/Reflector.php b/library/Mockery/Reflector.php index f6b194ae8..a01839d66 100644 --- a/library/Mockery/Reflector.php +++ b/library/Mockery/Reflector.php @@ -249,6 +249,12 @@ private static function getTypeFromReflectionType(\ReflectionType $type, \Reflec $type->getTypes() ); + $find = ['\Traversable','object', 'array']; + $intersect = array_intersect($find, $types); + if ($find === $intersect) { + $types = ['iterable', 'object']; + } + return implode( '|', array_map( From 0306faac62203690602037488ec0f6a71dc6edc4 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Fri, 28 Jul 2023 15:35:55 -0500 Subject: [PATCH 3/8] Update Bootstrap.php Signed-off-by: Nathanael Esayeas --- tests/Bootstrap.php | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index cf5273e1a..e6ac5574d 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -1,4 +1,6 @@ Date: Fri, 28 Jul 2023 23:26:33 -0500 Subject: [PATCH 4/8] Update Reflector.php Signed-off-by: Nathanael Esayeas --- library/Mockery/Reflector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Mockery/Reflector.php b/library/Mockery/Reflector.php index a01839d66..dd544dbda 100644 --- a/library/Mockery/Reflector.php +++ b/library/Mockery/Reflector.php @@ -252,7 +252,7 @@ private static function getTypeFromReflectionType(\ReflectionType $type, \Reflec $find = ['\Traversable','object', 'array']; $intersect = array_intersect($find, $types); if ($find === $intersect) { - $types = ['iterable', 'object']; + $types = ['iterable', 'object'] + array_diff($types, $find); } return implode( From 7bf9c0288c5053059b825d1f87cf8f3c6257b332 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Fri, 28 Jul 2023 23:27:34 -0500 Subject: [PATCH 5/8] test IterableObjectString Signed-off-by: Nathanael Esayeas --- .../Unit/PHP82/Php82LanguageFeaturesTest.php | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/tests/Unit/PHP82/Php82LanguageFeaturesTest.php b/tests/Unit/PHP82/Php82LanguageFeaturesTest.php index f83c69463..fee961728 100644 --- a/tests/Unit/PHP82/Php82LanguageFeaturesTest.php +++ b/tests/Unit/PHP82/Php82LanguageFeaturesTest.php @@ -86,24 +86,62 @@ public static function returnCoVarianceDataProvider(): Generator public function testTypeHintIterableObject(): void { - $refClass = new \ReflectionClass(ExampleClass::class); + $refClass = new \ReflectionClass(IterableObject::class); $refMethod = $refClass->getMethods()[0]; $refParam = $refMethod->getParameters()[0]; self::assertSame( - 'iterable|object', + 'iterable|object', + Reflector::getTypeHint($refParam) + ); + } + + public function testTypeHintIterableObjectString(): void + { + $refClass = new \ReflectionClass(IterableObjectString::class); + $refMethod = $refClass->getMethods()[0]; + $refParam = $refMethod->getParameters()[0]; + + self::assertSame( + 'iterable|object|string', + Reflector::getTypeHint($refParam) + ); + } + + public function testTypeHintIIterableStdClassString(): void + { + $refClass = new \ReflectionClass(IterableStdClassString::class); + $refMethod = $refClass->getMethods()[0]; + $refParam = $refMethod->getParameters()[0]; + + self::assertSame( + '\Traversable|\stdClass|array|string', Reflector::getTypeHint($refParam) ); } } -class ExampleClass +class IterableObject { public function __invoke(iterable|object $arg): void { } } +class IterableObjectString +{ + public function __invoke(iterable|object|string $arg): void + { + } +} + +class IterableStdClassString +{ + public function __invoke(iterable|\stdClass|string $arg): void + { + } +} + /** * The test fixtures in this directory have been directly copied and pasted from the source mentioned, * which is the PHP RFC (Request for Comments) titled "DNF Types" available at https://wiki.php.net/rfc/dnf_types. From e91dc181d1a918676f135a2aaedb31f87a3b3848 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Sat, 29 Jul 2023 00:03:59 -0500 Subject: [PATCH 6/8] Use const and add tests Signed-off-by: Nathanael Esayeas --- library/Mockery/Reflector.php | 9 ++--- tests/Mockery/ReflectorTest.php | 64 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 tests/Mockery/ReflectorTest.php diff --git a/library/Mockery/Reflector.php b/library/Mockery/Reflector.php index dd544dbda..e3c095923 100644 --- a/library/Mockery/Reflector.php +++ b/library/Mockery/Reflector.php @@ -15,6 +15,8 @@ */ class Reflector { + private const TRAVERSABLE_OBJECT_ARRAY = ['\Traversable','object', 'array']; + private const ITERABLE_OBJECT = ['iterable','object']; /** * Determine if the parameter is typed as an array. * @@ -249,10 +251,9 @@ private static function getTypeFromReflectionType(\ReflectionType $type, \Reflec $type->getTypes() ); - $find = ['\Traversable','object', 'array']; - $intersect = array_intersect($find, $types); - if ($find === $intersect) { - $types = ['iterable', 'object'] + array_diff($types, $find); + $intersect = array_intersect(self::TRAVERSABLE_OBJECT_ARRAY, $types); + if (self::TRAVERSABLE_OBJECT_ARRAY === $intersect) { + $types = self::ITERABLE_OBJECT + array_diff($types, self::TRAVERSABLE_OBJECT_ARRAY); } return implode( diff --git a/tests/Mockery/ReflectorTest.php b/tests/Mockery/ReflectorTest.php new file mode 100644 index 000000000..74a2606f4 --- /dev/null +++ b/tests/Mockery/ReflectorTest.php @@ -0,0 +1,64 @@ +getMethods()[0]; + $refParam = $refMethod->getParameters()[0]; + + self::assertSame( + $expectedTypeHint, + Reflector::getTypeHint($refParam) + ); + } + + public static function typeHintDataProvider(): Generator + { + $isPHPLessThan8 = \PHP_VERSION_ID < 80000; + yield from [ + [ParentClass::class, '\Mockery\Tests\Mockery\ParentClass'], + [ChildClass::class, '\Mockery\Tests\Mockery\ParentClass'], + NullableObject::class => [NullableObject::class, $isPHPLessThan8 ? '?object' : 'object|null'], + ]; + } + +} + +class ParentClass +{ + public function __invoke(self $arg): void + { + } +} + +class ChildClass extends ParentClass +{ + public function __invoke(parent $arg): void + { + } +} + +class NullableObject +{ + public function __invoke(?object $arg): void + { + } +} From 98bc863ac599e57f5e4dffc040bb9a12a25ccb7c Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Sat, 29 Jul 2023 09:34:50 -0500 Subject: [PATCH 7/8] Update Reflector.php Signed-off-by: Nathanael Esayeas Co-authored-by: Girgias <7906688+girgias@users.noreply.github.com> --- library/Mockery/Reflector.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/Mockery/Reflector.php b/library/Mockery/Reflector.php index e3c095923..0117cbeec 100644 --- a/library/Mockery/Reflector.php +++ b/library/Mockery/Reflector.php @@ -15,8 +15,8 @@ */ class Reflector { - private const TRAVERSABLE_OBJECT_ARRAY = ['\Traversable','object', 'array']; - private const ITERABLE_OBJECT = ['iterable','object']; + private const TRAVERSABLE_ARRAY = ['\Traversable', 'array']; + private const ITERABLE = ['iterable']; /** * Determine if the parameter is typed as an array. * @@ -251,9 +251,9 @@ private static function getTypeFromReflectionType(\ReflectionType $type, \Reflec $type->getTypes() ); - $intersect = array_intersect(self::TRAVERSABLE_OBJECT_ARRAY, $types); - if (self::TRAVERSABLE_OBJECT_ARRAY === $intersect) { - $types = self::ITERABLE_OBJECT + array_diff($types, self::TRAVERSABLE_OBJECT_ARRAY); + $intersect = array_intersect(self::TRAVERSABLE_ARRAY, $types); + if (self::TRAVERSABLE_ARRAY === $intersect) { + $types = self::ITERABLE + array_diff($types, self::TRAVERSABLE_ARRAY); } return implode( From 58538572a85607bda5840aa8ffe824a8d70b3678 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Sat, 29 Jul 2023 09:37:53 -0500 Subject: [PATCH 8/8] Fix test Signed-off-by: Nathanael Esayeas --- tests/Unit/PHP82/Php82LanguageFeaturesTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/PHP82/Php82LanguageFeaturesTest.php b/tests/Unit/PHP82/Php82LanguageFeaturesTest.php index fee961728..260b47942 100644 --- a/tests/Unit/PHP82/Php82LanguageFeaturesTest.php +++ b/tests/Unit/PHP82/Php82LanguageFeaturesTest.php @@ -115,7 +115,7 @@ public function testTypeHintIIterableStdClassString(): void $refParam = $refMethod->getParameters()[0]; self::assertSame( - '\Traversable|\stdClass|array|string', + 'iterable|\stdClass|string', Reflector::getTypeHint($refParam) ); }