forked from symfony/symfony
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
246 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,8 +12,6 @@ | |
namespace Symfony\Component\TypeInfo; | ||
|
||
use Symfony\Component\TypeInfo\Exception\LogicException; | ||
use Symfony\Component\TypeInfo\Type\BuiltinType; | ||
use Symfony\Component\TypeInfo\Type\ObjectType; | ||
|
||
/** | ||
* @author Mathias Arlaud <[email protected]> | ||
|
@@ -25,27 +23,18 @@ abstract class Type implements \Stringable | |
{ | ||
use TypeFactoryTrait; | ||
|
||
abstract public function getBaseType(): BuiltinType|ObjectType; | ||
|
||
/** | ||
* @param TypeIdentifier|class-string $subject | ||
*/ | ||
abstract public function isA(TypeIdentifier|string $subject): bool; | ||
abstract public function getTypeIdentifier(): TypeIdentifierInterface; | ||
|
||
abstract public function asNonNullable(): self; | ||
|
||
abstract public function isNullable(): bool; | ||
|
||
/** | ||
* @param callable(Type): bool $callable | ||
* Get all the classes/interfaces implemented by an "object" type. | ||
*/ | ||
public function is(callable $callable): bool | ||
{ | ||
return $callable($this); | ||
} | ||
abstract public function getClassNames(): array; | ||
|
||
public function isNullable(): bool | ||
{ | ||
return $this->is(fn (Type $t): bool => $t->isA(TypeIdentifier::NULL) || $t->isA(TypeIdentifier::MIXED)); | ||
} | ||
abstract public function accepts(Type $type): bool; | ||
|
||
/** | ||
* Graceful fallback for unexisting methods. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\TypeInfo\Type; | ||
|
||
use Symfony\Component\TypeInfo\Exception\LogicException; | ||
use Symfony\Component\TypeInfo\Type; | ||
use Symfony\Component\TypeInfo\TypeIdentifier; | ||
use Symfony\Component\TypeInfo\TypeIdentifierInterface; | ||
|
||
/** | ||
* Custom atomic type with no pre-established behavior. | ||
* | ||
* A custom type only accepts other custom types with the same name, type identifier and compatible variable types. | ||
* | ||
* They are by default seen as non-nullable, but users are free to implement their own types | ||
* with a different behavior by extending this class. | ||
* | ||
* @template TPrimitive of TypeIdentifier | ||
* @template TVariables of Type|void | ||
* | ||
* @author Mathias Arlaud <[email protected]> | ||
* @author Baptiste Leduc <[email protected]> | ||
* | ||
* @experimental | ||
*/ | ||
class AtomicType extends Type | ||
{ | ||
/** | ||
* @var list<TVariables> | ||
*/ | ||
private readonly array $variableTypes; | ||
|
||
/** | ||
* @param TPrimitive $typeIdentifier Native type represented by this type | ||
* @param string $name Type name | ||
* @param bool $isNullable Whether this type is nullable | ||
* @param string $compareName Whether to check another type name before accepting it | ||
* @param TVariables ...$variableTypes | ||
*/ | ||
public function __construct( | ||
private readonly TypeIdentifierInterface $typeIdentifier, | ||
private readonly string $name, | ||
private readonly bool $isNullable = false, | ||
private readonly bool $compareName = false, | ||
Type ...$variableTypes | ||
) { | ||
$this->variableTypes = $variableTypes; | ||
} | ||
|
||
final public function getName(): string | ||
{ | ||
return $this->name; | ||
} | ||
|
||
/** | ||
* @return list<TVariables> | ||
*/ | ||
final public function getVariableTypes(): array | ||
{ | ||
return $this->variableTypes; | ||
} | ||
|
||
final public function getTypeIdentifier(): TypeIdentifierInterface | ||
{ | ||
return $this->typeIdentifier; | ||
} | ||
|
||
public function isNullable(): bool | ||
{ | ||
return $this->isNullable; | ||
} | ||
|
||
public function asNonNullable(): Type | ||
{ | ||
if (!$this->isNullable()) { | ||
return $this; | ||
} | ||
|
||
throw new LogicException(sprintf('"%s" cannot be turned as non nullable.', (string) $this)); | ||
} | ||
|
||
public function accepts(Type $type): bool | ||
{ | ||
if ($this->compareName && (!$type instanceof self || $this->name !== $type->name)) { | ||
return false; | ||
} | ||
|
||
return $this->typeIdentifier->accepts($type->getTypeIdentifier()) && $this->acceptsVariables($type); | ||
} | ||
|
||
public function __toString(): string | ||
{ | ||
return $this->name.$this->renderVariableTypes(); | ||
} | ||
|
||
protected function renderVariableTypes(): string | ||
{ | ||
return $this->variableTypes ? '<'.implode(', ', $this->variableTypes).'>' : ''; | ||
} | ||
|
||
protected function acceptsVariables(Type $type): bool | ||
{ | ||
if (count($this->variableTypes) && !$type instanceof self) { | ||
return false; | ||
} | ||
$types = $type->getVariableTypes(); | ||
|
||
foreach ($this->getVariableTypes() as $n => $variableType) { | ||
if (!isset($types[$n]) || !$variableType->accepts($types[$n])) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,61 +16,38 @@ | |
use Symfony\Component\TypeInfo\TypeIdentifier; | ||
|
||
/** | ||
* Represents a PHP builtin type. | ||
* | ||
* @author Mathias Arlaud <[email protected]> | ||
* @author Baptiste Leduc <[email protected]> | ||
* | ||
* @template T of TypeIdentifier | ||
* | ||
* @experimental | ||
*/ | ||
final class BuiltinType extends Type | ||
final class BuiltinType extends AtomicType | ||
{ | ||
/** | ||
* @param T $typeIdentifier | ||
*/ | ||
public function __construct( | ||
private readonly TypeIdentifier $typeIdentifier, | ||
TypeIdentifier $typeIdentifier, | ||
) { | ||
} | ||
|
||
public function getBaseType(): self|ObjectType | ||
{ | ||
return $this; | ||
} | ||
|
||
/** | ||
* @return T | ||
*/ | ||
public function getTypeIdentifier(): TypeIdentifier | ||
{ | ||
return $this->typeIdentifier; | ||
} | ||
|
||
public function isA(TypeIdentifier|string $subject): bool | ||
{ | ||
if ($subject instanceof TypeIdentifier) { | ||
return $this->getTypeIdentifier() === $subject; | ||
} | ||
|
||
try { | ||
return TypeIdentifier::from($subject) === $this->getTypeIdentifier(); | ||
} catch (\ValueError) { | ||
return false; | ||
} | ||
parent::__construct($typeIdentifier, $typeIdentifier->value, TypeIdentifier::NULL === $typeIdentifier || TypeIdentifier::MIXED === $typeIdentifier); | ||
} | ||
|
||
/** | ||
* @return self|UnionType<BuiltinType<TypeIdentifier::OBJECT>|BuiltinType<TypeIdentifier::RESOURCE>|BuiltinType<TypeIdentifier::ARRAY>|BuiltinType<TypeIdentifier::STRING>|BuiltinType<TypeIdentifier::FLOAT>|BuiltinType<TypeIdentifier::INT>|BuiltinType<TypeIdentifier::BOOL>> | ||
*/ | ||
public function asNonNullable(): self|UnionType | ||
{ | ||
if (TypeIdentifier::NULL === $this->typeIdentifier) { | ||
if (TypeIdentifier::NULL === $this->getTypeIdentifier()) { | ||
throw new LogicException('"null" cannot be turned as non nullable.'); | ||
} | ||
|
||
// "mixed" is an alias of "object|resource|array|string|float|int|bool|null" | ||
// therefore, its non-nullable version is "object|resource|array|string|float|int|bool" | ||
if (TypeIdentifier::MIXED === $this->typeIdentifier) { | ||
if (TypeIdentifier::MIXED === $this->getTypeIdentifier()) { | ||
return new UnionType( | ||
new self(TypeIdentifier::OBJECT), | ||
new self(TypeIdentifier::RESOURCE), | ||
|
@@ -84,9 +61,4 @@ public function asNonNullable(): self|UnionType | |
|
||
return $this; | ||
} | ||
|
||
public function __toString(): string | ||
{ | ||
return $this->typeIdentifier->value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,11 +19,9 @@ | |
* @author Mathias Arlaud <[email protected]> | ||
* @author Baptiste Leduc <[email protected]> | ||
* | ||
* @internal | ||
* | ||
* @template T of Type | ||
*/ | ||
trait CompositeTypeTrait | ||
class CompositeType extends Type | ||
{ | ||
/** | ||
* @var list<T> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.