Skip to content

Commit 699b11e

Browse files
authored
Merge pull request #253 from voku/fix_issue_251
Param: fix phpdoc with reference hint
2 parents f3ab307 + 3d38a9c commit 699b11e

File tree

2 files changed

+127
-9
lines changed

2 files changed

+127
-9
lines changed

src/DocBlock/Tags/Param.php

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,22 @@ final class Param extends TagWithType implements Factory\StaticMethod
3838
/** @var bool determines whether this is a variadic argument */
3939
private $isVariadic;
4040

41+
/** @var bool determines whether this is passed by reference */
42+
private $isReference;
43+
4144
public function __construct(
4245
?string $variableName,
4346
?Type $type = null,
4447
bool $isVariadic = false,
45-
?Description $description = null
48+
?Description $description = null,
49+
bool $isReference = false
4650
) {
4751
$this->name = 'param';
4852
$this->variableName = $variableName;
4953
$this->type = $type;
5054
$this->isVariadic = $isVariadic;
5155
$this->description = $description;
56+
$this->isReference = $isReference;
5257
}
5358

5459
public static function create(
@@ -67,6 +72,7 @@ public static function create(
6772
$parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
6873
$variableName = '';
6974
$isVariadic = false;
75+
$isReference = false;
7076

7177
// if the first item that is encountered is not a variable; it is a type
7278
if ($firstPart && $firstPart[0] !== '$') {
@@ -76,26 +82,42 @@ public static function create(
7682
array_unshift($parts, $firstPart);
7783
}
7884

79-
// if the next item starts with a $ or ...$ it must be the variable name
80-
if (isset($parts[0]) && (strpos($parts[0], '$') === 0 || strpos($parts[0], '...$') === 0)) {
85+
// if the next item starts with a $ or ...$ or &$ or &...$ it must be the variable name
86+
if (isset($parts[0])
87+
&&
88+
(
89+
strpos($parts[0], '$') === 0
90+
||
91+
strpos($parts[0], '...$') === 0
92+
||
93+
strpos($parts[0], '&$') === 0
94+
||
95+
strpos($parts[0], '&...$') === 0
96+
)
97+
) {
8198
$variableName = array_shift($parts);
8299
array_shift($parts);
83100

84101
Assert::notNull($variableName);
85102

86-
if (strpos($variableName, '...') === 0) {
87-
$isVariadic = true;
88-
$variableName = substr($variableName, 3);
89-
}
90-
91103
if (strpos($variableName, '$') === 0) {
92104
$variableName = substr($variableName, 1);
105+
} elseif (strpos($variableName, '&$') === 0) {
106+
$isReference = true;
107+
$variableName = substr($variableName, 2);
108+
} elseif (strpos($variableName, '...$') === 0) {
109+
$isVariadic = true;
110+
$variableName = substr($variableName, 4);
111+
} elseif (strpos($variableName, '&...$') === 0) {
112+
$isVariadic = true;
113+
$isReference = true;
114+
$variableName = substr($variableName, 5);
93115
}
94116
}
95117

96118
$description = $descriptionFactory->create(implode('', $parts), $context);
97119

98-
return new static($variableName, $type, $isVariadic, $description);
120+
return new static($variableName, $type, $isVariadic, $description, $isReference);
99121
}
100122

101123
/**
@@ -114,12 +136,21 @@ public function isVariadic() : bool
114136
return $this->isVariadic;
115137
}
116138

139+
/**
140+
* Returns whether this tag is passed by reference.
141+
*/
142+
public function isReference() : bool
143+
{
144+
return $this->isReference;
145+
}
146+
117147
/**
118148
* Returns a string representation for this tag.
119149
*/
120150
public function __toString() : string
121151
{
122152
return ($this->type ? $this->type . ' ' : '')
153+
. ($this->isReference() ? '&' : '')
123154
. ($this->isVariadic() ? '...' : '')
124155
. ($this->variableName !== null ? '$' . $this->variableName : '')
125156
. ($this->description ? ' ' . $this->description : '');

tests/unit/DocBlock/Tags/ParamTest.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,99 @@ public function testFactoryMethod() : void
174174
$description = new Description('My Description');
175175
$descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description);
176176

177+
$fixture = Param::create('string $myParameter My Description', $typeResolver, $descriptionFactory, $context);
178+
179+
$this->assertSame('string $myParameter My Description', (string) $fixture);
180+
$this->assertSame('myParameter', $fixture->getVariableName());
181+
$this->assertInstanceOf(String_::class, $fixture->getType());
182+
$this->assertFalse($fixture->isVariadic());
183+
$this->assertFalse($fixture->isReference());
184+
$this->assertSame($description, $fixture->getDescription());
185+
}
186+
187+
/**
188+
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Param::<public>
189+
* @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory
190+
* @uses \phpDocumentor\Reflection\DocBlock\Description
191+
* @uses \phpDocumentor\Reflection\Types\Context
192+
*
193+
* @covers ::create
194+
*/
195+
public function testFactoryMethodWithVariadic() : void
196+
{
197+
$typeResolver = new TypeResolver();
198+
$descriptionFactory = m::mock(DescriptionFactory::class);
199+
$context = new Context('');
200+
201+
$description = new Description('My Description');
202+
$descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description);
203+
177204
$fixture = Param::create('string ...$myParameter My Description', $typeResolver, $descriptionFactory, $context);
178205

179206
$this->assertSame('string ...$myParameter My Description', (string) $fixture);
180207
$this->assertSame('myParameter', $fixture->getVariableName());
181208
$this->assertInstanceOf(String_::class, $fixture->getType());
182209
$this->assertTrue($fixture->isVariadic());
210+
$this->assertFalse($fixture->isReference());
211+
$this->assertSame($description, $fixture->getDescription());
212+
}
213+
214+
/**
215+
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Param::<public>
216+
* @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory
217+
* @uses \phpDocumentor\Reflection\DocBlock\Description
218+
* @uses \phpDocumentor\Reflection\Types\Context
219+
*
220+
* @covers ::create
221+
*/
222+
public function testFactoryMethodWithReference() : void
223+
{
224+
$typeResolver = new TypeResolver();
225+
$descriptionFactory = m::mock(DescriptionFactory::class);
226+
$context = new Context('');
227+
228+
$description = new Description('My Description');
229+
$descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description);
230+
231+
$fixture = Param::create('string &$myParameter My Description', $typeResolver, $descriptionFactory, $context);
232+
233+
$this->assertSame('string &$myParameter My Description', (string) $fixture);
234+
$this->assertSame('myParameter', $fixture->getVariableName());
235+
$this->assertInstanceOf(String_::class, $fixture->getType());
236+
$this->assertFalse($fixture->isVariadic());
237+
$this->assertTrue($fixture->isReference());
238+
$this->assertSame($description, $fixture->getDescription());
239+
}
240+
241+
/**
242+
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Param::<public>
243+
* @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory
244+
* @uses \phpDocumentor\Reflection\DocBlock\Description
245+
* @uses \phpDocumentor\Reflection\Types\Context
246+
*
247+
* @covers ::create
248+
*/
249+
public function testFactoryMethodWithVariadicReference() : void
250+
{
251+
$typeResolver = new TypeResolver();
252+
$descriptionFactory = m::mock(DescriptionFactory::class);
253+
$context = new Context('');
254+
255+
$description = new Description('My Description');
256+
$descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description);
257+
258+
$fixture = Param::create(
259+
'string &...$myParameter My Description',
260+
$typeResolver,
261+
$descriptionFactory,
262+
$context
263+
);
264+
265+
$this->assertSame('string &...$myParameter My Description', (string) $fixture);
266+
$this->assertSame('myParameter', $fixture->getVariableName());
267+
$this->assertInstanceOf(String_::class, $fixture->getType());
268+
$this->assertTrue($fixture->isVariadic());
269+
$this->assertTrue($fixture->isReference());
183270
$this->assertSame($description, $fixture->getDescription());
184271
}
185272

0 commit comments

Comments
 (0)