From b16fa8e4b803d69b33554391c9bb6d7840aaad58 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 3 Jan 2022 21:09:10 +0100 Subject: [PATCH] ReflectionNamedType with mixed allows null --- src/Reflection/Adapter/ReflectionNamedType.php | 4 +++- src/Reflection/Adapter/ReflectionType.php | 2 +- src/Reflection/ReflectionNamedType.php | 2 +- .../Reflection/Adapter/ReflectionTypeTest.php | 15 +++++++++++++++ test/unit/Reflection/ReflectionNamedTypeTest.php | 6 ++++++ 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Reflection/Adapter/ReflectionNamedType.php b/src/Reflection/Adapter/ReflectionNamedType.php index 62c9dc4d2..744844221 100644 --- a/src/Reflection/Adapter/ReflectionNamedType.php +++ b/src/Reflection/Adapter/ReflectionNamedType.php @@ -7,6 +7,8 @@ use ReflectionNamedType as CoreReflectionNamedType; use Roave\BetterReflection\Reflection\ReflectionNamedType as BetterReflectionNamedType; +use function strtolower; + /** * @psalm-suppress MissingImmutableAnnotation */ @@ -23,7 +25,7 @@ public function getName(): string public function __toString(): string { - return ($this->allowsNull ? '?' : '') + return ($this->allowsNull && strtolower($this->betterReflectionType->getName()) !== 'mixed' ? '?' : '') . $this->betterReflectionType->__toString(); } diff --git a/src/Reflection/Adapter/ReflectionType.php b/src/Reflection/Adapter/ReflectionType.php index 12d39f411..20888acea 100644 --- a/src/Reflection/Adapter/ReflectionType.php +++ b/src/Reflection/Adapter/ReflectionType.php @@ -43,6 +43,6 @@ public static function fromTypeOrNull(BetterReflectionNamedType|BetterReflection return new ReflectionIntersectionType($betterReflectionType); } - return new ReflectionNamedType($betterReflectionType, false); + return new ReflectionNamedType($betterReflectionType, $betterReflectionType->allowsNull()); } } diff --git a/src/Reflection/ReflectionNamedType.php b/src/Reflection/ReflectionNamedType.php index 276cbf033..1ffc5cfe3 100644 --- a/src/Reflection/ReflectionNamedType.php +++ b/src/Reflection/ReflectionNamedType.php @@ -103,7 +103,7 @@ public function getClass(): ReflectionClass public function allowsNull(): bool { - return false; + return strtolower($this->name) === 'mixed'; } public function __toString(): string diff --git a/test/unit/Reflection/Adapter/ReflectionTypeTest.php b/test/unit/Reflection/Adapter/ReflectionTypeTest.php index af9cf2783..a6b66630b 100644 --- a/test/unit/Reflection/Adapter/ReflectionTypeTest.php +++ b/test/unit/Reflection/Adapter/ReflectionTypeTest.php @@ -4,16 +4,21 @@ namespace Roave\BetterReflectionTest\Reflection\Adapter; +use PhpParser\Node\Identifier; use PHPUnit\Framework\TestCase; use ReflectionClass as CoreReflectionClass; use ReflectionType as CoreReflectionType; use Roave\BetterReflection\Reflection\Adapter\ReflectionIntersectionType as ReflectionIntersectionTypeAdapter; use Roave\BetterReflection\Reflection\Adapter\ReflectionNamedType as ReflectionNamedTypeAdapter; +use Roave\BetterReflection\Reflection\Adapter\ReflectionType; use Roave\BetterReflection\Reflection\Adapter\ReflectionType as ReflectionTypeAdapter; use Roave\BetterReflection\Reflection\Adapter\ReflectionUnionType as ReflectionUnionTypeAdapter; use Roave\BetterReflection\Reflection\ReflectionIntersectionType as BetterReflectionIntersectionType; +use Roave\BetterReflection\Reflection\ReflectionNamedType; use Roave\BetterReflection\Reflection\ReflectionNamedType as BetterReflectionNamedType; +use Roave\BetterReflection\Reflection\ReflectionParameter; use Roave\BetterReflection\Reflection\ReflectionUnionType as BetterReflectionUnionType; +use Roave\BetterReflection\Reflector\Reflector; use function array_combine; use function array_map; @@ -83,4 +88,14 @@ public function testFromTypeOrNullWithIntersectionType(): void { self::assertInstanceOf(ReflectionIntersectionTypeAdapter::class, ReflectionTypeAdapter::fromTypeOrNull($this->createMock(BetterReflectionIntersectionType::class))); } + + public function testMixedAllowsNull(): void + { + $type = ReflectionType::fromTypeOrNull(new ReflectionNamedType( + $this->createMock(Reflector::class), + $this->createMock(ReflectionParameter::class), + new Identifier('mixed'), + )); + self::assertTrue($type->allowsNull()); + } } diff --git a/test/unit/Reflection/ReflectionNamedTypeTest.php b/test/unit/Reflection/ReflectionNamedTypeTest.php index 0227d43f3..8c1a84be2 100644 --- a/test/unit/Reflection/ReflectionNamedTypeTest.php +++ b/test/unit/Reflection/ReflectionNamedTypeTest.php @@ -51,6 +51,12 @@ public function testAllowsNull(): void self::assertFalse($noNullType->allowsNull()); } + public function testMixedAllowsNull(): void + { + $noNullType = $this->createType('mixed'); + self::assertTrue($noNullType->allowsNull()); + } + public function isBuildinProvider(): Generator { yield ['string'];