Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[PropertyInfo] Added support for extracting type from constructor #25605

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

Merged
merged 1 commit into from
Feb 19, 2018

Conversation

lyrixx
Copy link
Member

@lyrixx lyrixx commented Dec 26, 2017

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets -
License MIT
Doc PR -

private function extractFromConstructor(string $class, string $property): ?array
{
try {
$class = new \ReflectionClass($class);
Copy link
Member

Choose a reason for hiding this comment

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

Instead of this:

$class = new \ReflectionClass($class);
$constructor = $class->getConstructor();

maybe we can use this:

$constructor = (new \ReflectionClass($class))->getConstructor();

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed.

return null;
}

foreach ($constructor->getParameters() as $name => $parameter) {
Copy link
Member

@javiereguiluz javiereguiluz Dec 26, 2017

Choose a reason for hiding this comment

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

Is the $name of the foreach different than the $parameter->name used below or we can reuse it?

Copy link
Member Author

@lyrixx lyrixx Dec 26, 2017

Choose a reason for hiding this comment

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

$name === '$string' (note the leading $).

So I removed the $name assignment. Thanks

@lyrixx lyrixx force-pushed the property-info-constructor branch from 4bc0bdb to e1672aa Compare December 26, 2017 12:11
Copy link
Member

@javiereguiluz javiereguiluz left a comment

Choose a reason for hiding this comment

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

Thanks for this contribution!

return null;
}

if (!$constructor) {
Copy link
Member

Choose a reason for hiding this comment

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

Should we take parent classes into account too?

Copy link
Member

Choose a reason for hiding this comment

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

@lyrixx WDYT? How does phpstorm handle overridden constructors? It could help decide.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think we should take parents into account.
But I don't know how phpstorm handle that. I don't use it. You should know it ;)
I will check

Copy link
Member Author

Choose a reason for hiding this comment

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

Just checked, PHP storm is using parent constructor too. I will update the PR

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, it's already supported ;) I added a new test case to ensure it works as expected.

Copy link
Member

Choose a reason for hiding this comment

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

I was thinking about this situation:

class a
{
  public $foo;
  function __construct(string $foo)
  {
    $this->foo = $foo;
  }
}

class b extends a
{
  function __construct()
  {
    parent::__construct('hello');
  }
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah ok. I have added support for such case with a test case.

I guess the PR is now READY \o/

@nicolas-grekas nicolas-grekas added this to the 4.1 milestone Dec 27, 2017
@nicolas-grekas
Copy link
Member

@jvasseur please comment when adding a 👎 , we're all curious about all opinions to enlighten decisions.

@lyrixx lyrixx force-pushed the property-info-constructor branch from e1672aa to 4dcdbb2 Compare December 27, 2017 11:23
@jvasseur
Copy link
Contributor

Sorry. I'm mostly against this change since having a constructor argument with the same name as a property doesn't necessarily mean it will be saved inside that property. This feels less reliable that using the types from getter/setters and I don't fell fine having this guess inside the same extractor. Maybe putting it inside a separate extractor that could be assigned a to a lower priority.

@lyrixx
Copy link
Member Author

lyrixx commented Dec 27, 2017

@jvasseur I agree with you, and it already have a lower priority. So there are no issue ;)

@jvasseur
Copy link
Contributor

@lyrixx it has a lower priority inside the reflection extractor, but it still is the same extractor meaning you can't run another extractor between the accessor and the constructor guess.

@lyrixx
Copy link
Member Author

lyrixx commented Dec 27, 2017

You are right, indeed ;)

But I'm not sure it worth a dedicated extractor. Do you really think it worth this complexity?

@jvasseur
Copy link
Contributor

Not necessary I am just thinking this is something that could append but I don't have a real case were it would append.

@lyrixx lyrixx force-pushed the property-info-constructor branch from 4dcdbb2 to 7ba526b Compare December 28, 2017 15:02
@lyrixx
Copy link
Member Author

lyrixx commented Dec 28, 2017

👍

return array($this->extractFromReflectionType($parameter->getType()));
}

if ($reflectionClass->getParentClass()) {
Copy link
Member

Choose a reason for hiding this comment

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

$parent = to prevent creating two instances of ReflectionClass

Copy link
Member Author

Choose a reason for hiding this comment

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

done.

@lyrixx lyrixx force-pushed the property-info-constructor branch from 7ba526b to 2b1c2b3 Compare December 28, 2017 16:45
@@ -100,12 +100,16 @@ public function getProperties($class, array $context = array())
*/
public function getTypes($class, $property, array $context = array())
{
if ($fromMutator = $this->extractFromMutator($class, $property)) {
Copy link
Member

Choose a reason for hiding this comment

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

Is is really necessary to change this (it will make it harder to merge bug fixes later)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope, it was just done in order to optimize the code. I can revert it if you want

Copy link
Member

Choose a reason for hiding this comment

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

let's revert yes please :)

Copy link
Member Author

Choose a reason for hiding this comment

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

It's reverted

@dunglas
Copy link
Member

dunglas commented Dec 29, 2017

Shouldn't you also update the getProperties() method to add properties accessible trough the constructor to the list (write only).

Also, if we start supporting this, it would be nice to also support constructors in the PhpDocExtractor (it is more powerful and precise than the ReflectionExtractor).

@dunglas
Copy link
Member

dunglas commented Dec 29, 2017

Regarding @jvasseur's comment, maybe can we add a flag in the constructor to disable this feature?

@javiereguiluz
Copy link
Member

@dunglas please, let's not complicate things with a constructor flag. I'd like to understand better the problem explained by @jvasseur. Imagine that this is your code:

private /* bool */ $stock;

public function __construct(int $stock)
{
    $this->stock = $stock > 10;
}

The $stock property is private and it doesn't have any getter/setter. The type of the property would be guessed as int instead of bool. Questions: 1) Is this code realistic or an academic example that nobody would use in practice? 2) Which parts of Symfony would stop working because of this wrong guess? Thanks!

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

apparently this needs to be opt-in, isn't it?

@lyrixx
Copy link
Member Author

lyrixx commented Jan 12, 2018

apparently this needs to be opt-in, isn't it?

What do you mean ?

*
* @return Type[]|null
*/
private function extractFromConstructor(string $class, string $property): ?array
Copy link
Contributor

Choose a reason for hiding this comment

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

why ?array, and not ?Type ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because it returns an array a not a Type

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

@dunglas, please advise: as is, context option, or constructor flag?

@@ -100,12 +100,16 @@ public function getProperties($class, array $context = array())
*/
public function getTypes($class, $property, array $context = array())
{
if ($fromMutator = $this->extractFromMutator($class, $property)) {
Copy link
Member

Choose a reason for hiding this comment

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

let's revert yes please :)

@lyrixx lyrixx force-pushed the property-info-constructor branch from 2b1c2b3 to 264f58f Compare February 9, 2018 17:29
@dunglas
Copy link
Member

dunglas commented Feb 9, 2018

Both would be great (we already do that in the serializer component), the constructor flag allowing to set the default value, and the context option taking priority.
If we must choose, I tend to prefer the constructor flag.

@lyrixx lyrixx force-pushed the property-info-constructor branch from 264f58f to c5b3f45 Compare February 16, 2018 15:04
@lyrixx
Copy link
Member Author

lyrixx commented Feb 16, 2018

This PR is now ready

@@ -107,6 +109,13 @@ public function getTypes($class, $property, array $context = array())
if ($fromAccessor = $this->extractFromAccessor($class, $property)) {
return $fromAccessor;
}

if (
Copy link
Member

Choose a reason for hiding this comment

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

$context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's not the same, because if one want to disable it, with your code it will fallback on the enableConstructorExtraction value.

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right. I fixed it.

@dunglas
Copy link
Member

dunglas commented Feb 19, 2018

Thanks @lyrixx.

@dunglas dunglas merged commit adcb25e into symfony:master Feb 19, 2018
dunglas added a commit that referenced this pull request Feb 19, 2018
…constructor (lyrixx)

This PR was merged into the 4.1-dev branch.

Discussion
----------

[PropertyInfo] Added support for extracting type from constructor

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

Commits
-------

adcb25e [PropertyInfo] Added support for extracting type from constructor
@lyrixx lyrixx deleted the property-info-constructor branch February 20, 2018 10:22
@fabpot fabpot mentioned this pull request May 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants