mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Merge pull request #54 from mvriel/feature/refactor-to-v2
Add support for types and improve resolution
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
namespace phpDocumentor\Reflection;
|
||||||
|
|
||||||
|
interface DocBlockFactoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Factory method for easy instantiation.
|
||||||
|
*
|
||||||
|
* @param string[] $additionalTags
|
||||||
|
*
|
||||||
|
* @return DocBlockFactory
|
||||||
|
*/
|
||||||
|
public static function createInstance(array $additionalTags = []);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $docblock
|
||||||
|
* @param DocBlock\Context $context
|
||||||
|
* @param DocBlock\Location $location
|
||||||
|
*
|
||||||
|
* @return DocBlock
|
||||||
|
*/
|
||||||
|
public function create($docblock, DocBlock\Context $context = null, DocBlock\Location $location = null);
|
||||||
|
}
|
||||||
@@ -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,87 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an array type as described in the PSR-5, the PHPDoc Standard.
|
||||||
|
*
|
||||||
|
* An array can be represented in two forms:
|
||||||
|
*
|
||||||
|
* 1. Untyped (`array`), where the key and value type is unknown and hence classified as 'Mixed'.
|
||||||
|
* 2. Types (`string[]`), where the value type is provided by preceding an opening and closing square bracket with a
|
||||||
|
* type name.
|
||||||
|
*/
|
||||||
|
final class Array_ implements Type
|
||||||
|
{
|
||||||
|
/** @var Type */
|
||||||
|
private $valueType;
|
||||||
|
|
||||||
|
/** @var Type */
|
||||||
|
private $keyType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes this representation of an array with the given Type or Fqsen.
|
||||||
|
*
|
||||||
|
* @param Type $valueType
|
||||||
|
* @param Type $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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type for the keys of this array.
|
||||||
|
*
|
||||||
|
* @return Type
|
||||||
|
*/
|
||||||
|
public function getKeyType()
|
||||||
|
{
|
||||||
|
return $this->keyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value for the keys of this array.
|
||||||
|
*
|
||||||
|
* @return Type
|
||||||
|
*/
|
||||||
|
public function getValueType()
|
||||||
|
{
|
||||||
|
return $this->valueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
if ($this->valueType instanceof Mixed) {
|
||||||
|
return 'array';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->valueType . '[]';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing a Boolean type.
|
||||||
|
*/
|
||||||
|
final class Boolean implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'bool';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing a Callable type.
|
||||||
|
*/
|
||||||
|
final class Callable_ implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'callable';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing a Compound Type.
|
||||||
|
*
|
||||||
|
* A Compound Type is not so much a special keyword or object reference but is a series of Types that are separated
|
||||||
|
* using an OR operator (`|`). This combination of types signifies that whatever is associated with this compound type
|
||||||
|
* may contain a value with any of the given types.
|
||||||
|
*/
|
||||||
|
final class Compound implements Type
|
||||||
|
{
|
||||||
|
/** @var Type[] */
|
||||||
|
private $types = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a compound type (i.e. `string|int`) and tests if the provided types all implement the Type interface.
|
||||||
|
*
|
||||||
|
* @param Type[] $types
|
||||||
|
*/
|
||||||
|
public function __construct($types)
|
||||||
|
{
|
||||||
|
foreach ($types as $type) {
|
||||||
|
if (!$type instanceof Type) {
|
||||||
|
throw new \InvalidArgumentException('A compound type can only have other types as elements');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->types = $types;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type at the given index.
|
||||||
|
*
|
||||||
|
* @param integer $index
|
||||||
|
*
|
||||||
|
* @return Type|null
|
||||||
|
*/
|
||||||
|
public function get($index)
|
||||||
|
{
|
||||||
|
if (!$this->has($index)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->types[$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if this compound type has a type with the given index.
|
||||||
|
*
|
||||||
|
* @param integer $index
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function has($index)
|
||||||
|
{
|
||||||
|
return isset($this->types[$index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return implode('|', $this->types);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing a Float.
|
||||||
|
*/
|
||||||
|
final class Float implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'float';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?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
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'int';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing an unknown, or mixed, type.
|
||||||
|
*/
|
||||||
|
final class Mixed implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'mixed';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing a null value or type.
|
||||||
|
*/
|
||||||
|
final class Null_ implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing an object.
|
||||||
|
*
|
||||||
|
* An object can be either typed or untyped. When an object is typed it means that it has an identifier, the FQSEN,
|
||||||
|
* pointing to an element in PHP. Object types that are untyped do not refer to a specific class but represent objects
|
||||||
|
* in general.
|
||||||
|
*/
|
||||||
|
final class Object_ implements Type
|
||||||
|
{
|
||||||
|
/** @var Fqsen|null */
|
||||||
|
private $fqsen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes this object with an optional FQSEN, if not provided this object is considered 'untyped'.
|
||||||
|
*
|
||||||
|
* @param Fqsen $fqsen
|
||||||
|
*/
|
||||||
|
public function __construct(Fqsen $fqsen = null)
|
||||||
|
{
|
||||||
|
if (strpos((string)$fqsen, '::') !== false || strpos((string)$fqsen, '()') !== false) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
'Object types can only refer to a class, interface or trait but a method, function, constant or '
|
||||||
|
. 'property was received: ' . (string)$fqsen
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->fqsen = $fqsen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the FQSEN associated with this object.
|
||||||
|
*
|
||||||
|
* @return Fqsen|null
|
||||||
|
*/
|
||||||
|
public function getFqsen()
|
||||||
|
{
|
||||||
|
return $this->fqsen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
if ($this->fqsen) {
|
||||||
|
return (string)$this->fqsen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'object';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,276 @@
|
|||||||
|
<?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\Type;
|
||||||
|
|
||||||
|
final 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 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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a keyword to the list of Keywords and associates it with a specific Value Object.
|
||||||
|
*
|
||||||
|
* @param string $keyword
|
||||||
|
* @param string $typeClassName
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addKeyword($keyword, $typeClassName)
|
||||||
|
{
|
||||||
|
if (!class_exists($typeClassName)) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
'The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class'
|
||||||
|
. ' but we could not find the class ' . $typeClassName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array(Type::class, class_implements($typeClassName))) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
'The class "' . $typeClassName . '" must implement the interface "phpDocumentor\Reflection\Type"'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->keywords[$keyword] = $typeClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 Object_
|
||||||
|
*/
|
||||||
|
private function resolveFqsen($type)
|
||||||
|
{
|
||||||
|
return new Object_(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 Object_
|
||||||
|
*/
|
||||||
|
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 Object_(new Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type));
|
||||||
|
}
|
||||||
|
|
||||||
|
$typeParts[0] = $namespaceAliases[$typeParts[0]];
|
||||||
|
|
||||||
|
return new Object_(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,31 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing the 'resource' Type.
|
||||||
|
*/
|
||||||
|
final class Resource implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'resource';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing the 'scalar' pseudo-type, which is either a string, integer, float or boolean.
|
||||||
|
*/
|
||||||
|
final class Scalar implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'scalar';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing the 'self' type.
|
||||||
|
*
|
||||||
|
* Self, as a Type, represents the class in which the associated element was defined.
|
||||||
|
*/
|
||||||
|
final class Self_ implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'self';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing the 'static' type.
|
||||||
|
*
|
||||||
|
* Self, as a Type, represents the class in which the associated element was called. This differs from self as self does
|
||||||
|
* not take inheritance into account but static means that the return type is always that of the class of the called
|
||||||
|
* element.
|
||||||
|
*
|
||||||
|
* See the documentation on late static binding in the PHP Documentation for more information on the difference between
|
||||||
|
* static and self.
|
||||||
|
*/
|
||||||
|
final class Static_ implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'static';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing the type 'string'.
|
||||||
|
*/
|
||||||
|
final class String implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'string';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing the '$this' pseudo-type.
|
||||||
|
*
|
||||||
|
* $this, as a Type, represents the instance of the class associated with the element as it was called. $this is
|
||||||
|
* commonly used when documenting fluent interfaces since it represents that the same object is returned.
|
||||||
|
*/
|
||||||
|
final class This implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return '$this';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value Object representing the pseudo-type 'void'.
|
||||||
|
*
|
||||||
|
* Void is generally only used when working with return types as it signifies that the method intentionally does not
|
||||||
|
* return any value.
|
||||||
|
*/
|
||||||
|
final class Void implements Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a rendered output of the Type as it would be used in a DocBlock.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return 'void';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* phpDocumentor
|
|
||||||
*
|
|
||||||
* PHP Version 5.3
|
|
||||||
*
|
|
||||||
* @author Mike van Riel <[email protected]>
|
|
||||||
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
|
|
||||||
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
|
||||||
* @link http://phpdoc.org
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace phpDocumentor\Reflection\DocBlock\Type;
|
|
||||||
|
|
||||||
use phpDocumentor\Reflection\DocBlock\Context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collection
|
|
||||||
*
|
|
||||||
* @author Mike van Riel <[email protected]>
|
|
||||||
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
|
|
||||||
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
|
||||||
* @link http://phpdoc.org
|
|
||||||
*/
|
|
||||||
class Collection extends \ArrayObject
|
|
||||||
{
|
|
||||||
/** @var string Definition of the OR operator for types */
|
|
||||||
const OPERATOR_OR = '|';
|
|
||||||
|
|
||||||
/** @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 */
|
|
||||||
protected static $keywords = array(
|
|
||||||
'string', 'int', 'integer', 'bool', 'boolean', 'float', 'double',
|
|
||||||
'object', 'mixed', 'array', 'resource', 'void', 'null', 'scalar',
|
|
||||||
'callback', 'callable', 'false', 'true', 'self', '$this', 'static'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 $location The current invoking location.
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
array $types = array(),
|
|
||||||
Context $context = null
|
|
||||||
) {
|
|
||||||
$this->context = null === $context ? new Context() : $context;
|
|
||||||
|
|
||||||
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->expand($part);
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 getNamespace to determine with what to prefix the type name.
|
|
||||||
* @uses getNamespaceAliases to check whether the first part of the relative
|
|
||||||
* type name should not be replaced with another namespace.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function expand($type)
|
|
||||||
{
|
|
||||||
$type = trim($type);
|
|
||||||
if (!$type) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isTypeAnArray($type)) {
|
|
||||||
return $this->expand(substr($type, 0, -2)) . self::OPERATOR_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isRelativeType($type) && !$this->isTypeAKeyword($type)) {
|
|
||||||
$type_parts = explode(self::OPERATOR_NAMESPACE, $type, 2);
|
|
||||||
|
|
||||||
$namespace_aliases = $this->context->getNamespaceAliases();
|
|
||||||
// if the first segment is not an alias; prepend namespace name and
|
|
||||||
// return
|
|
||||||
if (!isset($namespace_aliases[$type_parts[0]])) {
|
|
||||||
$namespace = $this->context->getNamespace();
|
|
||||||
if ('' !== $namespace) {
|
|
||||||
$namespace .= self::OPERATOR_NAMESPACE;
|
|
||||||
}
|
|
||||||
return self::OPERATOR_NAMESPACE . $namespace . $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
$type_parts[0] = $namespace_aliases[$type_parts[0]];
|
|
||||||
$type = implode(self::OPERATOR_NAMESPACE, $type_parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detects whether the given type represents an array.
|
|
||||||
*
|
|
||||||
* @param string $type A relative or absolute type as defined in the
|
|
||||||
* phpDocumentor documentation.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function isTypeAnArray($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
|
|
||||||
*/
|
|
||||||
protected function isTypeAKeyword($type)
|
|
||||||
{
|
|
||||||
return in_array(strtolower($type), static::$keywords, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detects whether the given type represents a relative or absolute path.
|
|
||||||
*
|
|
||||||
* This method will detect keywords as being absolute; even though they are
|
|
||||||
* not preceeded by a namespace separator.
|
|
||||||
*
|
|
||||||
* @param string $type A relative or absolute type as defined in the
|
|
||||||
* phpDocumentor documentation.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function isRelativeType($type)
|
|
||||||
{
|
|
||||||
return ($type[0] !== self::OPERATOR_NAMESPACE)
|
|
||||||
|| $this->isTypeAKeyword($type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,348 @@
|
|||||||
|
<?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 Mockery as m;
|
||||||
|
use phpDocumentor\Reflection\DocBlock\Context;
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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_
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Object_
|
||||||
|
*
|
||||||
|
* @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\Types\Object_
|
||||||
|
* @uses phpDocumentor\Reflection\Fqsen
|
||||||
|
*
|
||||||
|
* @dataProvider provideFqsen
|
||||||
|
*/
|
||||||
|
public function testResolvingFQSENs($fqsen)
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
/** @var Object_ $resolvedType */
|
||||||
|
$resolvedType = $fixture->resolve($fqsen, new Context(''));
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Object_', $resolvedType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Fqsen', $resolvedType->getFqsen());
|
||||||
|
$this->assertSame($fqsen, (string)$resolvedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Object_
|
||||||
|
* @uses phpDocumentor\Reflection\Fqsen
|
||||||
|
*/
|
||||||
|
public function testResolvingRelativeQSENsBasedOnNamespace()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
/** @var Object_ $resolvedType */
|
||||||
|
$resolvedType = $fixture->resolve('DocBlock', new Context('phpDocumentor\Reflection'));
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Object_', $resolvedType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Fqsen', $resolvedType->getFqsen());
|
||||||
|
$this->assertSame('\phpDocumentor\Reflection\DocBlock', (string)$resolvedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Object_
|
||||||
|
* @uses phpDocumentor\Reflection\Fqsen
|
||||||
|
*/
|
||||||
|
public function testResolvingRelativeQSENsBasedOnNamespaceAlias()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
/** @var Object_ $resolvedType */
|
||||||
|
$resolvedType = $fixture->resolve(
|
||||||
|
'm\MockInterface',
|
||||||
|
new Context('phpDocumentor\Reflection', ['m' => '\Mockery'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Object_', $resolvedType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Fqsen', $resolvedType->getFqsen());
|
||||||
|
$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\Types\Object_
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
/** @var String $secondType */
|
||||||
|
$firstType = $resolvedType->get(0);
|
||||||
|
|
||||||
|
/** @var Object_ $secondType */
|
||||||
|
$secondType = $resolvedType->get(1);
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\String', $firstType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Object_', $secondType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Fqsen', $secondType->getFqsen());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test asserts that the parameter order is correct.
|
||||||
|
*
|
||||||
|
* When you pass two arrays separated by the compound operator (i.e. 'integer[]|string[]') then we always split the
|
||||||
|
* expression in its compound parts and then we parse the types with the array operators. If we were to switch the
|
||||||
|
* order around then 'integer[]|string[]' would read as an array of string or integer array; which is something
|
||||||
|
* other than what we intend.
|
||||||
|
*
|
||||||
|
* @covers ::resolve
|
||||||
|
* @covers ::<private>
|
||||||
|
*
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Compound
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Array_
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Integer
|
||||||
|
* @uses phpDocumentor\Reflection\Types\String
|
||||||
|
*/
|
||||||
|
public function testResolvingCompoundTypesWithTwoArrays()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
|
||||||
|
/** @var Compound $resolvedType */
|
||||||
|
$resolvedType = $fixture->resolve('integer[]|string[]', new Context(''));
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Compound', $resolvedType);
|
||||||
|
$this->assertSame('int[]|string[]', (string)$resolvedType);
|
||||||
|
|
||||||
|
/** @var Array_ $firstType */
|
||||||
|
$firstType = $resolvedType->get(0);
|
||||||
|
|
||||||
|
/** @var Array_ $secondType */
|
||||||
|
$secondType = $resolvedType->get(1);
|
||||||
|
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Array_', $firstType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Integer', $firstType->getValueType());
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\Array_', $secondType);
|
||||||
|
$this->assertInstanceOf('phpDocumentor\Reflection\Types\String', $secondType->getValueType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::addKeyword
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Resolver::resolve
|
||||||
|
* @uses phpDocumentor\Reflection\Types\Resolver::<private>
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
*/
|
||||||
|
public function testAddingAKeyword()
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
$typeMock = m::mock(Type::class);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
$fixture = new Resolver();
|
||||||
|
$fixture->addKeyword('mock', get_class($typeMock));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
$result = $fixture->resolve('mock', new Context(''));
|
||||||
|
$this->assertInstanceOf(get_class($typeMock), $result);
|
||||||
|
$this->assertNotSame($typeMock, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::addKeyword
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testAddingAKeywordFailsIfTypeClassDoesNotExist()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
$fixture->addKeyword('mock', 'IDoNotExist');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::addKeyword
|
||||||
|
* @uses phpDocumentor\Reflection\DocBlock\Context
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testAddingAKeywordFailsIfTypeClassDoesNotImplementTypeInterface()
|
||||||
|
{
|
||||||
|
$fixture = new Resolver();
|
||||||
|
$fixture->addKeyword('mock', 'stdClass');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of keywords and expected classes that are created from them.
|
||||||
|
*
|
||||||
|
* @return string[][]
|
||||||
|
*/
|
||||||
|
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_'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a list of FQSENs to test the resolution patterns with.
|
||||||
|
*
|
||||||
|
* @return string[][]
|
||||||
|
*/
|
||||||
|
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