fix resolving parent/self/static type annotations
This commit is contained in:
parent
08c789c97b
commit
e9f2ece991
@ -142,11 +142,31 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$parentClass = null;
|
||||||
$types = [];
|
$types = [];
|
||||||
/** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
|
/** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
|
||||||
foreach ($docBlock->getTagsByName($tag) as $tag) {
|
foreach ($docBlock->getTagsByName($tag) as $tag) {
|
||||||
if ($tag && !$tag instanceof InvalidTag && null !== $tag->getType()) {
|
if ($tag && !$tag instanceof InvalidTag && null !== $tag->getType()) {
|
||||||
$types = array_merge($types, $this->phpDocTypeHelper->getTypes($tag->getType()));
|
foreach ($this->phpDocTypeHelper->getTypes($tag->getType()) as $type) {
|
||||||
|
switch ($type->getClassName()) {
|
||||||
|
case 'self':
|
||||||
|
case 'static':
|
||||||
|
$resolvedClass = $class;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'parent':
|
||||||
|
if (false !== $resolvedClass = $parentClass ?? $parentClass = get_parent_class($class)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// no break
|
||||||
|
|
||||||
|
default:
|
||||||
|
$types[] = $type;
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $type->isNullable(), $resolvedClass, $type->isCollection(), $type->getCollectionKeyType(), $type->getCollectionValueType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ use phpDocumentor\Reflection\Types\Collection;
|
|||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
|
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
|
||||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
|
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
|
||||||
|
use Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy;
|
||||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsedInTrait;
|
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsedInTrait;
|
||||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsingTrait;
|
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsingTrait;
|
||||||
use Symfony\Component\PropertyInfo\Type;
|
use Symfony\Component\PropertyInfo\Type;
|
||||||
@ -120,6 +121,7 @@ class PhpDocExtractorTest extends TestCase
|
|||||||
['staticGetter', null, null, null],
|
['staticGetter', null, null, null],
|
||||||
['staticSetter', null, null, null],
|
['staticSetter', null, null, null],
|
||||||
['emptyVar', null, $this->isPhpDocumentorV5() ? 'This should not be removed.' : null, null],
|
['emptyVar', null, $this->isPhpDocumentorV5() ? 'This should not be removed.' : null, null],
|
||||||
|
['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)], null, null],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,6 +295,38 @@ class PhpDocExtractorTest extends TestCase
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider propertiesStaticTypeProvider
|
||||||
|
*/
|
||||||
|
public function testPropertiesStaticType(string $class, string $property, Type $type)
|
||||||
|
{
|
||||||
|
$this->assertEquals([$type], $this->extractor->getTypes($class, $property));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function propertiesStaticTypeProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[ParentDummy::class, 'propertyTypeStatic', new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)],
|
||||||
|
[Dummy::class, 'propertyTypeStatic', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider propertiesParentTypeProvider
|
||||||
|
*/
|
||||||
|
public function testPropertiesParentType(string $class, string $property, ?array $types)
|
||||||
|
{
|
||||||
|
$this->assertEquals($types, $this->extractor->getTypes($class, $property));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function propertiesParentTypeProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[ParentDummy::class, 'parentAnnotationNoParent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'parent')]],
|
||||||
|
[Dummy::class, 'parentAnnotation', [new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
protected function isPhpDocumentorV5()
|
protected function isPhpDocumentorV5()
|
||||||
{
|
{
|
||||||
if (class_exists(InvalidTag::class)) {
|
if (class_exists(InvalidTag::class)) {
|
||||||
|
@ -20,6 +20,8 @@ use Symfony\Component\PropertyInfo\Tests\Fixtures\NotInstantiable;
|
|||||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71Dummy;
|
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71Dummy;
|
||||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyExtended2;
|
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyExtended2;
|
||||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php74Dummy;
|
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php74Dummy;
|
||||||
|
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy;
|
||||||
|
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7ParentDummy;
|
||||||
use Symfony\Component\PropertyInfo\Type;
|
use Symfony\Component\PropertyInfo\Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,12 +59,15 @@ class ReflectionExtractorTest extends TestCase
|
|||||||
'iteratorCollection',
|
'iteratorCollection',
|
||||||
'iteratorCollectionWithKey',
|
'iteratorCollectionWithKey',
|
||||||
'nestedIterators',
|
'nestedIterators',
|
||||||
|
'parentAnnotation',
|
||||||
'foo',
|
'foo',
|
||||||
'foo2',
|
'foo2',
|
||||||
'foo3',
|
'foo3',
|
||||||
'foo4',
|
'foo4',
|
||||||
'foo5',
|
'foo5',
|
||||||
'files',
|
'files',
|
||||||
|
'propertyTypeStatic',
|
||||||
|
'parentAnnotationNoParent',
|
||||||
'a',
|
'a',
|
||||||
'DOB',
|
'DOB',
|
||||||
'Id',
|
'Id',
|
||||||
@ -105,12 +110,15 @@ class ReflectionExtractorTest extends TestCase
|
|||||||
'iteratorCollection',
|
'iteratorCollection',
|
||||||
'iteratorCollectionWithKey',
|
'iteratorCollectionWithKey',
|
||||||
'nestedIterators',
|
'nestedIterators',
|
||||||
|
'parentAnnotation',
|
||||||
'foo',
|
'foo',
|
||||||
'foo2',
|
'foo2',
|
||||||
'foo3',
|
'foo3',
|
||||||
'foo4',
|
'foo4',
|
||||||
'foo5',
|
'foo5',
|
||||||
'files',
|
'files',
|
||||||
|
'propertyTypeStatic',
|
||||||
|
'parentAnnotationNoParent',
|
||||||
'date',
|
'date',
|
||||||
'c',
|
'c',
|
||||||
'd',
|
'd',
|
||||||
@ -143,12 +151,15 @@ class ReflectionExtractorTest extends TestCase
|
|||||||
'iteratorCollection',
|
'iteratorCollection',
|
||||||
'iteratorCollectionWithKey',
|
'iteratorCollectionWithKey',
|
||||||
'nestedIterators',
|
'nestedIterators',
|
||||||
|
'parentAnnotation',
|
||||||
'foo',
|
'foo',
|
||||||
'foo2',
|
'foo2',
|
||||||
'foo3',
|
'foo3',
|
||||||
'foo4',
|
'foo4',
|
||||||
'foo5',
|
'foo5',
|
||||||
'files',
|
'files',
|
||||||
|
'propertyTypeStatic',
|
||||||
|
'parentAnnotationNoParent',
|
||||||
],
|
],
|
||||||
$noPrefixExtractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy')
|
$noPrefixExtractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy')
|
||||||
);
|
);
|
||||||
@ -184,20 +195,21 @@ class ReflectionExtractorTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @dataProvider php7TypesProvider
|
* @dataProvider php7TypesProvider
|
||||||
*/
|
*/
|
||||||
public function testExtractPhp7Type($property, array $type = null)
|
public function testExtractPhp7Type(string $class, string $property, array $type = null)
|
||||||
{
|
{
|
||||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy', $property, []));
|
$this->assertEquals($type, $this->extractor->getTypes($class, $property, []));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function php7TypesProvider()
|
public function php7TypesProvider()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
['foo', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]],
|
[Php7Dummy::class, 'foo', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]],
|
||||||
['bar', [new Type(Type::BUILTIN_TYPE_INT)]],
|
[Php7Dummy::class, 'bar', [new Type(Type::BUILTIN_TYPE_INT)]],
|
||||||
['baz', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]],
|
[Php7Dummy::class, 'baz', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]],
|
||||||
['buz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy')]],
|
[Php7Dummy::class, 'buz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy')]],
|
||||||
['biz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'stdClass')]],
|
[Php7Dummy::class, 'biz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Php7ParentDummy::class)]],
|
||||||
['donotexist', null],
|
[Php7Dummy::class, 'donotexist', null],
|
||||||
|
[Php7ParentDummy::class, 'parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, \stdClass::class)]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +130,11 @@ class Dummy extends ParentDummy
|
|||||||
*/
|
*/
|
||||||
public $nestedIterators;
|
public $nestedIterators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var parent
|
||||||
|
*/
|
||||||
|
public $parentAnnotation;
|
||||||
|
|
||||||
public static function getStatic()
|
public static function getStatic()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,16 @@ class ParentDummy
|
|||||||
*/
|
*/
|
||||||
public $files;
|
public $files;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var static
|
||||||
|
*/
|
||||||
|
public $propertyTypeStatic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var parent
|
||||||
|
*/
|
||||||
|
public $parentAnnotationNoParent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool|null
|
* @return bool|null
|
||||||
*/
|
*/
|
||||||
|
@ -14,7 +14,7 @@ namespace Symfony\Component\PropertyInfo\Tests\Fixtures;
|
|||||||
/**
|
/**
|
||||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||||
*/
|
*/
|
||||||
class Php7Dummy extends \stdClass
|
class Php7Dummy extends Php7ParentDummy
|
||||||
{
|
{
|
||||||
public function getFoo(): array
|
public function getFoo(): array
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\PropertyInfo\Tests\Fixtures;
|
||||||
|
|
||||||
|
class Php7ParentDummy extends \stdClass
|
||||||
|
{
|
||||||
|
public function getParent(): parent
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -160,6 +160,10 @@ final class PhpDocTypeHelper
|
|||||||
return [$docType, null];
|
return [$docType, null];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (\in_array($docType, ['parent', 'self', 'static'], true)) {
|
||||||
|
return ['object', $docType];
|
||||||
|
}
|
||||||
|
|
||||||
return ['object', substr($docType, 1)];
|
return ['object', substr($docType, 1)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user