8000 [PropertyInfo] Extract property type from property declaration by tsantos84 · Pull Request #31798 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[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

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[PropertyInfo] Add self and parent type
  • Loading branch information
tsantos84 committed Jun 7, 2019
commit 72ee4012ef412f0d146e348831e17f91a833a5e3
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,8 @@ private function extractFromDeclaredType(string $class, string $property)
}

$reflectionType = $reflectionProperty->getType();
$type = $reflectionType->getName();

if ($reflectionType->isBuiltIn()) {
return [new Type(static::MAP_TYPES[$type] ?? $type, $reflectionType->allowsNull())];
}

return [new Type(Type::BUILTIN_TYPE_OBJECT, $reflectionType->allowsNull(), $type)];
return [$this->extractFromReflectionType($reflectionType, null, $reflectionProperty)];
}

/**
Expand All @@ -234,7 +229,7 @@ private function extractFromMutator(string $class, string $property): ?array
if (!$reflectionType = $reflectionParameter->getType()) {
return null;
}
$type = $this->extractFromReflectionType($reflectionType, $reflectionMethod);
$type = $this->extractFromReflectionType($reflectionType, $reflectionMethod, null);

if (\in_array($prefix, $this->arrayMutatorPrefixes)) {
$type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type);
Expand All @@ -256,7 +251,7 @@ private function extractFromAccessor(string $class, string $property): ?array
}

if ($reflectionType = $reflectionMethod->getReturnType()) {
return [$this->extractFromReflectionType($reflectionType, $reflectionMethod)];
return [$this->extractFromReflectionType($reflectionType, $reflectionMethod, null)];
}

if (\in_array($prefix, ['is', 'can', 'has'])) {
Expand Down Expand Up @@ -291,7 +286,7 @@ private function extractFromConstructor(string $class, string $property): ?array
}
$reflectionType = $parameter->getType();

return $reflectionType ? [$this->extractFromReflectionType($reflectionType, $constructor)] : null;
return $reflectionType ? [$this->extractFromReflectionType($reflectionType, $constructor, null)] : null;
}

if ($parentClass = $reflectionClass->getParentClass()) {
Expand Down Expand Up @@ -320,7 +315,7 @@ private function extractFromDefaultValue(string $class, string $property)
return [new Type(static::MAP_TYPES[$type] ?? $type)];
}

private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionMethod $reflectionMethod): Type
private function extractFromReflectionType(\ReflectionType $reflectionType, ?\ReflectionMethod $reflectionMethod, ?\ReflectionProperty $reflectionProperty): Type
{
$phpTypeOrClass = $reflectionType->getName();
$nullable = $reflectionType->allowsNull();
Expand All @@ -331,19 +326,27 @@ private function extractFromReflectionType(\ReflectionType $reflectionType, \Ref
$type = new Type(Type::BUILTIN_TYPE_NULL, $nullable);
} elseif ($reflectionType->isBuiltin()) {
$type = new Type($phpTypeOrClass, $nullable);
} elseif (null !== $reflectionMethod) {
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod, null));
} elseif (null !== $reflectionProperty) {
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, null, $reflectionProperty));
} else {
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod));
throw new \BadMethodCallException('You should provide method or property reflection');
}

return $type;
}

private function resolveTypeName(string $name, \ReflectionMethod $reflectionMethod): string
private function resolveTypeName(string $name, ?\ReflectionMethod $reflectionMethod, ?\ReflectionProperty $reflectionProperty): string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as we only need ->getDeclaringClass(), which is common on both class, I suggest using a single argument accepting \ReflectionMethod|\ReflectionProperty (and same in extractFromReflectionType). This will keep the code simpler

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better than contribute with something is learn something contributing.

Copy link
Contributor Author
@tsantos84 tsantos84 Jun 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this doesn't seems to be a valid syntax. Is your suggestion something like this?

private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionMethod|\ReflectionProperty $reflector): Type {...}

Or you are suggesting to not declare this argument with type:

/**
 * @param \ReflectionMethod|\ReflectionProperty $reflector
*/
private function extractFromReflectionType(\ReflectionType $reflectionType, object $reflector): Type {...}

Copy link
@mshavliuk mshavliuk Jun 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both \ReflectionMethod and \ReflectionProperty implements Reflector interface, so you can declare it like this:

/**
 * @param \ReflectionMethod|\ReflectionProperty $reflector
*/
private function extractFromReflectionType(\ReflectionType $reflectionType, \Reflector $reflector): Type {...}

Copy link
Contributor Author
@tsantos84 tsantos84 Jun 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, both implements \Reflector but \Reflector doesn't have the necessary getDeclaringClass() method. In this case, I don't think that we should use this interface as a typehint.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In any case It is far better than just object. For more specific typehint @param declaration will be enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As both extractFromReflectionType and resolveTypeName are private methods, I'm good to remove any typehint for this argument and declare its type on @param docblock. What do you think?

{
if (null === ($reflection = $reflectionMethod ?? $reflectionProperty)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calling the variable $reflector would be better, as that's the naming used by PHP for its interface implemented by all reflection classes (but it does not make sense to use it as typehint, as getDeclaringClass is not part of this interface as other reflection classes don't implement it)

throw new \BadMethodCallException('You should provide method or property reflection');
}

if ('self' === $lcName = strtolower($name)) {
return $reflectionMethod->getDeclaringClass()->name;
return $reflection->getDeclaringClass()->name;
}
if ('parent' === $lcName && $parent = $reflectionMethod->getDeclaringClass()->getParentClass()) {
if ('parent' === $lcName && $parent = $reflection->getDeclaringClass()->getParentClass()) {
return $parent->name;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Symfony\Component\PropertyInfo\Tests\Fixtures\DefaultValue;
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
use Symfony\Component\PropertyInfo\Tests\Fixtures\NotInstantiable;
use Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy;
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71Dummy;
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyExtended2;
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php74Dummy;
Expand Down Expand Up @@ -250,6 +251,8 @@ public function declaredTypeProvider()
['dummy', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)]],
['optionalDummy', [new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class)]],
['iterable', [new Type(Type::BUILTIN_TYPE_ITERABLE, false)]],
['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Php74Dummy::class)]],
['parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]],
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
*
* @author Tales Santos <tales.augusto.santos@gmail.com>
*/
class Php74Dummy
class Php74Dummy extends ParentDummy
{
public int $int;
public ?string $string;
public Dummy $dummy;
public parent $parent;
public self $self;
public ?Dummy $optionalDummy;
Copy link
@mshavliuk mshavliuk Jun 6, 2019

Choose a reason for hiding this comment

The 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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this test case should be removed because declaring callable for a property is not allowed. https://wiki.php.net/rfc/typed_properties_v2

public iterable $iterable;
}
0