[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. 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.
This commit is contained in:
parent
4cec0e1260
commit
38b369be3f
|
@ -104,7 +104,7 @@
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2",
|
"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"
|
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
|
||||||
},
|
},
|
||||||
"provide": {
|
"provide": {
|
||||||
|
|
|
@ -94,6 +94,9 @@ class PhpDocExtractorTest extends TestCase
|
||||||
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('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('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('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('donotexist', null, null, null),
|
||||||
array('staticGetter', null, null, null),
|
array('staticGetter', null, null, null),
|
||||||
array('staticSetter', null, null, null),
|
array('staticSetter', null, null, null),
|
||||||
|
@ -130,6 +133,9 @@ class PhpDocExtractorTest extends TestCase
|
||||||
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('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('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('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('donotexist', null, null, null),
|
||||||
array('staticGetter', null, null, null),
|
array('staticGetter', null, null, null),
|
||||||
array('staticSetter', null, null, null),
|
array('staticSetter', null, null, null),
|
||||||
|
@ -165,6 +171,9 @@ class PhpDocExtractorTest extends TestCase
|
||||||
array('e', null, null, null),
|
array('e', null, null, null),
|
||||||
array('f', null, null, null),
|
array('f', null, null, null),
|
||||||
array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', 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('donotexist', null, null, null),
|
||||||
array('staticGetter', null, null, null),
|
array('staticGetter', null, null, null),
|
||||||
array('staticSetter', null, null, null),
|
array('staticSetter', null, null, null),
|
||||||
|
|
|
@ -41,6 +41,9 @@ class ReflectionExtractorTest extends TestCase
|
||||||
'B',
|
'B',
|
||||||
'Guid',
|
'Guid',
|
||||||
'g',
|
'g',
|
||||||
|
'h',
|
||||||
|
'i',
|
||||||
|
'j',
|
||||||
'emptyVar',
|
'emptyVar',
|
||||||
'foo',
|
'foo',
|
||||||
'foo2',
|
'foo2',
|
||||||
|
@ -77,6 +80,9 @@ class ReflectionExtractorTest extends TestCase
|
||||||
'B',
|
'B',
|
||||||
'Guid',
|
'Guid',
|
||||||
'g',
|
'g',
|
||||||
|
'h',
|
||||||
|
'i',
|
||||||
|
'j',
|
||||||
'emptyVar',
|
'emptyVar',
|
||||||
'foo',
|
'foo',
|
||||||
'foo2',
|
'foo2',
|
||||||
|
@ -105,6 +111,9 @@ class ReflectionExtractorTest extends TestCase
|
||||||
'B',
|
'B',
|
||||||
'Guid',
|
'Guid',
|
||||||
'g',
|
'g',
|
||||||
|
'h',
|
||||||
|
'i',
|
||||||
|
'j',
|
||||||
'emptyVar',
|
'emptyVar',
|
||||||
'foo',
|
'foo',
|
||||||
'foo2',
|
'foo2',
|
||||||
|
|
|
@ -68,6 +68,21 @@ class Dummy extends ParentDummy
|
||||||
*/
|
*/
|
||||||
public $g;
|
public $g;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ?string
|
||||||
|
*/
|
||||||
|
public $h;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ?string|int
|
||||||
|
*/
|
||||||
|
public $i;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ?\DateTime
|
||||||
|
*/
|
||||||
|
public $j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This should not be removed.
|
* This should not be removed.
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Symfony\Component\PropertyInfo\Util;
|
||||||
use phpDocumentor\Reflection\Type as DocType;
|
use phpDocumentor\Reflection\Type as DocType;
|
||||||
use phpDocumentor\Reflection\Types\Compound;
|
use phpDocumentor\Reflection\Types\Compound;
|
||||||
use phpDocumentor\Reflection\Types\Null_;
|
use phpDocumentor\Reflection\Types\Null_;
|
||||||
|
use phpDocumentor\Reflection\Types\Nullable;
|
||||||
use Symfony\Component\PropertyInfo\Type;
|
use Symfony\Component\PropertyInfo\Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,13 +28,18 @@ final class PhpDocTypeHelper
|
||||||
/**
|
/**
|
||||||
* Creates a {@see Type} from a PHPDoc type.
|
* Creates a {@see Type} from a PHPDoc type.
|
||||||
*
|
*
|
||||||
* @return Type
|
* @return Type[]
|
||||||
*/
|
*/
|
||||||
public function getTypes(DocType $varType)
|
public function getTypes(DocType $varType)
|
||||||
{
|
{
|
||||||
$types = array();
|
$types = array();
|
||||||
$nullable = false;
|
$nullable = false;
|
||||||
|
|
||||||
|
if ($varType instanceof Nullable) {
|
||||||
|
$nullable = true;
|
||||||
|
$varType = $varType->getActualType();
|
||||||
|
}
|
||||||
|
|
||||||
if (!$varType instanceof Compound) {
|
if (!$varType instanceof Compound) {
|
||||||
if ($varType instanceof Null_) {
|
if ($varType instanceof Null_) {
|
||||||
$nullable = true;
|
$nullable = true;
|
||||||
|
@ -54,10 +60,10 @@ final class PhpDocTypeHelper
|
||||||
|
|
||||||
// If null is present, all types are nullable
|
// If null is present, all types are nullable
|
||||||
$nullKey = array_search(Type::BUILTIN_TYPE_NULL, $varTypes);
|
$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
|
// 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]);
|
unset($varTypes[$nullKey]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2",
|
"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"
|
"symfony/dependency-injection": "<3.3"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
|
Reference in New Issue