Skip to content

Commit

Permalink
feature #54670 [TypeInfo] Ease getting base type on nullable types (m…
Browse files Browse the repository at this point in the history
…tarld)

This PR was merged into the 7.1 branch.

Discussion
----------

[TypeInfo] Ease getting base type on nullable types

| Q             | A
| ------------- | ---
| Branch?       | 7.1
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        |
| License       | MIT

Allow retrieving base type on "nullable union types" (ie: `string|null`) without getting a `LogicException`.

Commits
-------

2b73bc9 [TypeInfo] Ease getting base type on nullable types
  • Loading branch information
fabpot committed May 2, 2024
2 parents 9a86584 + 2b73bc9 commit e02306b
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public function testIsNullable()
$this->assertFalse((new BackedEnumType(DummyBackedEnum::class, Type::int()))->isNullable());
}

public function testGetBaseType()
{
$this->assertEquals(new BackedEnumType(DummyBackedEnum::class, Type::int()), (new BackedEnumType(DummyBackedEnum::class, Type::int()))->getBaseType());
}

public function testAsNonNullable()
{
$type = new BackedEnumType(DummyBackedEnum::class, Type::int());
Expand Down
5 changes: 5 additions & 0 deletions src/Symfony/Component/TypeInfo/Tests/Type/BuiltinTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public function testToString()
$this->assertSame('int', (string) new BuiltinType(TypeIdentifier::INT));
}

public function testGetBaseType()
{
$this->assertEquals(new BuiltinType(TypeIdentifier::INT), (new BuiltinType(TypeIdentifier::INT))->getBaseType());
}

public function testIsNullable()
{
$this->assertFalse((new BuiltinType(TypeIdentifier::INT))->isNullable());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public function testToString()
$this->assertEquals('array<string,bool>', (string) $type);
}

public function testGetBaseType()
{
$this->assertEquals(Type::int(), Type::collection(Type::generic(Type::int(), Type::string()))->getBaseType());
}

public function testIsNullable()
{
$this->assertFalse((new CollectionType(Type::generic(Type::builtin(TypeIdentifier::ARRAY), Type::int())))->isNullable());
Expand Down
5 changes: 5 additions & 0 deletions src/Symfony/Component/TypeInfo/Tests/Type/EnumTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public function testToString()
$this->assertSame(DummyEnum::class, (string) new EnumType(DummyEnum::class));
}

public function testGetBaseType()
{
$this->assertEquals(new EnumType(DummyEnum::class), (new EnumType(DummyEnum::class))->getBaseType());
}

public function testIsNullable()
{
$this->assertFalse((new EnumType(DummyEnum::class))->isNullable());
Expand Down
5 changes: 5 additions & 0 deletions src/Symfony/Component/TypeInfo/Tests/Type/GenericTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public function testToString()
$this->assertEquals(sprintf('%s<bool|string,int,float>', self::class), (string) $type);
}

public function testGetBaseType()
{
$this->assertEquals(Type::object(), Type::generic(Type::object(), Type::int())->getBaseType());
}

public function testIsNullable()
{
$this->assertFalse((new GenericType(Type::builtin(TypeIdentifier::ARRAY), Type::int()))->isNullable());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public function testEveryTypeIs()
$this->assertFalse($type->everyTypeIs(fn (Type $t) => $t instanceof BuiltinType));
}

public function testGetBaseType()
{
$this->expectException(LogicException::class);
(new IntersectionType(Type::string(), Type::int()))->getBaseType();
}

public function testToString()
{
$type = new IntersectionType(Type::int(), Type::string(), Type::float());
Expand Down
5 changes: 5 additions & 0 deletions src/Symfony/Component/TypeInfo/Tests/Type/ObjectTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public function testIsNullable()
$this->assertFalse((new ObjectType(self::class))->isNullable());
}

public function testGetBaseType()
{
$this->assertEquals(new ObjectType(self::class), (new ObjectType(self::class))->getBaseType());
}

public function testIsA()
{
$this->assertFalse((new ObjectType(self::class))->isA(TypeIdentifier::ARRAY));
Expand Down
9 changes: 9 additions & 0 deletions src/Symfony/Component/TypeInfo/Tests/Type/UnionTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use PHPUnit\Framework\TestCase;
use Symfony\Component\TypeInfo\Exception\InvalidArgumentException;
use Symfony\Component\TypeInfo\Exception\LogicException;
use Symfony\Component\TypeInfo\Type;
use Symfony\Component\TypeInfo\Type\BuiltinType;
use Symfony\Component\TypeInfo\Type\UnionType;
Expand Down Expand Up @@ -66,6 +67,14 @@ public function testAsNonNullable()
], $type->asNonNullable()->getTypes());
}

public function testGetBaseType()
{
$this->assertEquals(Type::string(), (new UnionType(Type::string(), Type::null()))->getBaseType());

$this->expectException(LogicException::class);
(new UnionType(Type::string(), Type::int(), Type::null()))->getBaseType();
}

public function testAtLeastOneTypeIs()
{
$type = new UnionType(Type::int(), Type::string(), Type::bool());
Expand Down
9 changes: 0 additions & 9 deletions src/Symfony/Component/TypeInfo/Tests/TypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,6 @@ public function testIsNullable()
$this->assertFalse(Type::generic(Type::int(), Type::mixed())->isNullable());
}

public function testGetBaseType()
{
$this->assertEquals(Type::string(), Type::string()->getBaseType());
$this->assertEquals(Type::object(self::class), Type::object(self::class)->getBaseType());
$this->assertEquals(Type::object(), Type::generic(Type::object(), Type::int())->getBaseType());
$this->assertEquals(Type::builtin(TypeIdentifier::ARRAY), Type::list()->getBaseType());
$this->assertEquals(Type::int(), Type::collection(Type::generic(Type::int(), Type::string()))->getBaseType());
}

public function testCannotGetBaseTypeOnCompoundType()
{
$this->expectException(LogicException::class);
Expand Down
6 changes: 0 additions & 6 deletions src/Symfony/Component/TypeInfo/Type/CompositeTypeTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
namespace Symfony\Component\TypeInfo\Type;

use Symfony\Component\TypeInfo\Exception\InvalidArgumentException;
use Symfony\Component\TypeInfo\Exception\LogicException;
use Symfony\Component\TypeInfo\Type;
use Symfony\Component\TypeInfo\TypeIdentifier;

Expand Down Expand Up @@ -50,11 +49,6 @@ public function __construct(Type ...$types)
$this->types = array_values(array_unique($types));
}

public function getBaseType(): BuiltinType|ObjectType
{
throw new LogicException(sprintf('Cannot get base type on "%s" compound type.', $this));
}

public function isA(TypeIdentifier $typeIdentifier): bool
{
return $this->is(fn (Type $type) => $type->isA($typeIdentifier));
Expand Down
11 changes: 11 additions & 0 deletions src/Symfony/Component/TypeInfo/Type/IntersectionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ public function __toString(): string
return $string;
}

/**
* @throws LogicException
*/
public function getBaseType(): BuiltinType|ObjectType
{
throw new LogicException(sprintf('Cannot get base type on "%s" compound type.', $this));
}

/**
* @throws LogicException
*/
public function asNonNullable(): self
{
if ($this->isNullable()) {
Expand Down
14 changes: 14 additions & 0 deletions src/Symfony/Component/TypeInfo/Type/UnionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\TypeInfo\Type;

use Symfony\Component\TypeInfo\Exception\LogicException;
use Symfony\Component\TypeInfo\Type;
use Symfony\Component\TypeInfo\TypeIdentifier;

Expand All @@ -34,6 +35,19 @@ public function is(callable $callable): bool
return $this->atLeastOneTypeIs($callable);
}

/**
* @throws LogicException
*/
public function getBaseType(): BuiltinType|ObjectType
{
$nonNullableType = $this->asNonNullable();
if (!$nonNullableType instanceof self) {
return $nonNullableType->getBaseType();
}

throw new LogicException(sprintf('Cannot get base type on "%s" compound type.', $this));
}

public function asNonNullable(): Type
{
$nonNullableTypes = [];
Expand Down

0 comments on commit e02306b

Please sign in to comment.