Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Make constructor argument override the property docblock in PhpDocExtractor#30056

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

@karser
Copy link
Contributor

QA
Branch?3.4 up to 4.2
Bug fix?yes
New feature?no
BC breaks?hopefully no
Deprecations?no
Tests pass?yes
Fixed tickets#30053
LicenseMIT

The original ticket is#30053
In short, when using PhpDocExtractor, it ignores the constructor argument type, althoughargument types from constructor are the only types that are valid for the class instantiation.
This PR adds the constructor phpdoc support to PhpDocExtractor.

if (!$reflectionConstructor) {
returnnull;
}
if (!preg_match('/\@param.+?\$'.$property.'/',$reflectionConstructor->getDocComment(),$matches)) {
Copy link
Member

Choose a reason for hiding this comment

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

Can't we delegate the extraction of the parameter name tophpdocumentor/reflection-docblock? It would make the code more solid.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Done. Now I parse the phpdoc params using reflection-docblock, then filter docblock.tags so that only the requested property param is kept and then recreate the docblock object. The code became more verbose though.

karser added a commit to karser/symfony that referenced this pull requestFeb 5, 2019
@xabbuh
Copy link
Member

Will this also solve the reported case where the constructor has real type hints instead of a docblock? If so, we should also add a test for that case.

@karser
Copy link
ContributorAuthor

karser commentedFeb 5, 2019
edited
Loading

@xabbuh Nope, because PhpDocExtractor has higher priority than ReflectionExtractor. So if the constructor argument is not phpdoc-annotated, it'll return the property type.
ReflectionExtractor will get control only in case if both constructor argument and the property are not phpdoc-annotated.

@xabbuh
Copy link
Member

But how will this solve the linked issue then which is about a constructor not having a docblock. If I got you right, theReflectionExtractor will not do anything in that case.

@dunglas
Copy link
Member

The same kind of patch must be added to ReflectionExtractor.

@karser
Copy link
ContributorAuthor

Yep, adding phpdoc to the constructor would solve the linked issue.

@xabbuh How do you imagine this issue should be solved properly? Should we first check constructors for both PhpDocExtractor and ReflectionExtractor, and only after that properties?

@xabbuh
Copy link
Member

IMO we should only evaluate the property docblock (and in future PHP versions its type) if we were not able to infer the type from the constructor. The constructor is the gatekeeper here and can convey different information than the property if it performs some type conversion (like in the linked issue).

sfortop reacted with thumbs up emoji

karser added a commit to karser/symfony that referenced this pull requestFeb 6, 2019
…ctor and ReflectionExtractor. So that first attempt is to extract type from the constructor and otherwise from the propertysymfony#30056
@karser
Copy link
ContributorAuthor

@xabbuh Please take a look. I added ConstructorExtractor which has higher priority than PhpDocExtractor and ReflectionExtractor. So that first attempt is to extract the type from the constructor and otherwise from the property

karser added a commit to karser/symfony that referenced this pull requestFeb 6, 2019
karser added a commit to karser/symfony that referenced this pull requestFeb 6, 2019
karser added a commit to karser/symfony that referenced this pull requestFeb 6, 2019
@karser
Copy link
ContributorAuthor

karser commentedFeb 6, 2019
edited
Loading

Travis passes on php5 but gets an error on 7.2 / 7.3:Class 'Symfony\Component\PropertyInfo\Extractor\ConstructorExtractor' not found. It happens only for functional tests:

1) Symfony\Bundle\FrameworkBundle\Tests\Functional\PropertyInfoTest::testPhpDocPriorityError: Class 'Symfony\Component\PropertyInfo\Extractor\ConstructorExtractor' not found...7) Symfony\Bundle\FrameworkBundle\Tests\Functional\SerializerTest::testDeserializeArrayOfObjectError: Class 'Symfony\Component\PropertyInfo\Extractor\ConstructorExtractor' not found

I tried php 7.2 / 7.3 locally but I'm not able to reproduce this issue. Maybe autoloading / bytecode cache issue, or something else?

@karser
Copy link
ContributorAuthor

Thanks@xabbuh this fixes tests for php 7.3 but the error is still there for 7.2.
Still not fully following why this error happening and why it uses composer.json dependencies instead of the current symfony revision.

@nicolas-grekas
Copy link
Member

could you please squash all commits in one?

Copy link
Member

@nicolas-grekasnicolas-grekas left a comment

Choose a reason for hiding this comment

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

That's a lot of new public API for a bug fix, isn't this a new feature really?
How does that play with#25605?

@xabbuh
Copy link
Member

I wonder if we really need all the new classes (I haven't had time to read the code yet). But shouldn't the existing extractors take into account the constructor by default if the property they analyse is private?

@karser
Copy link
ContributorAuthor

karser commentedFeb 7, 2019
edited
Loading

That's a lot of new public API for a bug fix, isn't this a new feature really?

Does it mean it should be targeted to master?

How does that play with#25605?

@nicolas-grekas Unfortunately, I haven't seen this code because I was working in 3.4 branch, but it's different:

  1. It only fallbacks to constructor extraction (if getter/setter don't have types)
  2. It doesn't solve this issue ([AbstractObjectNormalizer][PropertyInfo] AbstractObjectNormalizer/PropertyInfoExtractor does not respect constructor type hinting. #30053) because if property is phpdoc-annotated,PhpDocExtractor will return non-null result and it will not even reachReflectionExtractor. Please see below my explanation.

@xabbuh Let's review it once again:
WhenPropertyInfoExtractor::getTypes is called, it tries to infer the type using one of the extractors in this order:[PhpDocExtractor::getTypes, ReflectionExtractor::getTypes].

Originally I modifiedPhpDocExtractor::getTypes so that it tries to extract the argument DocBlock from the constructor first and otherwise, fallbacks to the property one. It didn't solve the issue though (@xabbuh hasnoticed that) because it never calledReflectionExtractor::getTypes since the property was phpdoc annotated.

That's why I added a separate extractor -ConstructorExtractor which is called first (-999) and it attempts to extract the type from constructor only, either from PhpDoc or using reflection.
I addedgetTypesFromConstructor toPhpDocExtractor andReflectionExtractor - they implementConstructorArgumentTypeExtractorInterface interface.ConstructorExtractor aggregates those extractors using compiler pass.

So the flow of control looks like this:

PropertyInfoExtractor::getTypes:    - ConstructorExtractor::getTypes        - PhpDocExtractor::getTypesFromConstructor        - ReflectionExtractor::getTypesFromConstructor    - PhpDocExtractor::getTypes    - ReflectionExtractor::getTypes

@karserkarserforce-pushed thephpdocextractor-constructor-overrides-property-docblock branch from5d94e8d to6eade3bCompareFebruary 7, 2019 12:36
@karser
Copy link
ContributorAuthor

What type should be returned byPropertyInfoExtractor::getTypes for these examples?
Currently,ConstructorExtractor will be executed first and return string.

class DTO1 {    /** @var UuidInterface */    private $uuid;    public function __construct(string $uuid) {        $this->uuid = new Uuid($uuid);    }    /**     * @return UuidInterface     */    public function getUuid()    {        return $this->uuid;    }}
class DTO2 {    /** @var UuidInterface */    public $uuid;    public function __construct(string $uuid) {        $this->uuid = new Uuid($uuid);    }}
rvanlaak reacted with eyes emoji

@nicolas-grekas
Copy link
Member

OK, no opinion on that, maybe@dunglas@lyrixx would have good advice.
How would this PR look like on 4.2? Can you have a look and maybe submit one?

@dunglas
Copy link
Member

I'm not sure this is solvable as is...

@lyrixx
Copy link
Member

Yes, We knew there was some limitations to this system :/ IMHO, we need typed property to really fix this issue

@fabpot
Copy link
Member

Looks like this is a new feature indeed (fixing a "know limitation").@dunglas@lyrixx Do you agree?

@lyrixx
Copy link
Member

@fabpot I agree this is a new feature, yes

@karser
Copy link
ContributorAuthor

FYI the same PR but targeted to 4.2#30128

@fabpot
Copy link
Member

Closing this one then.

@fabpotfabpot closed thisFeb 21, 2019
@karserkarser deleted the phpdocextractor-constructor-overrides-property-docblock branchFebruary 21, 2019 16:49
fabpot added a commit that referenced this pull requestAug 26, 2020
…riority than PhpDocExtractor and ReflectionExtractor (karser)This PR was merged into the 5.2-dev branch.Discussion----------[PropertyInfo] ConstructorExtractor which has higher priority than PhpDocExtractor and ReflectionExtractor| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | yes| New feature?  | yes| BC breaks?    | hopefully no| Deprecations? | no| Tests pass?   | yes| Fixed tickets |#30053| License       | MITSupersedes#30056#30128In short, when using PhpDocExtractor, it ignores the constructor argument type, although `argument types from the constructor are the only types that are valid for the class instantiation`.This PR adds a separate extractor - `ConstructorExtractor` which is called first (-999) and it attempts to extract the type from constructor only, either from PhpDoc or using reflection.I added `getTypesFromConstructor` to `PhpDocExtractor` and `ReflectionExtractor` - they implement `ConstructorArgumentTypeExtractorInterface` interface. `ConstructorExtractor` aggregates those extractors using compiler pass.So the flow of control looks like this:```PropertyInfoExtractor::getTypes:    - ConstructorExtractor::getTypes        - PhpDocExtractor::getTypesFromConstructor        - ReflectionExtractor::getTypesFromConstructor    - PhpDocExtractor::getTypes    - ReflectionExtractor::getTypes```Commits-------5049e25 Added ConstructorExtractor which has higher priority than PhpDocExtractor and ReflectionExtractor
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@nicolas-grekasnicolas-grekasnicolas-grekas left review comments

@dunglasdunglasdunglas approved these changes

Assignees

No one assigned

Projects

None yet

Milestone

3.4

Development

Successfully merging this pull request may close these issues.

7 participants

@karser@xabbuh@dunglas@nicolas-grekas@lyrixx@fabpot@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp