From 8df5aa8525d0b78d75ec262fd4d81244ad59e44c Mon Sep 17 00:00:00 2001 From: Martin Ficzel Date: Thu, 23 Jan 2025 10:36:04 +0100 Subject: [PATCH 1/3] TASK: Move union-type tests into main suite as we only support php 8 nowadays --- .../{PHP8 => }/DummyClassWithUnionTypeHints.php | 2 +- .../Reflection/ReflectionServiceTest.php | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) rename Neos.Flow/Tests/Functional/Reflection/Fixtures/{PHP8 => }/DummyClassWithUnionTypeHints.php (91%) diff --git a/Neos.Flow/Tests/Functional/Reflection/Fixtures/PHP8/DummyClassWithUnionTypeHints.php b/Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeHints.php similarity index 91% rename from Neos.Flow/Tests/Functional/Reflection/Fixtures/PHP8/DummyClassWithUnionTypeHints.php rename to Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeHints.php index 25e2347473..424ce8bb3c 100644 --- a/Neos.Flow/Tests/Functional/Reflection/Fixtures/PHP8/DummyClassWithUnionTypeHints.php +++ b/Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeHints.php @@ -1,5 +1,5 @@ markTestSkipped('Only for PHP 8 with UnionTypes'); - } - $returnTypeA = $this->reflectionService->getMethodDeclaredReturnType(Reflection\Fixtures\PHP8\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypeA'); - $returnTypeB = $this->reflectionService->getMethodDeclaredReturnType(Reflection\Fixtures\PHP8\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypesB'); - $returnTypeC = $this->reflectionService->getMethodDeclaredReturnType(Reflection\Fixtures\PHP8\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypesC'); + $returnTypeA = $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypeA'); + $returnTypeB = $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypesB'); + $returnTypeC = $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypesC'); self::assertEquals('string|false', $returnTypeA); - self::assertEquals('\Neos\Flow\Tests\Functional\Reflection\Fixtures\PHP8\DummyClassWithUnionTypeHints|false', $returnTypeB); - self::assertEquals('?\Neos\Flow\Tests\Functional\Reflection\Fixtures\PHP8\DummyClassWithUnionTypeHints', $returnTypeC); + self::assertEquals('\Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints|false', $returnTypeB); + self::assertEquals('?\Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints', $returnTypeC); } } From 0a8733d4f3967b616c1526e2c4c36da4724b574e Mon Sep 17 00:00:00 2001 From: Martin Ficzel Date: Thu, 23 Jan 2025 14:13:29 +0100 Subject: [PATCH 2/3] TASK: Add test to document union type parameter handling in type hints --- .../Fixtures/DummyClassWithUnionTypeHints.php | 7 +++ .../Reflection/ReflectionServiceTest.php | 57 +++++++++++++++++-- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeHints.php b/Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeHints.php index 424ce8bb3c..7a47bb255f 100644 --- a/Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeHints.php +++ b/Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeHints.php @@ -17,6 +17,13 @@ */ class DummyClassWithUnionTypeHints { + public function methodWithUnionParameters( + string|false $parameterA, + false|DummyClassWithUnionTypeHints $parameterB, + null|DummyClassWithUnionTypeHints $parameterC + ): void { + } + public function methodWithUnionReturnTypeA(): string|false { } diff --git a/Neos.Flow/Tests/Functional/Reflection/ReflectionServiceTest.php b/Neos.Flow/Tests/Functional/Reflection/ReflectionServiceTest.php index b0e1a5dd46..a9a702eabe 100644 --- a/Neos.Flow/Tests/Functional/Reflection/ReflectionServiceTest.php +++ b/Neos.Flow/Tests/Functional/Reflection/ReflectionServiceTest.php @@ -356,12 +356,57 @@ public function annotatedArrayTypeHintsWorkCorrectly() */ public function unionReturnTypesWorkCorrectly() { - $returnTypeA = $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypeA'); - $returnTypeB = $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypesB'); - $returnTypeC = $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypesC'); + $returnTypes = [ + 'returnTypeA' => $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypeA'), + 'returnTypeB' => $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypesB'), + 'returnTypeC' => $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionReturnTypesC'), + ]; + + self::assertEquals( + [ + 'returnTypeA' => 'string|false', + 'returnTypeB' => '\Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints|false', + 'returnTypeC' => '?\Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints', + ], + $returnTypes + ); + } - self::assertEquals('string|false', $returnTypeA); - self::assertEquals('\Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints|false', $returnTypeB); - self::assertEquals('?\Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints', $returnTypeC); + /** + * @test + */ + public function unionParameterTypesWorkCorrectly() + { + $methodWithUnionParameters = $this->reflectionService->getMethodParameters(Fixtures\DummyClassWithUnionTypeHints::class, 'methodWithUnionParameters'); + + $methodWithUnionParametersReduced = array_map( + fn (array $item) => [ + 'type' => $item['type'], + 'class' => $item['class'], + 'allowsNull' => $item['allowsNull'], + ], + $methodWithUnionParameters + ); + + self::assertEquals( + [ + 'parameterA' => [ + 'type' => 'string|false', + 'class' => 'string|false', + 'allowsNull' => false, + ], + 'parameterB' => [ + 'type' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints|false', + 'class' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints|false', + 'allowsNull' => false, + ], + 'parameterC' => [ + 'type' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints', + 'class' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeHints', + 'allowsNull' => true, + ], + ], + $methodWithUnionParametersReduced + ); } } From 8d5438eebf509816f590a47c448d0857d161f28b Mon Sep 17 00:00:00 2001 From: Martin Ficzel Date: Thu, 23 Jan 2025 14:24:57 +0100 Subject: [PATCH 3/3] TASK: Add testclass with union type annotations to prove that reflection handles union type annotations different --- .../DummyClassWithUnionTypeAnnotations.php | 51 +++++++++++++++ .../Reflection/ReflectionServiceTest.php | 64 +++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeAnnotations.php diff --git a/Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeAnnotations.php b/Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeAnnotations.php new file mode 100644 index 0000000000..6fbfb9256b --- /dev/null +++ b/Neos.Flow/Tests/Functional/Reflection/Fixtures/DummyClassWithUnionTypeAnnotations.php @@ -0,0 +1,51 @@ + $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeAnnotations::class, 'methodWithUnionReturnTypeA'), + 'returnTypeB' => $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeAnnotations::class, 'methodWithUnionReturnTypesB'), + 'returnTypeC' => $this->reflectionService->getMethodDeclaredReturnType(Fixtures\DummyClassWithUnionTypeAnnotations::class, 'methodWithUnionReturnTypesC'), + ]; + + self::assertEquals( + [ + 'returnTypeA' => 'string|false', + 'returnTypeB' => '\Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeAnnotations|false', + 'returnTypeC' => '?\Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeAnnotations', + ], + $returnTypes + ); + } + + /** + * @test + */ + public function unionParameterTypeAnnotationsWorkCorrectly() + { + $methodWithUnionParameters = $this->reflectionService->getMethodParameters(Fixtures\DummyClassWithUnionTypeAnnotations::class, 'methodWithUnionParameters'); + + $methodWithUnionParametersReduced = array_map( + fn (array $item) => [ + 'type' => $item['type'], + 'class' => $item['class'], + 'allowsNull' => $item['allowsNull'], + ], + $methodWithUnionParameters + ); + + self::assertEquals( + [ + 'parameterA' => [ + 'type' => 'string|false', + 'class' => 'string|false', + 'allowsNull' => false, + ], + 'parameterB' => [ + 'type' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeAnnotations|false', + 'class' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeAnnotations|false', + 'allowsNull' => false, + ], + 'parameterB1' => [ + 'type' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeAnnotations|false', + 'class' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeAnnotations|false', + 'allowsNull' => false, + ], + 'parameterC' => [ + 'type' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeAnnotations', + 'class' => 'Neos\Flow\Tests\Functional\Reflection\Fixtures\DummyClassWithUnionTypeAnnotations', + 'allowsNull' => true, + ], + ], + $methodWithUnionParametersReduced + ); + } }