Skip to content

Commit

Permalink
Do not typehint DNF union types
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcin Czarnecki committed Feb 2, 2025
1 parent fa7ab39 commit 47f585b
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 1 deletion.
4 changes: 4 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
<exclude-pattern>tests/*</exclude-pattern>
</rule>

<rule ref="Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps">
<exclude-pattern>tests/Fixtures/TypedProperties/NotSupportedDNFTypes.php</exclude-pattern>
</rule>

<rule ref="SlevomatCodingStandard.Commenting.DocCommentSpacing">
<properties>
<property name="annotationsGroups" type="array">
Expand Down
10 changes: 9 additions & 1 deletion src/Metadata/Driver/TypedPropertiesDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,15 @@ private function shouldTypeHintUnion(?ReflectionType $reflectionType)
return false;
}

foreach ($reflectionType->getTypes() as $type) {
$types = $reflectionType->getTypes();

foreach ($types as $type) {
if ($type instanceof \ReflectionIntersectionType) {
return false;
}
}

foreach ($types as $type) {
if ($this->shouldTypeHintInsideUnion($type)) {
return true;
}
Expand Down
71 changes: 71 additions & 0 deletions tests/Fixtures/TypedProperties/NotSupportedDNFTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace JMS\Serializer\Tests\Fixtures\TypedProperties;

/**
* @link https://wiki.php.net/rfc/dnf_types
* Changing this file may create some BC change.
*/
class NotSupportedDNFTypes
{
// Accepts an object that implements both A and B,
// OR an object that implements D.
private (A&B)|D $CandBorD;

// Accepts an object that implements C,
// OR a child of X that also implements D,
// OR null.
private C|(X&D)|null $CorXandDorNULL;

// Accepts an object that implements all three of A, B, and D,
// OR an int,
// OR null.
private (A&B&D)|int|null $AandBandCorINTorNULL;

// Accepts an object that implements both A and B,
// OR an object that implements both A and D.
private (A&B)|(A&D ) $AandBorAandD;

// Accepts an object that implements A and B,
// OR an object that implements both B and D,
// OR a child of W that also implements B,
// OR null.
private A|(B&D)|(B&W)|null $AorBandDorBandWorNULL;

public function __construct(
private (A&B)|D $promotedCandBorD,
private C|(X&D)|null $promotedCorXandDorNULL,
private (A&B&D)|int|null $promotedAandBandCorINTorNULL,
private (A&B)|(A&D ) $promotedAandBorAandD,
private A|(B&D)|(B&W)|null $promotedAorBandDorBandWorNULL,
) {
}
}

interface A
{
}
interface B
{
}
interface C extends A
{
}
interface D
{
}

class W implements A
{
}
class X implements B
{
}
class Y implements A, B
{
}
class Z extends Y implements C
{
}
15 changes: 15 additions & 0 deletions tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use JMS\Serializer\Metadata\Driver\NullDriver;
use JMS\Serializer\Metadata\Driver\TypedPropertiesDriver;
use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy;
use JMS\Serializer\Tests\Fixtures\TypedProperties\NotSupportedDNFTypes;
use JMS\Serializer\Tests\Fixtures\TypedProperties\UnionTypedProperties;
use Metadata\Driver\DriverChain;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -86,6 +87,20 @@ public function testInferUnionTypesShouldIncludeValueTypes()
);
}

public function testDNFTypes()
{
if(PHP_VERSION_ID < 80200) {

Check failure on line 92 in tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php

View workflow job for this annotation

GitHub Actions / Coding Standards (7.4)

Expected 1 space after IF keyword; 0 found
self::markTestSkipped();
}

$m = $this->resolve(NotSupportedDNFTypes::class);

self::assertCount(10, $m->propertyMetadata);
foreach ($m->propertyMetadata as $propertyMetadata) {
self::assertNull($propertyMetadata->type, 'Breaking Change: TypeResolved for: ' . $propertyMetadata->name);
}
}

private function resolve(string $classToResolve): ClassMetadata
{
$namingStrategy = new IdenticalPropertyNamingStrategy();
Expand Down

0 comments on commit 47f585b

Please sign in to comment.