Infer return type information with Psalter#8150
Conversation
54e82d6 to
f805936
Compare
| * Name of the entity class that is cleared, or empty if all are cleared. | ||
| * | ||
| * @return string|null | ||
| * @return string |
There was a problem hiding this comment.
There is a check $this->entityClass === null line 84.
Are you sure this value can't be null ?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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…
There was a problem hiding this comment.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Isn't better to keep the Interface as return type ?
There was a problem hiding this comment.
I'm not sure, let see what other people say.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
It's still narrowing the type, which is a BC break. Please propose it for master if you want that
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Well there is no interface here, and the class is not final…
There was a problem hiding this comment.
>>> 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
There was a problem hiding this comment.
Yeah so we're all saying the exact same thing 😆
ostrolucky
left a comment
There was a problem hiding this comment.
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
f64b278 to
35c16e7
Compare
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 |
|
I pushed a new version that should make the |
|
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. |
lcobucci
left a comment
There was a problem hiding this comment.
There're plenty of array<array-key... things there that might be relevant for us to alter. Despite that, thanks a lot 👍
| * @param integer $lifetime | ||
| * | ||
| * @return \Doctrine\ORM\AbstractQuery This query instance. | ||
| * @return self This query instance. |
There was a problem hiding this comment.
Shouldn't we use static instead? Since this is an abstract class and all....
| * automatically generated for you. | ||
| * | ||
| * @return array ($key, $hash) | ||
| * @return string[] ($key, $hash) |
There was a problem hiding this comment.
| * @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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
| * @psalm-return list<array-key> | |
| * @psalm-return list<string> |
| * unique: bool, | ||
| * nullable: bool, | ||
| * precision: int, | ||
| * options?: array, |
There was a problem hiding this comment.
Of "both"! Ya... if you use ['foo' => true] or ['foo'], it'll lead to the same result and will become FOO on column definition.
There was a problem hiding this comment.
Let's use mixed[] here I guess 😅
| * @return self This query instance. | ||
| */ | ||
| public function setSQL($sql) | ||
| public function setSQL($sql) : self |
| } | ||
|
|
||
| /** | ||
| * @return mixed[] |
There was a problem hiding this comment.
Wouldn't this be something like \Doctrine\DBAL\Types\Type[]?
| * @param array $args | ||
| * | ||
| * @return Base | ||
| * @return self |
| * @return ResultSetMapping The result set mapping of the parsed query or | ||
| * NULL if the query is not a SELECT query. |
There was a problem hiding this comment.
Comment and change don't make sense together
There was a problem hiding this comment.
🤔 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.
| <rule ref="SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod"> | ||
| <exclude-pattern>lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php</exclude-pattern> | ||
| </rule> |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Please review this, I think the string is always true, not nullable.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Sharing same thing here as mentioned on https://github.com/doctrine/orm/pull/8150/files#r427314368
There was a problem hiding this comment.
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 onarray<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 |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Glad to learn all these mixed[] will go away in 3.x :)
9433159 to
9f7d9a9
Compare
These changes are a subset of changes done with vendor/bin/psalm --alter --issues=LessSpecificReturnType --allow-backwards-incompatible-changes=false
beberlei
left a comment
There was a problem hiding this comment.
What could go wrong? only comments :D
These changes are a subset of changes done with
vendor/bin/psalm --alter --issues=LessSpecificReturnType --allow-backwards-incompatible-changes=falseIf you want to see changes I rejected, you can have a look at greg0ire#2