[PropertyInfo] Add support for typed properties (PHP 7.4)
This commit is contained in:
parent
dab6732f39
commit
7edfe4f741
@ -133,6 +133,18 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
|||||||
*/
|
*/
|
||||||
public function getTypes(string $class, string $property, array $context = []): ?array
|
public function getTypes(string $class, string $property, array $context = []): ?array
|
||||||
{
|
{
|
||||||
|
if (\PHP_VERSION_ID >= 70400) {
|
||||||
|
try {
|
||||||
|
$reflectionProperty = new \ReflectionProperty($class, $property);
|
||||||
|
$type = $reflectionProperty->getType();
|
||||||
|
if (null !== $type) {
|
||||||
|
return [$this->extractFromReflectionType($type, $reflectionProperty->getDeclaringClass())];
|
||||||
|
}
|
||||||
|
} catch (\ReflectionException $e) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($fromMutator = $this->extractFromMutator($class, $property)) {
|
if ($fromMutator = $this->extractFromMutator($class, $property)) {
|
||||||
return $fromMutator;
|
return $fromMutator;
|
||||||
}
|
}
|
||||||
@ -227,7 +239,7 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
|||||||
if (!$reflectionType = $reflectionParameter->getType()) {
|
if (!$reflectionType = $reflectionParameter->getType()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$type = $this->extractFromReflectionType($reflectionType, $reflectionMethod);
|
$type = $this->extractFromReflectionType($reflectionType, $reflectionMethod->getDeclaringClass());
|
||||||
|
|
||||||
if (\in_array($prefix, $this->arrayMutatorPrefixes)) {
|
if (\in_array($prefix, $this->arrayMutatorPrefixes)) {
|
||||||
$type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type);
|
$type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type);
|
||||||
@ -249,7 +261,7 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($reflectionType = $reflectionMethod->getReturnType()) {
|
if ($reflectionType = $reflectionMethod->getReturnType()) {
|
||||||
return [$this->extractFromReflectionType($reflectionType, $reflectionMethod)];
|
return [$this->extractFromReflectionType($reflectionType, $reflectionMethod->getDeclaringClass())];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\in_array($prefix, ['is', 'can', 'has'])) {
|
if (\in_array($prefix, ['is', 'can', 'has'])) {
|
||||||
@ -284,7 +296,7 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
|||||||
}
|
}
|
||||||
$reflectionType = $parameter->getType();
|
$reflectionType = $parameter->getType();
|
||||||
|
|
||||||
return $reflectionType ? [$this->extractFromReflectionType($reflectionType, $constructor)] : null;
|
return $reflectionType ? [$this->extractFromReflectionType($reflectionType, $constructor->getDeclaringClass())] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($parentClass = $reflectionClass->getParentClass()) {
|
if ($parentClass = $reflectionClass->getParentClass()) {
|
||||||
@ -313,7 +325,7 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
|||||||
return [new Type(static::MAP_TYPES[$type] ?? $type)];
|
return [new Type(static::MAP_TYPES[$type] ?? $type)];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionMethod $reflectionMethod): Type
|
private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionClass $declaringClass): Type
|
||||||
{
|
{
|
||||||
$phpTypeOrClass = $reflectionType->getName();
|
$phpTypeOrClass = $reflectionType->getName();
|
||||||
$nullable = $reflectionType->allowsNull();
|
$nullable = $reflectionType->allowsNull();
|
||||||
@ -325,18 +337,18 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
|||||||
} elseif ($reflectionType->isBuiltin()) {
|
} elseif ($reflectionType->isBuiltin()) {
|
||||||
$type = new Type($phpTypeOrClass, $nullable);
|
$type = new Type($phpTypeOrClass, $nullable);
|
||||||
} else {
|
} else {
|
||||||
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod));
|
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $declaringClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $type;
|
return $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveTypeName(string $name, \ReflectionMethod $reflectionMethod): string
|
private function resolveTypeName(string $name, \ReflectionClass $declaringClass): string
|
||||||
{
|
{
|
||||||
if ('self' === $lcName = strtolower($name)) {
|
if ('self' === $lcName = strtolower($name)) {
|
||||||
return $reflectionMethod->getDeclaringClass()->name;
|
return $declaringClass->name;
|
||||||
}
|
}
|
||||||
if ('parent' === $lcName && $parent = $reflectionMethod->getDeclaringClass()->getParentClass()) {
|
if ('parent' === $lcName && $parent = $declaringClass->getParentClass()) {
|
||||||
return $parent->name;
|
return $parent->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
|
|||||||
use Symfony\Component\PropertyInfo\Tests\Fixtures\NotInstantiable;
|
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\Type;
|
use Symfony\Component\PropertyInfo\Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -365,4 +366,13 @@ class ReflectionExtractorTest extends TestCase
|
|||||||
[DefaultValue::class, 'foo', null],
|
[DefaultValue::class, 'foo', null],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires PHP 7.4
|
||||||
|
*/
|
||||||
|
public function testTypedProperties(): void
|
||||||
|
{
|
||||||
|
$this->assertEquals([new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)], $this->extractor->getTypes(Php74Dummy::class, 'dummy'));
|
||||||
|
$this->assertEquals([new Type(Type::BUILTIN_TYPE_BOOL, true)], $this->extractor->getTypes(Php74Dummy::class, 'nullableBoolProp'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||||
|
*/
|
||||||
|
class Php74Dummy
|
||||||
|
{
|
||||||
|
public Dummy $dummy;
|
||||||
|
private ?bool $nullableBoolProp;
|
||||||
|
}
|
Reference in New Issue
Block a user