diff --git a/packages/reflection/src/TypeReflector.php b/packages/reflection/src/TypeReflector.php index 64429ba19..acfcb0317 100644 --- a/packages/reflection/src/TypeReflector.php +++ b/packages/reflection/src/TypeReflector.php @@ -266,7 +266,14 @@ private function resolveDefinition(PHPReflector|PHPReflectionType|string $reflec private function resolveIsNullable(PHPReflectionType|PHPReflector|string $reflector): bool { if (is_string($reflector)) { - return str_contains($this->definition, '?') || str_contains($this->definition, 'null'); + if (str_contains($this->definition, '?')) { + return true; + } + + return array_any( + array: preg_split('/[&|]/', $this->definition), + callback: static fn (string $type) => $type === 'null', + ); } if ($reflector instanceof PHPReflectionParameter || $reflector instanceof PHPReflectionProperty) { diff --git a/packages/reflection/tests/Fixtures/AnnulledInvoice.php b/packages/reflection/tests/Fixtures/AnnulledInvoice.php new file mode 100644 index 000000000..f5d5c7f8f --- /dev/null +++ b/packages/reflection/tests/Fixtures/AnnulledInvoice.php @@ -0,0 +1,9 @@ +isUnitEnum(), ); } + + public function test_is_nullable(): void + { + $this->assertTrue(new TypeReflector('?string')->isNullable()); + $this->assertTrue(new TypeReflector('string|null')->isNullable()); + $this->assertTrue(new TypeReflector('null')->isNullable()); + $this->assertFalse(new TypeReflector('string')->isNullable()); + } + + public function test_class_name_containing_null_is_not_nullable(): void + { + $this->assertFalse(new TypeReflector(AnnulledInvoice::class)->isNullable()); + $this->assertFalse(new TypeReflector(NullableClass::class)->isNullable()); + } }