Skip to content

Commit

Permalink
Type: added basic API
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Sep 20, 2021
1 parent aa66d71 commit 35c3660
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 0 deletions.
73 changes: 73 additions & 0 deletions src/Utils/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ function ($t) use ($reflection) { return self::resolve($t->getName(), $reflectio
}


/**
* Creates the Type object according to the text notation.
*/
public static function fromString(string $type): self
{
if (!preg_match('#(?:\?([\w\\\\]+)|[\w\\\\]+(?:\|[\w\\\\]+)*)$#AD', $type, $m)) {
throw new Nette\InvalidArgumentException("Invalid type '$type'.");
}
if (isset($m[1])) {
return new self([$m[1], 'null']);
} else {
return new self(explode('|', $type));
}
}


/**
* Resolves 'self', 'static' and 'parent' to the actual class name.
* @param \ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $reflection
Expand Down Expand Up @@ -104,4 +120,61 @@ public function getNames(): array
{
return $this->types;
}


/**
* Returns the array of subtypes that make up the compound type as Type objects:
* @return self[]
*/
public function getTypes(): array
{
return array_map(function ($name) { return self::fromString($name); }, $this->types);
}


/**
* Returns the type name for single types, otherwise null.
*/
public function getSingleName(): ?string
{
return $this->single
? $this->types[0]
: null;
}


/**
* Returns true whether it is a union type.
*/
public function isUnion(): bool
{
return count($this->types) > 1;
}


/**
* Returns true whether it is a single type. Simple nullable types are also considered to be single types.
*/
public function isSingle(): bool
{
return $this->single;
}


/**
* Returns true whether the type is both a single and a PHP built-in type.
*/
public function isBuiltin(): bool
{
return $this->single && Reflection::isBuiltinType($this->types[0]);
}


/**
* Returns true whether the type is both a single and a class name.
*/
public function isClass(): bool
{
return $this->single && !Reflection::isBuiltinType($this->types[0]);
}
}
108 changes: 108 additions & 0 deletions tests/Utils/Type.fromString.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

/**
* Test: Nette\Utils\Type
*/

declare(strict_types=1);

use Nette\Utils\Type;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


$type = Type::fromString('string');

Assert::same(['string'], $type->getNames());
Assert::equal([Type::fromString('string')], $type->getTypes());
Assert::same('string', (string) $type);
Assert::same('string', $type->getSingleName());
Assert::false($type->isClass());
Assert::false($type->isUnion());
Assert::true($type->isSingle());
Assert::true($type->isBuiltin());


$type = Type::fromString('string|null');

Assert::same(['string', 'null'], $type->getNames());
Assert::equal([Type::fromString('string'), Type::fromString('null')], $type->getTypes());
Assert::same('?string', (string) $type);
Assert::same('string', $type->getSingleName());
Assert::false($type->isClass());
Assert::true($type->isUnion());
Assert::true($type->isSingle());
Assert::true($type->isBuiltin());


$type = Type::fromString('null|string');

Assert::same(['string', 'null'], $type->getNames());
Assert::equal([Type::fromString('string'), Type::fromString('null')], $type->getTypes());
Assert::same('?string', (string) $type);
Assert::same('string', $type->getSingleName());
Assert::false($type->isClass());
Assert::true($type->isUnion());
Assert::true($type->isSingle());
Assert::true($type->isBuiltin());


$type = Type::fromString('?string');

Assert::same(['string', 'null'], $type->getNames());
Assert::equal([Type::fromString('string'), Type::fromString('null')], $type->getTypes());
Assert::same('?string', (string) $type);
Assert::same('string', $type->getSingleName());
Assert::false($type->isClass());
Assert::true($type->isUnion());
Assert::true($type->isSingle());
Assert::true($type->isBuiltin());


$type = Type::fromString('NS\Foo');

Assert::same(['NS\Foo'], $type->getNames());
Assert::equal([Type::fromString('NS\Foo')], $type->getTypes());
Assert::same('NS\Foo', (string) $type);
Assert::same('NS\Foo', $type->getSingleName());
Assert::true($type->isClass());
Assert::false($type->isUnion());
Assert::true($type->isSingle());
Assert::false($type->isBuiltin());


$type = Type::fromString('string|Foo');

Assert::same(['string', 'Foo'], $type->getNames());
Assert::equal([Type::fromString('string'), Type::fromString('Foo')], $type->getTypes());
Assert::same('string|Foo', (string) $type);
Assert::null($type->getSingleName());
Assert::false($type->isClass());
Assert::true($type->isUnion());
Assert::false($type->isSingle());
Assert::false($type->isBuiltin());


$type = Type::fromString('mixed');

Assert::same(['mixed'], $type->getNames());
Assert::equal([Type::fromString('mixed')], $type->getTypes());
Assert::same('mixed', (string) $type);
Assert::same('mixed', $type->getSingleName());
Assert::false($type->isClass());
Assert::false($type->isUnion());
Assert::true($type->isSingle());
Assert::true($type->isBuiltin());


$type = Type::fromString('null'); // invalid type

Assert::same(['null'], $type->getNames());
Assert::equal([Type::fromString('null')], $type->getTypes());
Assert::same('null', (string) $type);
Assert::same('null', $type->getSingleName());
Assert::false($type->isClass());
Assert::false($type->isUnion());
Assert::true($type->isSingle());
Assert::true($type->isBuiltin());

0 comments on commit 35c3660

Please sign in to comment.