Skip to content

Commit d5d2d76

Browse files
authored
Parse template tag for generics (#21)
* Parse template tag for generics * Fixed templatetag docblock * Fixed PHP 7 issue * Fixed PHP 7.2 issue * Fixed another 7.2 issue
1 parent fba297a commit d5d2d76

File tree

8 files changed

+295
-5
lines changed

8 files changed

+295
-5
lines changed

src/Barryvdh/Reflection/DocBlock.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Barryvdh\Reflection\DocBlock\Tag;
1616
use Barryvdh\Reflection\DocBlock\Context;
1717
use Barryvdh\Reflection\DocBlock\Location;
18+
use Barryvdh\Reflection\DocBlock\Tag\TemplateTag;
1819

1920
/**
2021
* Parses the DocBlock for any structure.
@@ -40,6 +41,9 @@ class DocBlock implements \Reflector
4041
*/
4142
protected $tags = array();
4243

44+
/** @var string[] An array containing all the generics in this docblock. */
45+
protected $generics = array();
46+
4347
/** @var Context Information about the context of this DocBlock. */
4448
protected $context = null;
4549

@@ -238,7 +242,11 @@ protected function parseTags($tags)
238242

239243
// create proper Tag objects
240244
foreach ($result as $key => $tag_line) {
241-
$result[$key] = Tag::createInstance(trim($tag_line), $this);
245+
$tag = Tag::createInstance(trim($tag_line), $this);
246+
if ($tag instanceof TemplateTag) {
247+
$this->generics[] = $tag->getTemplateName();
248+
}
249+
$result[$key] = $tag;
242250
}
243251
}
244252

@@ -457,6 +465,16 @@ public function deleteTag(Tag $tag)
457465
return false;
458466
}
459467

468+
/**
469+
* Returns the generics for this DocBlock.
470+
*
471+
* @return string[]
472+
*/
473+
public function getGenerics()
474+
{
475+
return $this->generics;
476+
}
477+
460478
/**
461479
* Builds a string representation of this object.
462480
*

src/Barryvdh/Reflection/DocBlock/Tag.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ class Tag implements \Reflector
9797
'version'
9898
=> '\Barryvdh\Reflection\DocBlock\Tag\VersionTag',
9999
'SuppressWarnings'
100-
=> '\Barryvdh\Reflection\DocBlock\Tag\SuppressWarningsTag'
100+
=> '\Barryvdh\Reflection\DocBlock\Tag\SuppressWarningsTag',
101+
'template'
102+
=> '\Barryvdh\Reflection\DocBlock\Tag\TemplateTag'
101103
);
102104

103105
/**

src/Barryvdh/Reflection/DocBlock/Tag/ReturnTag.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ protected function getTypesCollection()
120120
if (null === $this->types) {
121121
$this->types = new Collection(
122122
array($this->type),
123-
$this->docblock ? $this->docblock->getContext() : null
123+
$this->docblock ? $this->docblock->getContext() : null,
124+
$this->docblock ? $this->docblock->getGenerics() : array()
124125
);
125126
}
126127
return $this->types;
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
/**
4+
* phpDocumentor
5+
*
6+
* PHP Version 5.3
7+
*
8+
* @author Mike van Riel <[email protected]>
9+
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
10+
* @license http://www.opensource.org/licenses/mit-license.php MIT
11+
* @link http://phpdoc.org
12+
*/
13+
14+
namespace Barryvdh\Reflection\DocBlock\Tag;
15+
16+
/**
17+
* Reflection class for a @template tag in a Docblock.
18+
*
19+
* @author chack1172 <[email protected]>
20+
* @license http://www.opensource.org/licenses/mit-license.php MIT
21+
* @link http://phpdoc.org
22+
*/
23+
class TemplateTag extends ParamTag
24+
{
25+
/** @var string */
26+
protected $templateName = null;
27+
28+
/** @var string|null */
29+
protected $bound = null;
30+
31+
public function getContent()
32+
{
33+
if (null === $this->content) {
34+
$this->content = $this->templateName;
35+
if (null !== $this->bound) {
36+
$this->content .= ' of ' . $this->bound;
37+
}
38+
}
39+
40+
return $this->content;
41+
}
42+
43+
/**
44+
* {@inheritDoc}
45+
*/
46+
public function setContent($content)
47+
{
48+
$parts = explode(' of ', $content);
49+
$this->templateName = $parts[0];
50+
if (isset($parts[1])) {
51+
$this->bound = $parts[1];
52+
}
53+
54+
$this->setDescription('');
55+
$this->content = $content;
56+
return $this;
57+
}
58+
59+
/**
60+
* Gets the template name
61+
*
62+
* @return string
63+
*/
64+
public function getTemplateName()
65+
{
66+
return $this->templateName;
67+
}
68+
69+
/**
70+
* Sets the template name
71+
*
72+
* @param string $templateName
73+
*
74+
* @return $this
75+
*/
76+
public function setTemplateName($templateName)
77+
{
78+
$this->templateName = $templateName;
79+
$this->content = null;
80+
return $this;
81+
}
82+
83+
/**
84+
* Gets the bound type
85+
*
86+
* @return string|null
87+
*/
88+
public function getBound()
89+
{
90+
return $this->bound;
91+
}
92+
93+
/**
94+
* Sets the bound type
95+
* @param string|null $bound
96+
* @return $this
97+
*/
98+
public function setBound($bound)
99+
{
100+
$this->bound = $bound;
101+
$this->content = null;
102+
return $this;
103+
}
104+
}

src/Barryvdh/Reflection/DocBlock/Type/Collection.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ class Collection extends \ArrayObject
5050
*/
5151
protected $context = null;
5252

53+
/**
54+
* List of generics types
55+
*
56+
* @var string[]
57+
*/
58+
protected $generics = array();
59+
5360
/**
5461
* Registers the namespace and aliases; uses that to add and expand the
5562
* given types.
@@ -60,9 +67,11 @@ class Collection extends \ArrayObject
6067
*/
6168
public function __construct(
6269
array $types = array(),
63-
?Context $context = null
70+
?Context $context = null,
71+
array $generics = array()
6472
) {
6573
$this->context = null === $context ? new Context() : $context;
74+
$this->generics = $generics;
6675

6776
foreach ($types as $type) {
6877
$this->add($type);
@@ -197,7 +206,7 @@ protected function expand($type)
197206
return $this->expand(substr($type, 0, -2)) . self::OPERATOR_ARRAY;
198207
}
199208

200-
if ($this->isRelativeType($type) && !$this->isTypeAKeyword($type)) {
209+
if ($this->isRelativeType($type) && !$this->isTypeAKeyword($type) && !$this->isTypeAGeneric($type)) {
201210

202211
if($this->shouldBeAbsolute($type)){
203212
return self::OPERATOR_NAMESPACE . $type;
@@ -273,6 +282,19 @@ protected function isRelativeType($type)
273282
|| $this->isTypeAKeyword($type);
274283
}
275284

285+
/**
286+
* Detects whether the given type represents a generic.
287+
*
288+
* @param string $type A relative or absolute type as defined in the
289+
* phpDocumentor documentation.
290+
*
291+
* @return bool
292+
*/
293+
protected function isTypeAGeneric($type)
294+
{
295+
return in_array($type, $this->generics, true);
296+
}
297+
276298
/**
277299
* Detects if the type should actually be absolute, by checking if it exists.
278300
*
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
/**
4+
* phpDocumentor Template Tag Test
5+
*
6+
* PHP version 5.3
7+
*
8+
* @author Daniel O'Connor <[email protected]>
9+
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
10+
* @license http://www.opensource.org/licenses/mit-license.php MIT
11+
* @link http://phpdoc.org
12+
*/
13+
14+
namespace Barryvdh\Reflection\DocBlock\Tag;
15+
16+
use PHPUnit\Framework\TestCase;
17+
18+
/**
19+
* Test class for \Barryvdh\Reflection\DocBlock\Tag\TemplateTag
20+
*
21+
* @author Daniel O'Connor <[email protected]>
22+
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
23+
* @license http://www.opensource.org/licenses/mit-license.php MIT
24+
* @link http://phpdoc.org
25+
*/
26+
class TemplateTagTest extends TestCase
27+
{
28+
/**
29+
* Test that the phpDocumentor_Reflection_DocBlock_Tag_See can create a link
30+
* for the @see doc block.
31+
*
32+
* @param string $type
33+
* @param string $content
34+
* @param string $exContent
35+
* @param string $exReference
36+
*
37+
* @covers \Barryvdh\Reflection\DocBlock\Tag\SeeTag
38+
* @dataProvider provideDataForConstuctor
39+
*
40+
* @return void
41+
*/
42+
public function testConstructorParesInputsIntoCorrectFields(
43+
$type,
44+
$content,
45+
$exContent,
46+
$exDescription,
47+
$exTemplateName,
48+
$exBound
49+
) {
50+
$tag = new TemplateTag($type, $content);
51+
52+
$this->assertEquals($type, $tag->getName());
53+
$this->assertEquals($exContent, $tag->getContent());
54+
$this->assertEquals($exDescription, $tag->getDescription());
55+
$this->assertEquals($exTemplateName, $tag->getTemplateName());
56+
$this->assertEquals($exBound, $tag->getBound());
57+
}
58+
59+
/**
60+
* Data provider for testConstructorParesInputsIntoCorrectFields
61+
*
62+
* @return array
63+
*/
64+
public function provideDataForConstuctor()
65+
{
66+
// $type, $content, $exContent, $exDescription, $exTemplateName, $exBound
67+
return array(
68+
array(
69+
'template',
70+
'TValue',
71+
'TValue',
72+
'',
73+
'TValue',
74+
null,
75+
),
76+
array(
77+
'template',
78+
'TValue of string',
79+
'TValue of string',
80+
'',
81+
'TValue',
82+
'string',
83+
),
84+
);
85+
}
86+
}

tests/Barryvdh/Reflection/DocBlock/Type/CollectionTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,27 @@ public function testAddMethodsAndProperties($fixture, $expected)
144144
$this->assertSame($expected, $collection->getArrayCopy());
145145
}
146146

147+
/**
148+
* @param string $fixture
149+
* @param array $expected
150+
*
151+
* @dataProvider provideTypesToExpandWithGenerics
152+
* @covers Barryvdh\Reflection\DocBlock\Type\Collection::add
153+
*
154+
* @return void
155+
*/
156+
public function testAddWithGenerics($fixture, $expected)
157+
{
158+
$collection = new Collection(
159+
array(),
160+
new Context('\My\Space', array('Alias' => '\My\Space\Aliasing')),
161+
array('TValue')
162+
);
163+
$collection->add($fixture);
164+
165+
$this->assertSame($expected, $collection->getArrayCopy());
166+
}
167+
147168
/**
148169
* @covers Barryvdh\Reflection\DocBlock\Type\Collection::add
149170
*
@@ -267,4 +288,22 @@ public function provideTypesToExpandWithPropertyOrMethod($method)
267288
),
268289
);
269290
}
291+
292+
/**
293+
* Returns the types and their expected values to test the retrieval of
294+
* types including generics.
295+
*
296+
* @param string $method Name of the method consuming this data provider.
297+
* @param string $namespace Name of the namespace to user as basis.
298+
*
299+
* @return string[]
300+
*/
301+
public function provideTypesToExpandWithGenerics($method, $namespace = '\My\Space\\')
302+
{
303+
return array(
304+
array('TValue', array('TValue')),
305+
array('TValue[]', array('TValue[]')),
306+
array('TValue|DocBlock', array('TValue', $namespace . 'DocBlock')),
307+
);
308+
}
270309
}

tests/Barryvdh/Reflection/DocBlockTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,4 +336,22 @@ public function testGetTagsByNameMultipleMatch()
336336
$this->assertCount(1, $object->getTagsByName('return'));
337337
$this->assertCount(2, $object->getTagsByName('param'));
338338
}
339+
340+
/**
341+
* @covers \Barryvdh\Reflection\DocBlock::parseTags
342+
*
343+
* @return void
344+
*/
345+
public function testGenericsAreParsed()
346+
{
347+
$fixture = <<<DOCBLOCK
348+
/**
349+
* @template TValue
350+
* @param TValue
351+
* @return TValue
352+
*/
353+
DOCBLOCK;
354+
$object = new DocBlock($fixture);
355+
$this->assertSame(array('TValue'), $object->getGenerics());
356+
}
339357
}

0 commit comments

Comments
 (0)