mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Added support for namespace expansion of a DocBlock and via the DocBlock to its tags
This commit is contained in:
@@ -36,14 +36,36 @@ class DocBlock implements \Reflector
|
|||||||
*/
|
*/
|
||||||
protected $tags = array();
|
protected $tags = array();
|
||||||
|
|
||||||
|
/** @var string the current namespace */
|
||||||
|
protected $namespace = '\\';
|
||||||
|
|
||||||
|
/** @var string[] List of namespace aliases => Fully Qualified Namespace */
|
||||||
|
protected $namespace_aliases = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the given docblock and populates the member fields.
|
* Parses the given docblock and populates the member fields.
|
||||||
*
|
*
|
||||||
* @param string|\Reflector $docblock A docblock comment (including asterisks)
|
* The constructor may also receive namespace information such as the
|
||||||
|
* current namespace and aliases. This information is used in the
|
||||||
|
* {@link expandType()} method to transform a relative Type into a FQCN.
|
||||||
|
*
|
||||||
|
* For example the param and return tags use this to expand their type
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* @param \Reflector|string $docblock A docblock comment (including asterisks)
|
||||||
* or reflector supporting the getDocComment method.
|
* or reflector supporting the getDocComment method.
|
||||||
|
* @param string $namespace The namespace where this DocBlock resides in;
|
||||||
|
* defaults to `\`.
|
||||||
|
* @param string[] $namespace_aliases a list of namespace aliases as
|
||||||
|
* provided by the `use` keyword; the key of the array is the alias name
|
||||||
|
* or last part of the alias array if no alias name is provided.
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException if the given argument does not have the
|
||||||
|
* getDocComment method.
|
||||||
*/
|
*/
|
||||||
public function __construct($docblock)
|
public function __construct(
|
||||||
{
|
$docblock, $namespace = '\\', $namespace_aliases = array()
|
||||||
|
) {
|
||||||
if (is_object($docblock)) {
|
if (is_object($docblock)) {
|
||||||
if (!method_exists($docblock, 'getDocComment')) {
|
if (!method_exists($docblock, 'getDocComment')) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
@@ -61,6 +83,9 @@ class DocBlock implements \Reflector
|
|||||||
$this->short_description = $short;
|
$this->short_description = $short;
|
||||||
$this->long_description = new DocBlock\LongDescription($long);
|
$this->long_description = new DocBlock\LongDescription($long);
|
||||||
$this->parseTags($tags);
|
$this->parseTags($tags);
|
||||||
|
|
||||||
|
$this->namespace = $namespace;
|
||||||
|
$this->namespace_aliases = $namespace_aliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,6 +296,93 @@ class DocBlock implements \Reflector
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to expand a type to it's full namespaced equivalent (FQCN).
|
||||||
|
*
|
||||||
|
* This method will take the given type and examine the current namespace
|
||||||
|
* and namespace aliases to see whether it should expand it into a FQCN
|
||||||
|
* as defined by the rules in PHP.
|
||||||
|
*
|
||||||
|
* @param string $type Type to expand into full namespaced
|
||||||
|
* equivalent.
|
||||||
|
* @param string[] $ignore_keywords Whether to ignore given keywords, when
|
||||||
|
* null it will use the default keywords: 'string', 'int', 'integer',
|
||||||
|
* 'bool', 'boolean', 'float', 'double', 'object', 'mixed', 'array',
|
||||||
|
* 'resource', 'void', 'null', 'callback', 'false', 'true'.
|
||||||
|
* Default value for this parameter is null.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function expandType($type, $ignore_keywords = null)
|
||||||
|
{
|
||||||
|
if ($type === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ignore_keywords === null) {
|
||||||
|
$ignore_keywords = array(
|
||||||
|
'string', 'int', 'integer', 'bool', 'boolean', 'float', 'double',
|
||||||
|
'object', 'mixed', 'array', 'resource', 'void', 'null',
|
||||||
|
'callback', 'false', 'true'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$namespace = '';
|
||||||
|
if ($this->namespace != 'default') {
|
||||||
|
$namespace = rtrim($this->namespace, '\\') . '\\';
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = explode('|', $type);
|
||||||
|
foreach ($type as &$item) {
|
||||||
|
$item = trim($item);
|
||||||
|
|
||||||
|
// add support for array notation
|
||||||
|
$is_array = false;
|
||||||
|
if (substr($item, -2) == '[]') {
|
||||||
|
$item = substr($item, 0, -2);
|
||||||
|
$is_array = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((substr($item, 0, 1) != '\\')
|
||||||
|
&& (!in_array(strtolower($item), $ignore_keywords))
|
||||||
|
) {
|
||||||
|
$type_parts = explode('\\', $item);
|
||||||
|
|
||||||
|
// if the first part is the keyword 'namespace', replace it
|
||||||
|
// with the current namespace
|
||||||
|
if ($type_parts[0] == 'namespace') {
|
||||||
|
$type_parts[0] = $this->getNamespace();
|
||||||
|
$item = implode('\\', $type_parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the first segment is an alias; replace with full name
|
||||||
|
if (isset($this->namespace_aliases[$type_parts[0]])) {
|
||||||
|
$type_parts[0] = $this->namespace_aliases[$type_parts[0]];
|
||||||
|
|
||||||
|
$item = implode('\\', $type_parts);
|
||||||
|
} elseif (count($type_parts) == 1) {
|
||||||
|
// prefix the item with the namespace if there is only one
|
||||||
|
// part and no alias
|
||||||
|
$item = $namespace . $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// full paths always start with a slash
|
||||||
|
if (isset($item[0]) && ($item[0] !== '\\')
|
||||||
|
&& (!in_array(strtolower($item), $ignore_keywords))
|
||||||
|
) {
|
||||||
|
$item = '\\' . $item;
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-add the array notation markers
|
||||||
|
if ($is_array) {
|
||||||
|
$item .= '[]';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode('|', $type);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a string representation of this object.
|
* Builds a string representation of this object.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
namespace phpDocumentor\Reflection;
|
namespace phpDocumentor\Reflection;
|
||||||
|
|
||||||
require_once __DIR__.'/../../../src/phpDocumentor/Reflection/DocBlock.php';
|
require_once __DIR__.'/../../../src/phpDocumentor/Reflection/DocBlock.php';
|
||||||
require_once __DIR__.'/../../../src/phpDocumentor/Reflection/DocBlock/LongDescription.php';
|
require_once __DIR__
|
||||||
|
.'/../../../src/phpDocumentor/Reflection/DocBlock/LongDescription.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for phpDocumentor_Reflection_DocBlock
|
* Test class for phpDocumentor_Reflection_DocBlock
|
||||||
@@ -38,7 +39,8 @@ DOCBLOCK;
|
|||||||
'This is a short description.', $object->getShortDescription()
|
'This is a short description.', $object->getShortDescription()
|
||||||
);
|
);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'This is a long description.', $object->getLongDescription()->getContents()
|
'This is a long description.',
|
||||||
|
$object->getLongDescription()->getContents()
|
||||||
);
|
);
|
||||||
$this->assertEquals(2, count($object->getTags()));
|
$this->assertEquals(2, count($object->getTags()));
|
||||||
$this->assertTrue($object->hasTag('see'));
|
$this->assertTrue($object->hasTag('see'));
|
||||||
@@ -58,7 +60,88 @@ DOCBLOCK;
|
|||||||
'This is a short description.', $object->getShortDescription()
|
'This is a short description.', $object->getShortDescription()
|
||||||
);
|
);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
"This is a long description.\nThis is a continuation of the long description.", $object->getLongDescription()->getContents()
|
"This is a long description.\nThis is a continuation of the long "
|
||||||
|
."description.", $object->getLongDescription()->getContents()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether a type is expanded with the given namespace and that a
|
||||||
|
* keyword is not expanded.
|
||||||
|
*
|
||||||
|
* @covers \phpDocumentor\Reflection\DocBlock::expandType()
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testExpandTypeUsingNamespace()
|
||||||
|
{
|
||||||
|
$docblock = new DocBlock('', '\My\Namespace');
|
||||||
|
$this->assertEquals('\My\Namespace\Mine', $docblock->expandType('Mine'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether a type is expanded when no namespace is given.
|
||||||
|
*
|
||||||
|
* @covers \phpDocumentor\Reflection\DocBlock::expandType()
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testExpandTypeWithoutNamespace()
|
||||||
|
{
|
||||||
|
$docblock = new DocBlock('');
|
||||||
|
$this->assertEquals('\Mine', $docblock->expandType('Mine'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether a type is expanded with the given namespace when an alias
|
||||||
|
* is provided.
|
||||||
|
*
|
||||||
|
* @covers \phpDocumentor\Reflection\DocBlock::expandType()
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testExpandTypeUsingNamespaceAlias()
|
||||||
|
{
|
||||||
|
$docblock = new DocBlock(
|
||||||
|
'', '\My\Namespace', array('Alias' => '\My\Namespace\Alias')
|
||||||
|
);
|
||||||
|
|
||||||
|
// first try a normal resolution without alias
|
||||||
|
$this->assertEquals(
|
||||||
|
'\My\Namespace\Al', $docblock->expandType('Al')
|
||||||
|
);
|
||||||
|
|
||||||
|
// try to use the alias
|
||||||
|
$this->assertEquals(
|
||||||
|
'\My\Namespace\Alias\Al', $docblock->expandType('Alias\Al')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether the keywords that should not be converted are not converted.
|
||||||
|
*
|
||||||
|
* @param string $keyword The keyword that is to be tested; this is provided
|
||||||
|
* by the dataprovider.
|
||||||
|
*
|
||||||
|
* @covers \phpDocumentor\Reflection\DocBlock::expandType()
|
||||||
|
*
|
||||||
|
* @dataProvider getNonExpandableKeywordsForExpandType
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testThatExpandTypeDoesNotExpandAllKeywords($keyword)
|
||||||
|
{
|
||||||
|
$docblock = new DocBlock('', '\My\Namespace');
|
||||||
|
$this->assertEquals($keyword, $docblock->expandType($keyword));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNonExpandableKeywordsForExpandType()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('string'), array('int'), array('integer'), array('bool'),
|
||||||
|
array('boolean'), array('float'), array('double'), array('object'),
|
||||||
|
array('mixed'), array('array'), array('resource'), array('void'),
|
||||||
|
array('null'), array('callback'), array('false'), array('true')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user