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

Skip to content

Infer return type information with Psalter#8150

Merged
beberlei merged 1 commit into
doctrine:2.7from
greg0ire:psalter
Jul 5, 2020
Merged

Infer return type information with Psalter#8150
beberlei merged 1 commit into
doctrine:2.7from
greg0ire:psalter

Conversation

@greg0ire
Copy link
Copy Markdown
Member

@greg0ire greg0ire commented May 17, 2020

These changes are a subset of changes done with vendor/bin/psalm --alter --issues=LessSpecificReturnType --allow-backwards-incompatible-changes=false

If you want to see changes I rejected, you can have a look at greg0ire#2

* Name of the entity class that is cleared, or empty if all are cleared.
*
* @return string|null
* @return string
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There is a check $this->entityClass === null line 84.

Are you sure this value can't be null ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Right, I'll revert this, what is wrong here is the property's phpdoc, let's fix it.

* must override this method and return TRUE.
*
* @return boolean
* @return false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's better to keep return boolean to show all possible values.
It can avoid some return type no compatible with parent error message too.

Copy link
Copy Markdown
Member Author

@greg0ire greg0ire May 17, 2020

Choose a reason for hiding this comment

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

Can it really? false is a boolean, but it is not really a subtype of that. We have both Psalm and Phpstan running on the ORM and neither complained…

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah it's probably that we don't use a strict enough level yet… I will revert this.

* Filled after {@link dispach()}.
*
* @return \Doctrine\Common\Collections\Collection
* @return ArrayCollection
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isn't better to keep the Interface as return type ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm not sure, let see what other people say.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

People will code against your advertised return type. The question is: do you need this method to return an ArrayCollection for it to be used properly, or would any Collection be the same, meaning the choice of ArrayCollection is an implementation detail internal to the method itself?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I agree with @kuraobi

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't need it to be advertised as such, but as a bonus, people can have methods specific to ArrayCollection show up in their auto-completion. Also, their SA tools will not complain if they do use such methods.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's still narrowing the type, which is a BC break. Please propose it for master if you want that

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Narrowing a return type in a concrete class is not a BC break AFAIK, unless you have children classes and no interface to enforce a common contract.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Well there is no interface here, and the class is not final…

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

>>> interface a{function a():IteratorAggregate;}
>>> class b implements a{function a():ArrayObject {}}
>>> class c extends b {function a(): IteratorAggregate {}}
PHP Fatal error:  Declaration of c::a(): IteratorAggregate must be compatible with b::a(): ArrayObject

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yeah so we're all saying the exact same thing 😆

Copy link
Copy Markdown
Member

@ostrolucky ostrolucky left a comment

Choose a reason for hiding this comment

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

This is similar to #8144, we should think about complications when upmerging to 3.x, so let's merge it after it's clear what to do there

Comment thread lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
Comment thread lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
Comment thread lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php Outdated
@greg0ire greg0ire force-pushed the psalter branch 2 times, most recently from f64b278 to 35c16e7 Compare May 17, 2020 11:42
Comment thread lib/Doctrine/ORM/EntityRepository.php Outdated
@greg0ire
Copy link
Copy Markdown
Member Author

This is similar to #8144, we should think about complications when upmerging to 3.x, so let's merge it after it's clear what to do there

Let take this with a grain of salt (lol): the order of magnitude is not really the same (42 files changed vs more than 1000). I can definitely cherry-pick this myself in master afterwards, and I can't say the same about #8144

@greg0ire
Copy link
Copy Markdown
Member Author

I pushed a new version that should make the @psalm-return annotations easier on the eye

@ostrolucky
Copy link
Copy Markdown
Member

I appreciate you volunteer to cherry-pick this to master, but I'm not sure it will solve issues when rebasing it. What I worry would happen is that even if you cherry pick this, during rebasing all conflicts would have to be solved again. But of course, I acknowledge this is much smaller PR. I would merge it, but let's see what @guilhermeblanco has to say.

Copy link
Copy Markdown
Member

@lcobucci lcobucci left a comment

Choose a reason for hiding this comment

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

There're plenty of array<array-key... things there that might be relevant for us to alter. Despite that, thanks a lot 👍

Comment thread lib/Doctrine/ORM/AbstractQuery.php Outdated
* @param integer $lifetime
*
* @return \Doctrine\ORM\AbstractQuery This query instance.
* @return self This query instance.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn't we use static instead? Since this is an abstract class and all....

Comment thread lib/Doctrine/ORM/AbstractQuery.php Outdated
* automatically generated for you.
*
* @return array ($key, $hash)
* @return string[] ($key, $hash)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* @return string[] ($key, $hash)
* @return array<string, string> ($key, $hash)

* @return array|null
* @return mixed[]|null
*
* @psalm-return array{targetEntity: string, type: mixed, list?: array<array-key, array>, identifier?: array}|null
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AFAIK psalm, phpstan, and phpcs understand that if we use it on @return.

Also array<array-key, array> is a bit vague, isn't it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Also array<array-key, array> is a bit vague, isn't it?

woops, will change that indeed

AFAIK psalm, phpstan, and phpcs understand that if we use it on @return.

I'm doing this out of consideration for PhpStorm users (and also it's what Psalter did naturally). I'm told PhpStorm does not understand this yet, cc @goetas with who I had that debate.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That's probably true... 😭

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My general feel on arrays matters are:
1- If array key is ignorable, then use type[] syntax
2- If array key is relevant, then use array<type, type> syntax
3- For maps of maps, repeat the process array<type, array<type, type>>

Anything more complex than 2 requires a comment that describes the return. Also, this hints me that it would be a good candidate for a wrapper object (that encapsulates this logic, make them immutable if needed, only allow pin-point modifications, etc).

Finally, avoid tools specific (aka. non-standardized) markers, such as phpcbf, psalm, phpstan, etc, but rather backed by official standard published publicly, such as xUnit, coverage, etc.

Copy link
Copy Markdown
Member Author

@greg0ire greg0ire May 19, 2020

Choose a reason for hiding this comment

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

Anything more complex than 2 requires a comment that describes the return

From the original author though, I will have a hard time commenting on that after the fact. I agree that we could require that from contributors.

Also, this hints me that it would be a good candidate for a wrapper object (that encapsulates this logic, make them immutable if needed, only allow pin-point modifications, etc).

I love how this PR makes that kind of code smell more visible

Finally, avoid tools specific (aka. non-standardized) markers, such as phpcbf, psalm, phpstan, etc, but rather backed by official standard published publicly, such as xUnit, coverage, etc.

My hope was to remove the prefixes once Phpstorm has caught up. Also, we can't install a recent enough version of phpcs on this branch to support that, it would require dropping old versions of php I think.

Copy link
Copy Markdown
Contributor

@orklah orklah May 19, 2020

Choose a reason for hiding this comment

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

Finally, avoid tools specific (aka. non-standardized) markers, such as phpcbf, psalm, phpstan

My two cents: psalm prefixes are actually compatible with Phpstan and Phan for the most part. Some syntax used is inspired by the unfinished PSR-5 about PHPDoc and it's quite probable that any syntax used in static analysis will make it's way into standards in the end.
Phpstorm is lagging behind because they make the mistake of waiting for standards. It slows adoption, which in turn slows the publication of standards. Adoption by big tools is exactly what we need to help everything move.

I misinterpreted what you meant. However, using @return for advanced notation breaks autocompletion and functionnalities in IDE (I'm sure for PHPStorm and I believe VS Code will have the same issue). This is quite annoying but it will get better when adoption rate of these notations become wider.

* @return array
* @return mixed[]
*
* @psalm-return list<array-key>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* @psalm-return list<array-key>
* @psalm-return list<string>

* unique: bool,
* nullable: bool,
* precision: int,
* options?: array,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Array of what?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Of "both"! Ya... if you use ['foo' => true] or ['foo'], it'll lead to the same result and will become FOO on column definition.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Let's use mixed[] here I guess 😅

* @return self This query instance.
*/
public function setSQL($sql)
public function setSQL($sql) : self
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Final classes are just ❤️

}

/**
* @return mixed[]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wouldn't this be something like \Doctrine\DBAL\Types\Type[]?

Comment thread lib/Doctrine/ORM/Query/Expr/Base.php Outdated
* @param array $args
*
* @return Base
* @return self
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

static?

Comment thread lib/Doctrine/ORM/Query/ParserResult.php Outdated
Comment on lines +68 to +69
* @return ResultSetMapping The result set mapping of the parsed query or
* NULL if the query is not a SELECT query.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment and change don't make sense together

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🤔 indeed. The property is private, and from reading its accessor and the setter, it does not look like it could be null, so let's remove that part of the comment.

Comment thread phpcs.xml.dist Outdated
Comment on lines +128 to +130
<rule ref="SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod">
<exclude-pattern>lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php</exclude-pattern>
</rule>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd suggest using // phpcs:ignore SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod only on the method that's being ignored instead of excluding the entire file.


/**
* @var string
* @var string|null
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please review this, I think the string is always true, not nullable.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

clear() can (and should?) be called without an entity name. And from the code it looks like that really happens.

*
* @return array An array with all the fields (name => value) of the data row,
* grouped by their component alias.
* @return mixed[][] An array with all the fields (name => value) of the
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sharing same thing here as mentioned on https://github.com/doctrine/orm/pull/8150/files#r427314368

Copy link
Copy Markdown
Member

@guilhermeblanco guilhermeblanco May 19, 2020

Choose a reason for hiding this comment

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

Copying same comments shared on Slack:

I’m against using these types of annotations, but rather provide relevant comments on the actual data structure. Also, we should be doing better at describing the data structure (mixed[][] is far from ideal), and rely on array<string, array<string, mixed>> in this scenario. Also, meaningful comments should exist describing the data structure… and finally, complex arrays hierarchies like this one screams the needs of wrapper objects.

* @param string $fieldName
*
* @return AssociationBuilder
* @return self
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

static as return type everywhere in this file, since it's inherited by more specialized AssociationBuilders

* @param array $mapping The mapping.
*
* @return array The updated mapping.
* @return mixed[] The updated mapping.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh... now I remember why we started 3.0...
Maybe we should do something on psalm to ignore these return mappings and only enforce on 3.0. The entire 2.X series we are only relying on complex array structures as they were 1- more memory effective and 2- faster than objects.
This is no longer true on PHP 7.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Glad to learn all these mixed[] will go away in 3.x :)

@greg0ire greg0ire force-pushed the psalter branch 2 times, most recently from 9433159 to 9f7d9a9 Compare May 20, 2020 06:52
These changes are a subset of changes done with vendor/bin/psalm --alter
--issues=LessSpecificReturnType
--allow-backwards-incompatible-changes=false
Copy link
Copy Markdown
Member

@beberlei beberlei left a comment

Choose a reason for hiding this comment

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

What could go wrong? only comments :D

@beberlei beberlei merged commit 6c73a6b into doctrine:2.7 Jul 5, 2020
@beberlei beberlei added this to the 2.7.4 milestone Jul 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants