-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[PropertyInfo] Extract property type from property declaration #31798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4baeb0c
e903eeb
e71852d
550c4d2
afaea21
d11d8f0
f2b5c1a
72ee401
2a273c1
4e5bfe1
2f8b2fe
7f1095d
92e8be6
d6c3e5a
bc8d70c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ matrix: | |
env: deps=high | ||
- php: 7.3 | ||
env: deps=low | ||
- php: 7.4snapshot | ||
|
||
fast_finish: true | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,6 +109,10 @@ public function getProperties($class, array $context = []) | |
*/ | ||
public function getTypes($class, $property, array $context = []) | ||
{ | ||
if ($fromDeclaredType = $this->extractFromDeclaredType($class, $property)) { | ||
return $fromDeclaredType; | ||
} | ||
|
||
if ($fromMutator = $this->extractFromMutator($class, $property)) { | ||
return $fromMutator; | ||
} | ||
|
@@ -185,6 +189,28 @@ public function isInitializable(string $class, string $property, array $context | |
return false; | ||
} | ||
|
||
private function extractFromDeclaredType(string $class, string $property) | ||
{ | ||
if (version_compare(\PHP_VERSION_ID, 70400, '<')) { | ||
return null; | ||
} | ||
|
||
try { | ||
$reflectionClass = new \ReflectionClass($class); | ||
$reflectionProperty = $reflectionClass->getProperty($property); | ||
} catch (\ReflectionException $e) { | ||
return null; | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To prevent test fails you can add following code here: if (!$reflectionClass->hasProperty($property)) {
return null;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or you can expand try-catch block for the whole function content (to prevent errors, which can happen while calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've used the same |
||
if (!$reflectionProperty->hasType()) { | ||
return null; | ||
} | ||
|
||
$reflectionType = $reflectionProperty->getType(); | ||
|
||
return [$this->extractFromReflectionType($reflectionType, $reflectionProperty)]; | ||
} | ||
|
||
/** | ||
* @return Type[]|null | ||
*/ | ||
|
@@ -287,7 +313,13 @@ private function extractFromDefaultValue(string $class, string $property) | |
return [new Type(static::MAP_TYPES[$type] ?? $type)]; | ||
} | ||
|
||
private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionMethod $reflectionMethod): Type | ||
/** | ||
* @param \ReflectionType $reflectionType | ||
* @param \ReflectionMethod|\ReflectionProperty $reflector | ||
* | ||
* @return Type | ||
*/ | ||
private function extractFromReflectionType(\ReflectionType $reflectionType, $reflector): Type | ||
{ | ||
$phpTypeOrClass = $reflectionType->getName(); | ||
$nullable = $reflectionType->allowsNull(); | ||
|
@@ -298,19 +330,37 @@ private function extractFromReflectionType(\ReflectionType $reflectionType, \Ref | |
$type = new Type(Type::BUILTIN_TYPE_NULL, $nullable); | ||
} elseif ($reflectionType->isBuiltin()) { | ||
$type = new Type($phpTypeOrClass, $nullable); | ||
} elseif ($reflector instanceof \ReflectionMethod || $reflector instanceof \ReflectionProperty) { | ||
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflector)); | ||
} else { | ||
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod)); | ||
throw new \InvalidArgumentException( | ||
'$reflector should be an instance of ReflectionMethod or ReflectionProperty, ' | ||
.(\is_object($reflector) ? \get_class($reflector) : \gettype($reflector)).' given' | ||
); | ||
} | ||
|
||
return $type; | ||
} | ||
|
||
private function resolveTypeName(string $name, \ReflectionMethod $reflectionMethod): string | ||
/** | ||
* @param string $name | ||
* @param \ReflectionMethod|\ReflectionProperty $reflector | ||
* | ||
* @return string | ||
*/ | ||
private function resolveTypeName(string $name, $reflector): string | ||
{ | ||
if (!($reflector instanceof \ReflectionMethod || $reflector instanceof \ReflectionProperty)) { | ||
throw new \InvalidArgumentException( | ||
'$reflector should be an instance of ReflectionMethod or ReflectionProperty, ' | ||
.(\is_object($reflector) ? \get_class($reflector) : \gettype($reflector)).' given' | ||
); | ||
} | ||
|
||
if ('self' === $lcName = strtolower($name)) { | ||
return $reflectionMethod->getDeclaringClass()->name; | ||
return $reflector->getDeclaringClass()->name; | ||
} | ||
if ('parent' === $lcName && $parent = $reflectionMethod->getDeclaringClass()->getParentClass()) { | ||
if ('parent' === $lcName && $parent = $reflector->getDeclaringClass()->getParentClass()) { | ||
return $parent->name; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?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 Php74Dummy | ||
* | ||
* @author Tales Santos <tales.augusto.santos@gmail.com> | ||
*/ | ||
class Php74Dummy extends ParentDummy | ||
{ | ||
public int $int; | ||
public ?string $string; | ||
public Dummy $dummy; | ||
public parent $parent; | ||
public self $self; | ||
public ?Dummy $optionalDummy; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like you forgot about "callable" property, which is mention in test There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, this test case should be removed because declaring |
||
public iterable $iterable; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change causing test fails:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can easily reproduce this tests by running this in
src/Symfony/Component/PropertyInfo
:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed