Skip to content

Commit

Permalink
bug #27618 [PropertyInfo] added handling of nullable types in PhpDoc …
Browse files Browse the repository at this point in the history
…(oxan)

This PR was merged into the 3.4 branch.

Discussion
----------

[PropertyInfo] added handling of nullable types in PhpDoc

While not specified in PSR-5, PhpDocumentor does support parsing nullable types in the PHP 7.1 syntax (i.e. `?string`), and returns those in a `Nullable` wrapper type. We currently don't handle this and neither throw an error, which results in all kind of weird breakage when this syntax is used (e.g. "class string|int not found").

Correctly parse this syntax into a nullable type.

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | n/a

Commits
-------

38b369b [PropertyInfo] added handling of nullable types in PhpDoc
  • Loading branch information
fabpot committed Jul 2, 2018
2 parents 52b91bb + 38b369b commit 1aae233
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 5 deletions.
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -104,7 +104,7 @@
},
"conflict": {
"phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2",
"phpdocumentor/type-resolver": "<0.2.1",
"phpdocumentor/type-resolver": "<0.3.0",
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
},
"provide": {
Expand Down
Expand Up @@ -94,6 +94,9 @@ public function typesProvider()
array('e', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))), null, null),
array('f', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime'))), null, null),
array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', null),
array('h', array(new Type(Type::BUILTIN_TYPE_STRING, true)), null, null),
array('i', array(new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)), null, null),
array('j', array(new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTime')), null, null),
array('donotexist', null, null, null),
array('staticGetter', null, null, null),
array('staticSetter', null, null, null),
Expand Down Expand Up @@ -130,6 +133,9 @@ public function typesWithCustomPrefixesProvider()
array('e', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))), null, null),
array('f', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime'))), null, null),
array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', null),
array('h', array(new Type(Type::BUILTIN_TYPE_STRING, true)), null, null),
array('i', array(new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)), null, null),
array('j', array(new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTime')), null, null),
array('donotexist', null, null, null),
array('staticGetter', null, null, null),
array('staticSetter', null, null, null),
Expand Down Expand Up @@ -165,6 +171,9 @@ public function typesWithNoPrefixesProvider()
array('e', null, null, null),
array('f', null, null, null),
array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', null),
array('h', array(new Type(Type::BUILTIN_TYPE_STRING, true)), null, null),
array('i', array(new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)), null, null),
array('j', array(new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTime')), null, null),
array('donotexist', null, null, null),
array('staticGetter', null, null, null),
array('staticSetter', null, null, null),
Expand Down
Expand Up @@ -41,6 +41,9 @@ public function testGetProperties()
'B',
'Guid',
'g',
'h',
'i',
'j',
'emptyVar',
'foo',
'foo2',
Expand Down Expand Up @@ -77,6 +80,9 @@ public function testGetPropertiesWithCustomPrefixes()
'B',
'Guid',
'g',
'h',
'i',
'j',
'emptyVar',
'foo',
'foo2',
Expand Down Expand Up @@ -105,6 +111,9 @@ public function testGetPropertiesWithNoPrefixes()
'B',
'Guid',
'g',
'h',
'i',
'j',
'emptyVar',
'foo',
'foo2',
Expand Down
15 changes: 15 additions & 0 deletions src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php
Expand Up @@ -68,6 +68,21 @@ class Dummy extends ParentDummy
*/
public $g;

/**
* @var ?string
*/
public $h;

/**
* @var ?string|int
*/
public $i;

/**
* @var ?\DateTime
*/
public $j;

/**
* This should not be removed.
*
Expand Down
12 changes: 9 additions & 3 deletions src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php
Expand Up @@ -14,6 +14,7 @@
use phpDocumentor\Reflection\Type as DocType;
use phpDocumentor\Reflection\Types\Compound;
use phpDocumentor\Reflection\Types\Null_;
use phpDocumentor\Reflection\Types\Nullable;
use Symfony\Component\PropertyInfo\Type;

/**
Expand All @@ -27,13 +28,18 @@ final class PhpDocTypeHelper
/**
* Creates a {@see Type} from a PHPDoc type.
*
* @return Type
* @return Type[]
*/
public function getTypes(DocType $varType)
{
$types = array();
$nullable = false;

if ($varType instanceof Nullable) {
$nullable = true;
$varType = $varType->getActualType();
}

if (!$varType instanceof Compound) {
if ($varType instanceof Null_) {
$nullable = true;
Expand All @@ -54,10 +60,10 @@ public function getTypes(DocType $varType)

// If null is present, all types are nullable
$nullKey = array_search(Type::BUILTIN_TYPE_NULL, $varTypes);
$nullable = false !== $nullKey;
$nullable = $nullable || false !== $nullKey;

// Remove the null type from the type if other types are defined
if ($nullable && count($varTypes) > 1) {
if ($nullable && false !== $nullKey && count($varTypes) > 1) {
unset($varTypes[$nullKey]);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/PropertyInfo/composer.json
Expand Up @@ -35,7 +35,7 @@
},
"conflict": {
"phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2",
"phpdocumentor/type-resolver": "<0.2.1",
"phpdocumentor/type-resolver": "<0.3.0",
"symfony/dependency-injection": "<3.3"
},
"suggest": {
Expand Down

0 comments on commit 1aae233

Please sign in to comment.