diff --git a/src/Barryvdh/Reflection/DocBlock.php b/src/Barryvdh/Reflection/DocBlock.php index 873e34ea..f5f1035c 100644 --- a/src/Barryvdh/Reflection/DocBlock.php +++ b/src/Barryvdh/Reflection/DocBlock.php @@ -15,6 +15,7 @@ use Barryvdh\Reflection\DocBlock\Tag; use Barryvdh\Reflection\DocBlock\Context; use Barryvdh\Reflection\DocBlock\Location; +use Barryvdh\Reflection\DocBlock\Tag\TemplateTag; /** * Parses the DocBlock for any structure. @@ -40,6 +41,9 @@ class DocBlock implements \Reflector */ protected $tags = array(); + /** @var string[] An array containing all the generics in this docblock. */ + protected $generics = array(); + /** @var Context Information about the context of this DocBlock. */ protected $context = null; @@ -238,7 +242,11 @@ protected function parseTags($tags) // create proper Tag objects foreach ($result as $key => $tag_line) { - $result[$key] = Tag::createInstance(trim($tag_line), $this); + $tag = Tag::createInstance(trim($tag_line), $this); + if ($tag instanceof TemplateTag) { + $this->generics[] = $tag->getTemplateName(); + } + $result[$key] = $tag; } } @@ -457,6 +465,16 @@ public function deleteTag(Tag $tag) return false; } + /** + * Returns the generics for this DocBlock. + * + * @return string[] + */ + public function getGenerics() + { + return $this->generics; + } + /** * Builds a string representation of this object. * diff --git a/src/Barryvdh/Reflection/DocBlock/Tag.php b/src/Barryvdh/Reflection/DocBlock/Tag.php index d56e5237..62cfe161 100644 --- a/src/Barryvdh/Reflection/DocBlock/Tag.php +++ b/src/Barryvdh/Reflection/DocBlock/Tag.php @@ -97,7 +97,9 @@ class Tag implements \Reflector 'version' => '\Barryvdh\Reflection\DocBlock\Tag\VersionTag', 'SuppressWarnings' - => '\Barryvdh\Reflection\DocBlock\Tag\SuppressWarningsTag' + => '\Barryvdh\Reflection\DocBlock\Tag\SuppressWarningsTag', + 'template' + => '\Barryvdh\Reflection\DocBlock\Tag\TemplateTag' ); /** diff --git a/src/Barryvdh/Reflection/DocBlock/Tag/ReturnTag.php b/src/Barryvdh/Reflection/DocBlock/Tag/ReturnTag.php index 65b01e48..2bb0d185 100644 --- a/src/Barryvdh/Reflection/DocBlock/Tag/ReturnTag.php +++ b/src/Barryvdh/Reflection/DocBlock/Tag/ReturnTag.php @@ -120,7 +120,8 @@ protected function getTypesCollection() if (null === $this->types) { $this->types = new Collection( array($this->type), - $this->docblock ? $this->docblock->getContext() : null + $this->docblock ? $this->docblock->getContext() : null, + $this->docblock ? $this->docblock->getGenerics() : array() ); } return $this->types; diff --git a/src/Barryvdh/Reflection/DocBlock/Tag/TemplateTag.php b/src/Barryvdh/Reflection/DocBlock/Tag/TemplateTag.php new file mode 100644 index 00000000..968ed8f5 --- /dev/null +++ b/src/Barryvdh/Reflection/DocBlock/Tag/TemplateTag.php @@ -0,0 +1,104 @@ + + * @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 Barryvdh\Reflection\DocBlock\Tag; + +/** + * Reflection class for a @template tag in a Docblock. + * + * @author chack1172 + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ +class TemplateTag extends ParamTag +{ + /** @var string */ + protected $templateName = null; + + /** @var string|null */ + protected $bound = null; + + public function getContent() + { + if (null === $this->content) { + $this->content = $this->templateName; + if (null !== $this->bound) { + $this->content .= ' of ' . $this->bound; + } + } + + return $this->content; + } + + /** + * {@inheritDoc} + */ + public function setContent($content) + { + $parts = explode(' of ', $content); + $this->templateName = $parts[0]; + if (isset($parts[1])) { + $this->bound = $parts[1]; + } + + $this->setDescription(''); + $this->content = $content; + return $this; + } + + /** + * Gets the template name + * + * @return string + */ + public function getTemplateName() + { + return $this->templateName; + } + + /** + * Sets the template name + * + * @param string $templateName + * + * @return $this + */ + public function setTemplateName($templateName) + { + $this->templateName = $templateName; + $this->content = null; + return $this; + } + + /** + * Gets the bound type + * + * @return string|null + */ + public function getBound() + { + return $this->bound; + } + + /** + * Sets the bound type + * @param string|null $bound + * @return $this + */ + public function setBound($bound) + { + $this->bound = $bound; + $this->content = null; + return $this; + } +} diff --git a/src/Barryvdh/Reflection/DocBlock/Type/Collection.php b/src/Barryvdh/Reflection/DocBlock/Type/Collection.php index 3cf3a373..936ee285 100644 --- a/src/Barryvdh/Reflection/DocBlock/Type/Collection.php +++ b/src/Barryvdh/Reflection/DocBlock/Type/Collection.php @@ -50,6 +50,13 @@ class Collection extends \ArrayObject */ protected $context = null; + /** + * List of generics types + * + * @var string[] + */ + protected $generics = array(); + /** * Registers the namespace and aliases; uses that to add and expand the * given types. @@ -60,9 +67,11 @@ class Collection extends \ArrayObject */ public function __construct( array $types = array(), - ?Context $context = null + ?Context $context = null, + array $generics = array() ) { $this->context = null === $context ? new Context() : $context; + $this->generics = $generics; foreach ($types as $type) { $this->add($type); @@ -197,7 +206,7 @@ protected function expand($type) return $this->expand(substr($type, 0, -2)) . self::OPERATOR_ARRAY; } - if ($this->isRelativeType($type) && !$this->isTypeAKeyword($type)) { + if ($this->isRelativeType($type) && !$this->isTypeAKeyword($type) && !$this->isTypeAGeneric($type)) { if($this->shouldBeAbsolute($type)){ return self::OPERATOR_NAMESPACE . $type; @@ -273,6 +282,19 @@ protected function isRelativeType($type) || $this->isTypeAKeyword($type); } + /** + * Detects whether the given type represents a generic. + * + * @param string $type A relative or absolute type as defined in the + * phpDocumentor documentation. + * + * @return bool + */ + protected function isTypeAGeneric($type) + { + return in_array($type, $this->generics, true); + } + /** * Detects if the type should actually be absolute, by checking if it exists. * diff --git a/tests/Barryvdh/Reflection/DocBlock/Tag/TemplateTagTest.php b/tests/Barryvdh/Reflection/DocBlock/Tag/TemplateTagTest.php new file mode 100644 index 00000000..c7991439 --- /dev/null +++ b/tests/Barryvdh/Reflection/DocBlock/Tag/TemplateTagTest.php @@ -0,0 +1,86 @@ + + * @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 Barryvdh\Reflection\DocBlock\Tag; + +use PHPUnit\Framework\TestCase; + +/** + * Test class for \Barryvdh\Reflection\DocBlock\Tag\TemplateTag + * + * @author Daniel O'Connor + * @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 TemplateTagTest extends TestCase +{ + /** + * Test that the phpDocumentor_Reflection_DocBlock_Tag_See can create a link + * for the @see doc block. + * + * @param string $type + * @param string $content + * @param string $exContent + * @param string $exReference + * + * @covers \Barryvdh\Reflection\DocBlock\Tag\SeeTag + * @dataProvider provideDataForConstuctor + * + * @return void + */ + public function testConstructorParesInputsIntoCorrectFields( + $type, + $content, + $exContent, + $exDescription, + $exTemplateName, + $exBound + ) { + $tag = new TemplateTag($type, $content); + + $this->assertEquals($type, $tag->getName()); + $this->assertEquals($exContent, $tag->getContent()); + $this->assertEquals($exDescription, $tag->getDescription()); + $this->assertEquals($exTemplateName, $tag->getTemplateName()); + $this->assertEquals($exBound, $tag->getBound()); + } + + /** + * Data provider for testConstructorParesInputsIntoCorrectFields + * + * @return array + */ + public function provideDataForConstuctor() + { + // $type, $content, $exContent, $exDescription, $exTemplateName, $exBound + return array( + array( + 'template', + 'TValue', + 'TValue', + '', + 'TValue', + null, + ), + array( + 'template', + 'TValue of string', + 'TValue of string', + '', + 'TValue', + 'string', + ), + ); + } +} diff --git a/tests/Barryvdh/Reflection/DocBlock/Type/CollectionTest.php b/tests/Barryvdh/Reflection/DocBlock/Type/CollectionTest.php index b1b456f2..b3dcba00 100644 --- a/tests/Barryvdh/Reflection/DocBlock/Type/CollectionTest.php +++ b/tests/Barryvdh/Reflection/DocBlock/Type/CollectionTest.php @@ -144,6 +144,27 @@ public function testAddMethodsAndProperties($fixture, $expected) $this->assertSame($expected, $collection->getArrayCopy()); } + /** + * @param string $fixture + * @param array $expected + * + * @dataProvider provideTypesToExpandWithGenerics + * @covers Barryvdh\Reflection\DocBlock\Type\Collection::add + * + * @return void + */ + public function testAddWithGenerics($fixture, $expected) + { + $collection = new Collection( + array(), + new Context('\My\Space', array('Alias' => '\My\Space\Aliasing')), + array('TValue') + ); + $collection->add($fixture); + + $this->assertSame($expected, $collection->getArrayCopy()); + } + /** * @covers Barryvdh\Reflection\DocBlock\Type\Collection::add * @@ -267,4 +288,22 @@ public function provideTypesToExpandWithPropertyOrMethod($method) ), ); } + + /** + * Returns the types and their expected values to test the retrieval of + * types including generics. + * + * @param string $method Name of the method consuming this data provider. + * @param string $namespace Name of the namespace to user as basis. + * + * @return string[] + */ + public function provideTypesToExpandWithGenerics($method, $namespace = '\My\Space\\') + { + return array( + array('TValue', array('TValue')), + array('TValue[]', array('TValue[]')), + array('TValue|DocBlock', array('TValue', $namespace . 'DocBlock')), + ); + } } diff --git a/tests/Barryvdh/Reflection/DocBlockTest.php b/tests/Barryvdh/Reflection/DocBlockTest.php index ab197a60..88ad7db7 100644 --- a/tests/Barryvdh/Reflection/DocBlockTest.php +++ b/tests/Barryvdh/Reflection/DocBlockTest.php @@ -336,4 +336,22 @@ public function testGetTagsByNameMultipleMatch() $this->assertCount(1, $object->getTagsByName('return')); $this->assertCount(2, $object->getTagsByName('param')); } + + /** + * @covers \Barryvdh\Reflection\DocBlock::parseTags + * + * @return void + */ + public function testGenericsAreParsed() + { + $fixture = <<assertSame(array('TValue'), $object->getGenerics()); + } }