mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Add support for types and improve resolution
As part of the re-architecting of phpDocumentor and its Reflection component we needed to move the type classes from the \phpDocumentor\Descriptor namespace to \phpDocumentor\Reflection\Types. In addition to this I have removed the resolution / type creation from the Collection class into a new Resolver class that is capable of resolving any type into a Type or Fqsen object. This is the first commit with the base classes and a test for the Resolver functionality in subsequent commits we need to add tests for the other classes and to refactor the collection object.
This commit is contained in:
committed by
Mike van Riel
parent
f3f4d07808
commit
fab7169255
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection;
|
||||||
|
|
||||||
|
interface Type
|
||||||
|
{
|
||||||
|
public function __toString();
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
class Array_ implements Type
|
||||||
|
{
|
||||||
|
/** @var Type */
|
||||||
|
private $valueType;
|
||||||
|
|
||||||
|
/** @var Type */
|
||||||
|
private $keyType;
|
||||||
|
|
||||||
|
public function __construct(Type $valueType = null, Type $keyType = null)
|
||||||
|
{
|
||||||
|
if ($keyType === null) {
|
||||||
|
$keyType = new Mixed();
|
||||||
|
}
|
||||||
|
if ($valueType === null) {
|
||||||
|
$valueType = new Mixed();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->valueType = $valueType;
|
||||||
|
$this->keyType = $keyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Type
|
||||||
|
*/
|
||||||
|
public function getKeyType()
|
||||||
|
{
|
||||||
|
return $this->keyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Type
|
||||||
|
*/
|
||||||
|
public function getValueType()
|
||||||
|
{
|
||||||
|
return $this->valueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
if ($this->valueType instanceof Mixed) {
|
||||||
|
return 'array';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->valueType . '[]';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Boolean implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'bool';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Callable_ implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'callable';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Types\Resolver;
|
||||||
|
use phpDocumentor\Reflection\DocBlock\Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection
|
||||||
|
*/
|
||||||
|
class Collection extends \ArrayObject
|
||||||
|
{
|
||||||
|
/** @var string Definition of the OR operator for types */
|
||||||
|
const OPERATOR_OR = '|';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current invoking location.
|
||||||
|
*
|
||||||
|
* This is used to prepend to type with a relative location.
|
||||||
|
* May also be 'default' or 'global', in which case they are ignored.
|
||||||
|
*
|
||||||
|
* @var Context
|
||||||
|
*/
|
||||||
|
protected $context = null;
|
||||||
|
/**
|
||||||
|
* @var Resolver
|
||||||
|
*/
|
||||||
|
private $resolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the namespace and aliases; uses that to add and expand the given types.
|
||||||
|
*
|
||||||
|
* @param string[] $types Array containing a list of types to add to this container.
|
||||||
|
* @param Context $context
|
||||||
|
* @param Resolver $resolver
|
||||||
|
*/
|
||||||
|
public function __construct(array $types = array(), Context $context = null, Resolver $resolver = null)
|
||||||
|
{
|
||||||
|
$this->context = $context ?: new Context('');
|
||||||
|
$this->resolver = $resolver ?: new Resolver();
|
||||||
|
|
||||||
|
foreach ($types as $type) {
|
||||||
|
$this->add($type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current invoking location.
|
||||||
|
*
|
||||||
|
* @return Context
|
||||||
|
*/
|
||||||
|
public function getContext()
|
||||||
|
{
|
||||||
|
return $this->context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new type to the collection and expands it if it contains a
|
||||||
|
* relative namespace.
|
||||||
|
*
|
||||||
|
* If a class in the type contains a relative namespace than this collection
|
||||||
|
* will try to expand that into a FQCN.
|
||||||
|
*
|
||||||
|
* @param string $type A 'Type' as defined in the phpDocumentor
|
||||||
|
* documentation.
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException if a non-string argument is passed.
|
||||||
|
*
|
||||||
|
* @see http://phpdoc.org/docs/latest/for-users/types.html for the
|
||||||
|
* definition of a type.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add($type)
|
||||||
|
{
|
||||||
|
if (!is_string($type)) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
'A type should be represented by a string, received: '
|
||||||
|
. var_export($type, true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// separate the type by the OR operator
|
||||||
|
$type_parts = explode(self::OPERATOR_OR, $type);
|
||||||
|
foreach ($type_parts as $part) {
|
||||||
|
$expanded_type = $this->resolver->resolve($part, $this->context);
|
||||||
|
if ($expanded_type) {
|
||||||
|
$this[] = $expanded_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the collection.
|
||||||
|
*
|
||||||
|
* @return string The resolved types across the collection, separated with
|
||||||
|
* {@link self::OPERATOR_OR}.
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return implode(self::OPERATOR_OR, $this->getArrayCopy());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Fqsen;
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Compound implements Type
|
||||||
|
{
|
||||||
|
/** @var Type[] */
|
||||||
|
private $types = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Type[]|Fqsen[] $types
|
||||||
|
*/
|
||||||
|
public function __construct($types)
|
||||||
|
{
|
||||||
|
$this->types = $types;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param integer $index
|
||||||
|
*
|
||||||
|
* @return null|Type|Fqsen
|
||||||
|
*/
|
||||||
|
public function get($index)
|
||||||
|
{
|
||||||
|
if (!$this->has($index)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->types[$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param integer $index
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function has($index)
|
||||||
|
{
|
||||||
|
return isset($this->types[$index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return implode('|', $this->types);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Float implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'float';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Integer implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'int';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Mixed implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'mixed';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Null_ implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Object_ implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'object';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\DocBlock\Context;
|
||||||
|
use phpDocumentor\Reflection\Fqsen;
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
class Resolver
|
||||||
|
{
|
||||||
|
/** @var string Definition of the ARRAY operator for types */
|
||||||
|
const OPERATOR_ARRAY = '[]';
|
||||||
|
|
||||||
|
/** @var string Definition of the NAMESPACE operator in PHP */
|
||||||
|
const OPERATOR_NAMESPACE = '\\';
|
||||||
|
|
||||||
|
/** @var string[] List of recognized keywords and unto which Value Object they map */
|
||||||
|
private $keywords = array(
|
||||||
|
'string' => 'phpDocumentor\Reflection\Types\String',
|
||||||
|
'int' => 'phpDocumentor\Reflection\Types\Integer',
|
||||||
|
'integer' => 'phpDocumentor\Reflection\Types\Integer',
|
||||||
|
'bool' => 'phpDocumentor\Reflection\Types\Boolean',
|
||||||
|
'boolean' => 'phpDocumentor\Reflection\Types\Boolean',
|
||||||
|
'float' => 'phpDocumentor\Reflection\Types\Float',
|
||||||
|
'double' => 'phpDocumentor\Reflection\Types\Float',
|
||||||
|
'object' => 'phpDocumentor\Reflection\Types\Object_',
|
||||||
|
'mixed' => 'phpDocumentor\Reflection\Types\Mixed',
|
||||||
|
'array' => 'phpDocumentor\Reflection\Types\Array_',
|
||||||
|
'resource' => 'phpDocumentor\Reflection\Types\Resource',
|
||||||
|
'void' => 'phpDocumentor\Reflection\Types\Void',
|
||||||
|
'null' => 'phpDocumentor\Reflection\Types\Null_',
|
||||||
|
'scalar' => 'phpDocumentor\Reflection\Types\Scalar',
|
||||||
|
'callback' => 'phpDocumentor\Reflection\Types\Callable_',
|
||||||
|
'callable' => 'phpDocumentor\Reflection\Types\Callable_',
|
||||||
|
'false' => 'phpDocumentor\Reflection\Types\Boolean',
|
||||||
|
'true' => 'phpDocumentor\Reflection\Types\Boolean',
|
||||||
|
'self' => 'phpDocumentor\Reflection\Types\Self_',
|
||||||
|
'$this' => 'phpDocumentor\Reflection\Types\This',
|
||||||
|
'static' => 'phpDocumentor\Reflection\Types\Static_'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyzes the given type and returns the FQCN variant.
|
||||||
|
*
|
||||||
|
* When a type is provided this method checks whether it is not a keyword or
|
||||||
|
* Fully Qualified Class Name. If so it will use the given namespace and
|
||||||
|
* aliases to expand the type to a FQCN representation.
|
||||||
|
*
|
||||||
|
* This method only works as expected if the namespace and aliases are set;
|
||||||
|
* no dynamic reflection is being performed here.
|
||||||
|
*
|
||||||
|
* @param string $type The relative or absolute type.
|
||||||
|
*
|
||||||
|
* @uses Context::getNamespace() to determine with what to prefix the type name.
|
||||||
|
* @uses Context::getNamespaceAliases() to check whether the first part of the relative type name should not be
|
||||||
|
* replaced with another namespace.
|
||||||
|
*
|
||||||
|
* @return Fqsen|Type|null
|
||||||
|
*/
|
||||||
|
public function resolve($type, Context $context)
|
||||||
|
{
|
||||||
|
if (!is_string($type)) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
'Attempted to resolve type but it appeared not to be a string, received: ' . var_export($type, true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = trim($type);
|
||||||
|
if (!$type) {
|
||||||
|
throw new \InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (true) {
|
||||||
|
case $this->isKeyword($type):
|
||||||
|
return $this->resolveKeyword($type);
|
||||||
|
case ($this->isCompoundType($type)):
|
||||||
|
return $this->resolveCompoundType($type, $context);
|
||||||
|
case $this->isFqsen($type):
|
||||||
|
return $this->resolveFqsen($type);
|
||||||
|
case $this->isTypedArray($type):
|
||||||
|
return $this->resolveTypedArray($type, $context);
|
||||||
|
case $this->isPartialStructuralElementName($type):
|
||||||
|
return $this->resolvePartialStructuralElementName($type, $context);
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
default:
|
||||||
|
// I haven't got the foggiest how the logic would come here but added this as a defense.
|
||||||
|
throw new \RuntimeException(
|
||||||
|
'Unable to resolve type "' . $type . '", there is no known method to resolve it'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects whether the given type represents an array.
|
||||||
|
*
|
||||||
|
* @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isTypedArray($type)
|
||||||
|
{
|
||||||
|
return substr($type, -2) === self::OPERATOR_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects whether the given type represents a PHPDoc keyword.
|
||||||
|
*
|
||||||
|
* @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isKeyword($type)
|
||||||
|
{
|
||||||
|
return in_array(strtolower($type), array_keys($this->keywords), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects whether the given type represents a relative structural element name.
|
||||||
|
*
|
||||||
|
* @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isPartialStructuralElementName($type)
|
||||||
|
{
|
||||||
|
return ($type[0] !== self::OPERATOR_NAMESPACE) && !$this->isKeyword($type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether the given type is a Fully Qualified Structural Element Name.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isFqsen($type)
|
||||||
|
{
|
||||||
|
return strpos($type, self::OPERATOR_NAMESPACE) === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether the given type is a compound type (i.e. `string|int`).
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isCompoundType($type)
|
||||||
|
{
|
||||||
|
return strpos($type, '|') !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the given typed array string (i.e. `string[]`) into an Array object with the right types set.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @param Context $context
|
||||||
|
*
|
||||||
|
* @return Array_
|
||||||
|
*/
|
||||||
|
private function resolveTypedArray($type, Context $context)
|
||||||
|
{
|
||||||
|
return new Array_($this->resolve(substr($type, 0, -2), $context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the given keyword (such as `string`) into a Type object representing that keyword.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
*
|
||||||
|
* @return Type
|
||||||
|
*/
|
||||||
|
private function resolveKeyword($type)
|
||||||
|
{
|
||||||
|
$className = $this->keywords[strtolower($type)];
|
||||||
|
|
||||||
|
return new $className();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the given FQSEN string into an FQSEN object.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
*
|
||||||
|
* @return Fqsen
|
||||||
|
*/
|
||||||
|
private function resolveFqsen($type)
|
||||||
|
{
|
||||||
|
return new Fqsen($type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation
|
||||||
|
* (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @param Context $context
|
||||||
|
*
|
||||||
|
* @return Fqsen
|
||||||
|
*/
|
||||||
|
private function resolvePartialStructuralElementName($type, Context $context)
|
||||||
|
{
|
||||||
|
$typeParts = explode(self::OPERATOR_NAMESPACE, $type, 2);
|
||||||
|
|
||||||
|
$namespaceAliases = $context->getNamespaceAliases();
|
||||||
|
|
||||||
|
// if the first segment is not an alias; prepend namespace name and return
|
||||||
|
if (!isset($namespaceAliases[$typeParts[0]])) {
|
||||||
|
$namespace = $context->getNamespace();
|
||||||
|
if ('' !== $namespace) {
|
||||||
|
$namespace .= self::OPERATOR_NAMESPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
$typeParts[0] = $namespaceAliases[$typeParts[0]];
|
||||||
|
|
||||||
|
return new Fqsen(self::OPERATOR_NAMESPACE . implode(self::OPERATOR_NAMESPACE, $typeParts));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a compound type (i.e. `string|int`) into the appropriate Type objects or FQSEN.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @param Context $context
|
||||||
|
*
|
||||||
|
* @return Compound
|
||||||
|
*/
|
||||||
|
private function resolveCompoundType($type, Context $context)
|
||||||
|
{
|
||||||
|
$types = [];
|
||||||
|
|
||||||
|
foreach (explode('|', $type) as $part) {
|
||||||
|
$types[] = $this->resolve($part, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Compound($types);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Resource implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'resource';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
class Scalar implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'scalar';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Self_ implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'self';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Static_ implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'static';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class String implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'string';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class This implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return '$this';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class Void implements Type
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'void';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of phpDocumentor.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||||
|
* @link http://phpdoc.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection\Types;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\DocBlock\Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @coversDefaultClass phpDocumentor\Reflection\Types\Resolver
|
||||||
|
*/
|
||||||
|
class ResolverTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $keyword
|
||||||
|
* @param string $expectedClass
|
||||||
|
*
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Array_
|
||||||
|
*
|
||||||
|
* @dataProvider provideKeywords
|
||||||
|
*/
|
||||||
|
public function testResolvingKeywords($keyword, $expectedClass)
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
$resolvedType = $fixture->resolve($keyword, new Context(''));
|
||||||
|
|
||||||
|
$this->assertInstanceOf($expectedClass, $resolvedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $fqsen
|
||||||
|
*
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Fqsen
|
||||||
|
*
|
||||||
|
* @dataProvider provideFqsen
|
||||||
|
*/
|
||||||
|
public function testResolvingFQSENs($fqsen)
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
$resolvedType = $fixture->resolve($fqsen, new Context(''));
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Fqsen', $resolvedType);
|
||||||
|
$this->assertSame($fqsen, (string)$resolvedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Fqsen
|
||||||
|
*/
|
||||||
|
public function testResolvingRelativeQSENsBasedOnNamespace()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
$resolvedType = $fixture->resolve('DocBlock', new Context('phpDocumentor\Reflection'));
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Fqsen', $resolvedType);
|
||||||
|
$this->assertSame('\phpDocumentor\Reflection\DocBlock', (string)$resolvedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Fqsen
|
||||||
|
*/
|
||||||
|
public function testResolvingRelativeQSENsBasedOnNamespaceAlias()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
$resolvedType = $fixture->resolve(
|
||||||
|
'm\MockInterface',
|
||||||
|
new Context('phpDocumentor\Reflection', ['m' => '\Mockery'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Fqsen', $resolvedType);
|
||||||
|
$this->assertSame('\Mockery\MockInterface', (string)$resolvedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Array_
|
||||||
|
* @uses phpDocumentor\Reflection\Types\String
|
||||||
|
*/
|
||||||
|
public function testResolvingTypedArrays()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
/** @var Array_ $resolvedType */
|
||||||
|
$resolvedType = $fixture->resolve('string[]', new Context(''));
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Array_', $resolvedType);
|
||||||
|
$this->assertSame('string[]', (string)$resolvedType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Mixed', $resolvedType->getKeyType());
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\String', $resolvedType->getValueType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Array_
|
||||||
|
* @uses phpDocumentor\Reflection\Types\String
|
||||||
|
*/
|
||||||
|
public function testResolvingNestedTypedArrays()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
/** @var Array_ $resolvedType */
|
||||||
|
$resolvedType = $fixture->resolve('string[][]', new Context(''));
|
||||||
|
|
||||||
|
/** @var Array_ $childValueType */
|
||||||
|
$childValueType = $resolvedType->getValueType();
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Array_', $resolvedType);
|
||||||
|
|
||||||
|
$this->assertSame('string[][]', (string)$resolvedType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Mixed', $resolvedType->getKeyType());
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Array_', $childValueType);
|
||||||
|
|
||||||
|
$this->assertSame('string[]', (string)$childValueType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Mixed', $childValueType->getKeyType());
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\String', $childValueType->getValueType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Compound
|
||||||
|
* @uses phpDocumentor\Reflection\Types\String
|
||||||
|
* @uses phpDocumentor\Reflection\Fqsen
|
||||||
|
*/
|
||||||
|
public function testResolvingCompoundTypes()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
/** @var Compound $resolvedType */
|
||||||
|
$resolvedType = $fixture->resolve('string|Reflection\DocBlock', new Context('phpDocumentor'));
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Compound', $resolvedType);
|
||||||
|
$this->assertSame('string|\phpDocumentor\Reflection\DocBlock', (string)$resolvedType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\String', $resolvedType->get(0));
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Fqsen', $resolvedType->get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::resolve
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
*
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testExceptionIsThrownIfTypeIsEmpty()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
$fixture->resolve(' ', new Context(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::resolve
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
*
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testExceptionIsThrownIfTypeIsNotAString()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
$fixture->resolve(['a'], new Context(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideKeywords()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['string', 'phpDocumentor\Reflection\Types\String'],
|
||||||
|
['int', 'phpDocumentor\Reflection\Types\Integer'],
|
||||||
|
['integer', 'phpDocumentor\Reflection\Types\Integer'],
|
||||||
|
['float', 'phpDocumentor\Reflection\Types\Float'],
|
||||||
|
['double', 'phpDocumentor\Reflection\Types\Float'],
|
||||||
|
['bool', 'phpDocumentor\Reflection\Types\Boolean'],
|
||||||
|
['boolean', 'phpDocumentor\Reflection\Types\Boolean'],
|
||||||
|
['resource', 'phpDocumentor\Reflection\Types\Resource'],
|
||||||
|
['null', 'phpDocumentor\Reflection\Types\Null_'],
|
||||||
|
['callable', 'phpDocumentor\Reflection\Types\Callable_'],
|
||||||
|
['callback', 'phpDocumentor\Reflection\Types\Callable_'],
|
||||||
|
['array', 'phpDocumentor\Reflection\Types\Array_'],
|
||||||
|
['scalar', 'phpDocumentor\Reflection\Types\Scalar'],
|
||||||
|
['object', 'phpDocumentor\Reflection\Types\Object_'],
|
||||||
|
['mixed', 'phpDocumentor\Reflection\Types\Mixed'],
|
||||||
|
['void', 'phpDocumentor\Reflection\Types\Void'],
|
||||||
|
['$this', 'phpDocumentor\Reflection\Types\This'],
|
||||||
|
['static', 'phpDocumentor\Reflection\Types\Static_'],
|
||||||
|
['self', 'phpDocumentor\Reflection\Types\Self_'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideFqsen()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'namespace' => ['\phpDocumentor\Reflection'],
|
||||||
|
'class' => ['\phpDocumentor\Reflection\DocBlock'],
|
||||||
|
'function' => ['\DI\object()'],
|
||||||
|
'constant' => ['\phpDocumentor\Reflection\GLOBAL_CONSTANT'],
|
||||||
|
'classConstant' => ['\phpDocumentor\Reflection\DocBlock::CONSTANT'],
|
||||||
|
'property' => ['\phpDocumentor\Reflection\DocBlock::$summary'],
|
||||||
|
'method' => ['\phpDocumentor\Reflection\DocBlock::getSummary()'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user