Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse template tag for generics #21

Merged
merged 5 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/Barryvdh/Reflection/DocBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;

Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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.
*
Expand Down
4 changes: 3 additions & 1 deletion src/Barryvdh/Reflection/DocBlock/Tag.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'
);

/**
Expand Down
3 changes: 2 additions & 1 deletion src/Barryvdh/Reflection/DocBlock/Tag/ReturnTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
104 changes: 104 additions & 0 deletions src/Barryvdh/Reflection/DocBlock/Tag/TemplateTag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?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 Barryvdh\Reflection\DocBlock\Tag;

/**
* Reflection class for a @template tag in a Docblock.
*
* @author chack1172 <[email protected]>
* @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;
}
}
26 changes: 24 additions & 2 deletions src/Barryvdh/Reflection/DocBlock/Type/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
*
Expand Down
86 changes: 86 additions & 0 deletions tests/Barryvdh/Reflection/DocBlock/Tag/TemplateTagTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

/**
* phpDocumentor Template Tag Test
*
* PHP version 5.3
*
* @author Daniel O'Connor <[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 Barryvdh\Reflection\DocBlock\Tag;

use PHPUnit\Framework\TestCase;

/**
* Test class for \Barryvdh\Reflection\DocBlock\Tag\TemplateTag
*
* @author Daniel O'Connor <[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 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',
),
);
}
}
39 changes: 39 additions & 0 deletions tests/Barryvdh/Reflection/DocBlock/Type/CollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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')),
);
}
}
18 changes: 18 additions & 0 deletions tests/Barryvdh/Reflection/DocBlockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <<<DOCBLOCK
/**
* @template TValue
* @param TValue
* @return TValue
*/
DOCBLOCK;
$object = new DocBlock($fixture);
$this->assertSame(array('TValue'), $object->getGenerics());
}
}
Loading