/** * @param string $decl * * @return Type The type */ public static function fromDecl($decl) { if ($decl instanceof Type) { return $decl; } elseif (!is_string($decl)) { throw new \LogicException("Should never happen"); } elseif (empty($decl)) { throw new \RuntimeException("Empty declaration found"); } if ($decl[0] === '\\') { $decl = substr($decl, 1); } elseif ($decl[0] === '?') { $decl = substr($decl, 1); $type = Type::fromDecl($decl); return (new Type(Type::TYPE_UNION, [$type, new Type(Type::TYPE_NULL)]))->simplify(); } switch (strtolower($decl)) { case 'boolean': case 'bool': case 'false': case 'true': return new Type(Type::TYPE_BOOLEAN); case 'integer': case 'int': return new Type(Type::TYPE_LONG); case 'double': case 'real': case 'float': return new Type(Type::TYPE_DOUBLE); case 'string': return new Type(Type::TYPE_STRING); case 'array': return new Type(Type::TYPE_ARRAY); case 'callable': return new Type(Type::TYPE_CALLABLE); case 'null': return new Type(Type::TYPE_NULL); case 'numeric': return Type::fromDecl('int|float'); } // TODO: parse | and & and () if (strpos($decl, '|') !== false || strpos($decl, '&') !== false || strpos($decl, '(') !== false) { return self::parseCompexDecl($decl)->simplify(); } if (substr($decl, -2) === '[]') { $type = Type::fromDecl(substr($decl, 0, -2)); return new Type(Type::TYPE_ARRAY, [$type]); } $regex = '(^([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*\\\\)*[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$)'; if (!preg_match($regex, $decl)) { throw new \RuntimeException("Unknown type declaration found: {$decl}"); } return new Type(Type::TYPE_OBJECT, [], $decl); }
public static function fromDecl($decl) { if ($decl instanceof Type) { return $decl; } elseif (!is_string($decl)) { throw new \LogicException("Should never happen"); } elseif (empty($decl)) { throw new \RuntimeException("Empty declaration found"); } if ($decl[0] === '\\') { $decl = substr($decl, 1); } switch (strtolower($decl)) { case 'boolean': case 'bool': return new Type(Type::TYPE_BOOLEAN); case 'integer': case 'int': return new Type(Type::TYPE_LONG); case 'double': case 'real': case 'float': return new Type(Type::TYPE_DOUBLE); case 'string': return new Type(Type::TYPE_STRING); case 'array': return new Type(Type::TYPE_ARRAY); case 'callable': return new Type(Type::TYPE_CALLABLE); } if (strpos($decl, '|') !== false) { $parts = explode('|', $decl); $allowedTypes = 0; $userTypes = []; $subTypes = []; foreach ($parts as $part) { $type = Type::fromDecl($part); $allowedTypes |= $type->type; $userTypes = array_merge($type->userTypes, $userTypes); $subTypes = array_merge($type->subTypes, $subTypes); } return new Type($allowedTypes, $subTypes, $userTypes); } if (substr($decl, -2) === '[]') { $type = Type::fromDecl(substr($decl, 0, -2)); return new Type(Type::TYPE_ARRAY, [$type]); } if (substr($decl, -2) === '()') { // because some people use array() as a type declaration. sigh return Type::fromDecl(substr($decl, 0, -2)); } $regex = '(^([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*\\\\)*[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$)'; if (!preg_match($regex, $decl)) { throw new \RuntimeException("Unknown type declaration found: {$decl}"); } return new Type(Type::TYPE_USER, [], [$decl]); }
public function __construct(State $state) { $this->state = $state; $this->callableUnion = Type::fromDecl("string|array|object"); }
/** * @dataProvider provideTestDecl */ public function testDecl($decl, $result) { $type = Type::fromDecl($decl); $this->assertEquals($result, $type); $this->assertEquals($decl, (string) $type); }
public function __construct(array $components) { $this->components = $components; $this->callableUnion = Type::fromDecl("string|array|object"); }