diff --git a/phpunit/src/ReflectionTest.php b/phpunit/src/ReflectionTest.php index 1158c2cf..effac68c 100644 --- a/phpunit/src/ReflectionTest.php +++ b/phpunit/src/ReflectionTest.php @@ -7,6 +7,25 @@ use PhpAot\Php\Reflection; class ReflectionTest extends TestCase { + public function testGetFunctionReturnTypeUnionReturnsNull(): void + { + eval('function php_aot_reflection_union_return(): int|string { return 1; }'); + $this->assertNull(Reflection::getFunctionReturnType('php_aot_reflection_union_return')); + } + + public function testGetFunctionReturnTypeIntersectionReturnsNull(): void + { + eval(' + interface PhpAotReflectionI1 {} + interface PhpAotReflectionI2 {} + final class PhpAotReflectionBoth implements PhpAotReflectionI1, PhpAotReflectionI2 {} + function php_aot_reflection_intersection_return(): PhpAotReflectionI1&PhpAotReflectionI2 { + return new PhpAotReflectionBoth(); + } + '); + $this->assertNull(Reflection::getFunctionReturnType('php_aot_reflection_intersection_return')); + } + public function testIsInternalClass(): void { // Standard PHP internal classes @@ -125,6 +144,33 @@ class ReflectionTest extends TestCase $this->assertEquals('string', $type); } + public function testGetMethodReturnTypeUnionReturnsNull(): void + { + eval(' + class PhpAotReflectionUnionMethodReturn { + public function value(): int|string { + return 1; + } + } + '); + $this->assertNull(Reflection::getMethodReturnType('PhpAotReflectionUnionMethodReturn', 'value')); + } + + public function testGetMethodReturnTypeIntersectionReturnsNull(): void + { + eval(' + interface PhpAotReflectionMethodI1 {} + interface PhpAotReflectionMethodI2 {} + final class PhpAotReflectionMethodBoth implements PhpAotReflectionMethodI1, PhpAotReflectionMethodI2 {} + class PhpAotReflectionIntersectionMethodReturn { + public function value(): PhpAotReflectionMethodI1&PhpAotReflectionMethodI2 { + return new PhpAotReflectionMethodBoth(); + } + } + '); + $this->assertNull(Reflection::getMethodReturnType('PhpAotReflectionIntersectionMethodReturn', 'value')); + } + public function testGetMethodReturnTypeNonexistent(): void { $type = Reflection::getMethodReturnType('NonExistent_' . uniqid(), 'test'); diff --git a/src/Php/Reflection.php b/src/Php/Reflection.php index 9dc89764..5c380d3f 100644 --- a/src/Php/Reflection.php +++ b/src/Php/Reflection.php @@ -93,15 +93,7 @@ class Reflection if (!$func) { return null; } - $returnType = $func->getReturnType(); - if (!$returnType) { - return null; - } - if ($returnType instanceof \ReflectionUnionType) { - return null; - } - - return $returnType->getName(); + return self::extractNamedReturnType($func->getReturnType()); } public static function getFunctionParameter(string $fn, int $index): ?\ReflectionParameter @@ -172,7 +164,7 @@ class Reflection return null; } $methodDef = $classRef->getMethod($method); - return $methodDef->getReturnType() ? $methodDef->getReturnType()->getName() : null; + return self::extractNamedReturnType($methodDef->getReturnType()); } public static function isAbstractClass(string $name): bool @@ -215,4 +207,13 @@ class Reflection $lastParam = end($params); return $lastParam->isVariadic() ? $lastParam : null; } + + private static function extractNamedReturnType(?\ReflectionType $returnType): ?string + { + if (!$returnType instanceof \ReflectionNamedType) { + return null; + } + + return $returnType->getName(); + } }