Skip to content

Commit 719e816

Browse files
asgrimjaapio
authored andcommitted
Resolve nullable types using a Nullable type wrapper
1 parent 9cf5c16 commit 719e816

File tree

4 files changed

+147
-0
lines changed

4 files changed

+147
-0
lines changed

src/TypeResolver.php

+28
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use phpDocumentor\Reflection\Types\Compound;
1717
use phpDocumentor\Reflection\Types\Context;
1818
use phpDocumentor\Reflection\Types\Iterable_;
19+
use phpDocumentor\Reflection\Types\Nullable;
1920
use phpDocumentor\Reflection\Types\Object_;
2021

2122
final class TypeResolver
@@ -102,6 +103,8 @@ public function resolve($type, Context $context = null)
102103
}
103104

104105
switch (true) {
106+
case $this->isNullableType($type):
107+
return $this->resolveNullableType($type, $context);
105108
case $this->isKeyword($type):
106109
return $this->resolveKeyword($type);
107110
case ($this->isCompoundType($type)):
@@ -208,6 +211,18 @@ private function isCompoundType($type)
208211
return strpos($type, '|') !== false;
209212
}
210213

214+
/**
215+
* Test whether the given type is a nullable type (i.e. `?string`)
216+
*
217+
* @param string $type
218+
*
219+
* @return bool
220+
*/
221+
private function isNullableType($type)
222+
{
223+
return $type[0] === '?';
224+
}
225+
211226
/**
212227
* Resolves the given typed array string (i.e. `string[]`) into an Array object with the right types set.
213228
*
@@ -265,4 +280,17 @@ private function resolveCompoundType($type, Context $context)
265280

266281
return new Compound($types);
267282
}
283+
284+
/**
285+
* Resolve nullable types (i.e. `?string`) into a Nullable type wrapper
286+
*
287+
* @param string $type
288+
* @param Context $context
289+
*
290+
* @return Nullable
291+
*/
292+
private function resolveNullableType($type, Context $context)
293+
{
294+
return new Nullable($this->resolve(ltrim($type, '?'), $context));
295+
}
268296
}

src/Types/Nullable.php

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
/**
3+
* This file is part of phpDocumentor.
4+
*
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*
8+
* @copyright 2010-2017 Mike van Riel<[email protected]>
9+
* @license http://www.opensource.org/licenses/mit-license.php MIT
10+
* @link http://phpdoc.org
11+
*/
12+
13+
namespace phpDocumentor\Reflection\Types;
14+
15+
use phpDocumentor\Reflection\Type;
16+
17+
/**
18+
* Value Object representing a nullable type. The real type is wrapped.
19+
*/
20+
final class Nullable implements Type
21+
{
22+
/**
23+
* @var Type
24+
*/
25+
private $realType;
26+
27+
/**
28+
* Initialises this nullable type using the real type embedded
29+
*
30+
* @param Type $realType
31+
*/
32+
public function __construct(Type $realType)
33+
{
34+
$this->realType = $realType;
35+
}
36+
37+
/**
38+
* Provide access to the actual type directly, if needed.
39+
*
40+
* @return Type
41+
*/
42+
public function getActualType()
43+
{
44+
return $this->realType;
45+
}
46+
47+
/**
48+
* Returns a rendered output of the Type as it would be used in a DocBlock.
49+
*
50+
* @return string
51+
*/
52+
public function __toString()
53+
{
54+
return '?' . $this->realType->__toString();
55+
}
56+
}

tests/unit/TypeResolverTest.php

+23
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
use phpDocumentor\Reflection\Types\Compound;
1818
use phpDocumentor\Reflection\Types\Context;
1919
use phpDocumentor\Reflection\Types\Iterable_;
20+
use phpDocumentor\Reflection\Types\Nullable;
2021
use phpDocumentor\Reflection\Types\Object_;
22+
use phpDocumentor\Reflection\Types\String_;
2123

2224
/**
2325
* @coversDefaultClass phpDocumentor\Reflection\TypeResolver
@@ -142,6 +144,27 @@ public function testResolvingTypedArrays()
142144
$this->assertInstanceOf('phpDocumentor\Reflection\Types\String_', $resolvedType->getValueType());
143145
}
144146

147+
/**
148+
* @covers ::__construct
149+
* @covers ::resolve
150+
* @covers ::<private>
151+
*
152+
* @uses \phpDocumentor\Reflection\Types\Context
153+
* @uses \phpDocumentor\Reflection\Types\Nullable
154+
* @uses \phpDocumentor\Reflection\Types\String_
155+
*/
156+
public function testResolvingNullableTypes()
157+
{
158+
$fixture = new TypeResolver();
159+
160+
/** @var Nullable $resolvedType */
161+
$resolvedType = $fixture->resolve('?string', new Context(''));
162+
163+
$this->assertInstanceOf(Nullable::class, $resolvedType);
164+
$this->assertInstanceOf(String_::class, $resolvedType->getActualType());
165+
$this->assertSame('?string', (string)$resolvedType);
166+
}
167+
145168
/**
146169
* @covers ::__construct
147170
* @covers ::resolve

tests/unit/Types/NullableTest.php

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
/**
3+
* This file is part of phpDocumentor.
4+
*
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*
8+
* @copyright 2010-2017 Mike van Riel<[email protected]>
9+
* @license http://www.opensource.org/licenses/mit-license.php MIT
10+
* @link http://phpdoc.org
11+
*/
12+
13+
namespace phpDocumentor\Reflection\Types;
14+
15+
/**
16+
* @coversDefaultClass \phpDocumentor\Reflection\Types\Nullable
17+
*/
18+
class NullableTest extends \PHPUnit_Framework_TestCase
19+
{
20+
/**
21+
* @covers ::__construct
22+
* @covers ::getActualType
23+
*/
24+
public function testNullableTypeWrapsCorrectly()
25+
{
26+
$realType = new String_();
27+
28+
$nullableString = new Nullable($realType);
29+
30+
$this->assertSame($realType, $nullableString->getActualType());
31+
}
32+
33+
/**
34+
* @covers ::__toString
35+
*/
36+
public function testNullableStringifyCorrectly()
37+
{
38+
$this->assertSame('?string', (string)(new Nullable(new String_())));
39+
}
40+
}

0 commit comments

Comments
 (0)