mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Compare commits
13
Commits
1.0.0-beta4
..
1.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c999e7d32a | ||
|
|
2b05ea3221 | ||
|
|
33a2e55cbc | ||
|
|
3d97a72bac | ||
|
|
51210b581e | ||
|
|
cee3c0bc21 | ||
|
|
731e797dd8 | ||
|
|
838fbfa43f | ||
|
|
4d262053fc | ||
|
|
bbac3fa418 | ||
|
|
cd252c1f09 | ||
|
|
8f8cbd9ab6 | ||
|
|
a5b50ba482 |
@@ -36,14 +36,36 @@ class DocBlock implements \Reflector
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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.
|
||||
* @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 (!method_exists($docblock, 'getDocComment')) {
|
||||
throw new \InvalidArgumentException(
|
||||
@@ -61,6 +83,9 @@ class DocBlock implements \Reflector
|
||||
$this->short_description = $short;
|
||||
$this->long_description = new DocBlock\LongDescription($long);
|
||||
$this->parseTags($tags);
|
||||
|
||||
$this->namespace = $namespace;
|
||||
$this->namespace_aliases = $namespace_aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +99,7 @@ class DocBlock implements \Reflector
|
||||
{
|
||||
$comment = trim(
|
||||
preg_replace(
|
||||
'#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#', '$1', $comment
|
||||
'#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#u', '$1', $comment
|
||||
)
|
||||
);
|
||||
|
||||
@@ -108,7 +133,7 @@ class DocBlock implements \Reflector
|
||||
} else {
|
||||
// clears all extra horizontal whitespace from the line endings
|
||||
// to prevent parsing issues
|
||||
$comment = preg_replace('~(?m)\h*$~', '', $comment);
|
||||
$comment = preg_replace('~(?m)\h*$~u', '', $comment);
|
||||
|
||||
/*
|
||||
* Splits the docblock into a short description, long description and
|
||||
@@ -127,11 +152,11 @@ class DocBlock implements \Reflector
|
||||
preg_match(
|
||||
'/(?x)
|
||||
\A (
|
||||
[^\n]+
|
||||
[^\n.]+
|
||||
(?:
|
||||
(?! (?<=\.) \n | \n{2} ) # disallow the first seperator here
|
||||
\n (?! [ \t]* @\pL ) # disallow second seperator
|
||||
[^\n]+
|
||||
(?! \. \s | \n{2} ) # disallow the first seperator here
|
||||
[\n.] (?! [ \t]* @\pL ) # disallow second seperator
|
||||
[^\n.]+
|
||||
)*
|
||||
\.?
|
||||
)
|
||||
@@ -148,7 +173,7 @@ class DocBlock implements \Reflector
|
||||
)
|
||||
)?
|
||||
(\s+ [\s\S]*)? # everything that follows
|
||||
/', $comment, $matches
|
||||
/u', $comment, $matches
|
||||
);
|
||||
array_shift($matches);
|
||||
}
|
||||
@@ -192,7 +217,9 @@ class DocBlock implements \Reflector
|
||||
|
||||
// create proper Tag objects
|
||||
foreach ($result as $key => $tag_line) {
|
||||
$result[$key] = DocBlock\Tag::createInstance($tag_line);
|
||||
$tag = DocBlock\Tag::createInstance($tag_line);
|
||||
$tag->setDocBlock($this);
|
||||
$result[$key] = $tag;
|
||||
}
|
||||
|
||||
$this->tags = $result;
|
||||
@@ -271,6 +298,84 @@ class DocBlock implements \Reflector
|
||||
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' && $this->namespace != 'global') {
|
||||
$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 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);
|
||||
} else {
|
||||
// otherwise prepend the current namespace
|
||||
$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.
|
||||
*
|
||||
|
||||
@@ -35,7 +35,7 @@ class LongDescription implements \Reflector
|
||||
*/
|
||||
public function __construct($content)
|
||||
{
|
||||
if (preg_match('/\{\@(.+?)\}/', $content, $matches)) {
|
||||
if (preg_match('/\{\@(.+?)\}/u', $content, $matches)) {
|
||||
array_shift($matches);
|
||||
foreach ($matches as $tag) {
|
||||
$this->tags[] = Tag::createInstance('@' . $tag);
|
||||
@@ -78,7 +78,7 @@ class LongDescription implements \Reflector
|
||||
);
|
||||
}
|
||||
|
||||
if (class_exists('\dflydev\markdown\MarkdownExtraParser')) {
|
||||
if (class_exists('dflydev\markdown\MarkdownExtraParser')) {
|
||||
$md = new \dflydev\markdown\MarkdownExtraParser();
|
||||
$result = $md->transformMarkdown($result);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class Tag implements \Reflector
|
||||
/** @var int line number of the tag */
|
||||
protected $line_number = 0;
|
||||
|
||||
/** @var object docblock class */
|
||||
/** @var \phpDocumentor\Reflection\DocBlock docblock class */
|
||||
protected $docblock;
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,7 +63,12 @@ class ParamTag extends Tag
|
||||
public function getTypes()
|
||||
{
|
||||
$types = explode('|', $this->type);
|
||||
array_walk($types, 'trim');
|
||||
foreach ($types as &$type) {
|
||||
$type = !empty($type) && $this->docblock
|
||||
? $this->docblock->expandType($type)
|
||||
: trim($type);
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
@@ -74,7 +79,7 @@ class ParamTag extends Tag
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
return $this->docblock->expandType($this->type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,25 +42,4 @@ class ReturnTag extends ParamTag
|
||||
$this->description = implode(' ', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the variable.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTypes()
|
||||
{
|
||||
$types = explode('|', $this->type);
|
||||
array_walk($types, 'trim');
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the variable.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/**
|
||||
* phpDocumentor Param tag test.
|
||||
*
|
||||
* @author Mike van Riel <[email protected]>
|
||||
* @copyright Copyright (c) 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tag;
|
||||
|
||||
require_once __DIR__ . '/../../../../../src/phpDocumentor/Reflection/DocBlock/Tag/ParamTag.php';
|
||||
|
||||
/**
|
||||
* Test class for phpDocumentor_Reflection_DocBlock_Param.
|
||||
*
|
||||
* @author Mike van Riel <[email protected]>
|
||||
* @copyright Copyright (c) 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
|
||||
*/
|
||||
class ParamTagTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\ParamTag can
|
||||
* understand the param DocBlock.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $content
|
||||
* @param string $extracted_type
|
||||
* @param string $extracted_variable_name
|
||||
* @param string $extracted_description
|
||||
*
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tag\ParamTag::__construct
|
||||
*
|
||||
* @dataProvider provideDataForConstructor
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConstructorParsesInputsIntoCorrectFields(
|
||||
$type, $content, $extracted_type, $extracted_variable_name,
|
||||
$extracted_description
|
||||
) {
|
||||
$tag = new ParamTag($type, $content);
|
||||
|
||||
$this->assertEquals($extracted_type, $tag->getTypes());
|
||||
$this->assertEquals($extracted_variable_name, $tag->getVariableName());
|
||||
$this->assertEquals($extracted_description, $tag->getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the getTypes method correctly converts the given tags.
|
||||
*
|
||||
* @param string $type Type string to test
|
||||
* @param string[] $expected Array of expected types
|
||||
*
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tag\ParamTag::getTypes()
|
||||
*
|
||||
* @dataProvider provideTypesToExpand
|
||||
*/
|
||||
public function testExpandTypeIntoCorrectFcqn($type, $expected)
|
||||
{
|
||||
$docblock = new \phpDocumentor\Reflection\DocBlock(
|
||||
'', '\My\Namespace', array('Alias' => '\My\Namespace\Aliasing')
|
||||
);
|
||||
|
||||
$tag = new ParamTag('param', $type.' $my_type');
|
||||
$tag->setDocBlock($docblock);
|
||||
$this->assertEquals($expected, $tag->getTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testConstructorParsesInputsIntoCorrectFields()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provideDataForConstructor()
|
||||
{
|
||||
return array(
|
||||
array('param', 'int', array(''), '', 'int'),
|
||||
array('param', '$bob', array(''), '$bob', ''),
|
||||
array(
|
||||
'param', 'int Number of bobs', array('int'), '',
|
||||
'Number of bobs'
|
||||
),
|
||||
array('param', 'int $bob', array('int'), '$bob', ''),
|
||||
array(
|
||||
'param', 'int $bob Number of bobs', array('int'), '$bob',
|
||||
'Number of bobs'
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the types and their expected values to test the retrieval of
|
||||
* types.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function provideTypesToExpand()
|
||||
{
|
||||
return array(
|
||||
array('', array('')),
|
||||
array(' ', array('')),
|
||||
array('int', array('int')),
|
||||
array('int ', array('int')),
|
||||
array('string', array('string')),
|
||||
array('DocBlock', array('\My\Namespace\DocBlock')),
|
||||
// array(' DocBlock ', array('\My\Namespace\DocBlock')), FIXME
|
||||
array('Alias\DocBlock', array('\My\Namespace\Aliasing\DocBlock')),
|
||||
array(
|
||||
'DocBlock|Tag',
|
||||
array('\My\Namespace\DocBlock', '\My\Namespace\Tag')
|
||||
),
|
||||
array(
|
||||
'DocBlock|null',
|
||||
array('\My\Namespace\DocBlock', 'null')
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* phpDocumentor Return tag test.
|
||||
*
|
||||
* @author Mike van Riel <[email protected]>
|
||||
* @copyright Copyright (c) 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tag;
|
||||
|
||||
require_once __DIR__
|
||||
. '/../../../../../src/phpDocumentor/Reflection/DocBlock/Tag/ReturnTag.php';
|
||||
|
||||
/**
|
||||
* Test class for phpDocumentor_Reflection_DocBlock_ReturnTag.
|
||||
*
|
||||
* @author Mike van Riel <[email protected]>
|
||||
* @copyright Copyright (c) 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
|
||||
*/
|
||||
class ReturnTagTest extends ParamTagTest
|
||||
{
|
||||
/**
|
||||
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\ReturnTag can
|
||||
* understand the Return DocBlock.
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $extracted_type
|
||||
* @param string $extracted_description
|
||||
*
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tag\ReturnTag::__construct
|
||||
*
|
||||
* @dataProvider provideDataForConstructor
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConstructorParsesInputsIntoCorrectFields(
|
||||
$content, $extracted_type, $extracted_description
|
||||
) {
|
||||
$tag = new ReturnTag('return', $content);
|
||||
|
||||
$this->assertEquals($extracted_type, $tag->getTypes());
|
||||
$this->assertEquals($extracted_description, $tag->getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the getTypes method correctly converts the given tags.
|
||||
*
|
||||
* @param string $type Type string to test
|
||||
* @param string[] $expected Array of expected types
|
||||
*
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tag\ReturnTag::getTypes()
|
||||
*
|
||||
* @dataProvider provideTypesToExpand
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExpandTypeIntoCorrectFcqn($type, $expected)
|
||||
{
|
||||
$docblock = new \phpDocumentor\Reflection\DocBlock(
|
||||
'', '\My\Namespace', array('Alias' => '\My\Namespace\Aliasing')
|
||||
);
|
||||
|
||||
$tag = new ReturnTag('return', $type);
|
||||
$tag->setDocBlock($docblock);
|
||||
$this->assertEquals($expected, $tag->getTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testConstructorParsesInputsIntoCorrectFields()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provideDataForConstructor()
|
||||
{
|
||||
return array(
|
||||
array('', array(''), ''),
|
||||
array('int', array('int'), ''),
|
||||
array('int Number of Bobs', array('int'), 'Number of Bobs'),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,8 @@
|
||||
namespace phpDocumentor\Reflection;
|
||||
|
||||
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
|
||||
@@ -38,10 +39,110 @@ DOCBLOCK;
|
||||
'This is a short description.', $object->getShortDescription()
|
||||
);
|
||||
$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->assertTrue($object->hasTag('see'));
|
||||
$this->assertTrue($object->hasTag('return'));
|
||||
}
|
||||
|
||||
public function testDotSeperation()
|
||||
{
|
||||
$fixture = <<<DOCBLOCK
|
||||
/**
|
||||
* This is a short description. This is a long description.
|
||||
* This is a continuation of the long description.
|
||||
*/
|
||||
DOCBLOCK;
|
||||
$object = new DocBlock($fixture);
|
||||
$this->assertEquals(
|
||||
'This is a short description.', $object->getShortDescription()
|
||||
);
|
||||
$this->assertEquals(
|
||||
"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