maker-bundle
maker-bundle copied to clipboard
Psalm LessSpecificImplementedReturnType error on Repository's `findAll()` docblock
Psalm is reporting this:
ERROR: LessSpecificImplementedReturnType - src/Repository/LinkRepository.php:8:12 - The inherited return type 'list
' for Doctrine\ORM\EntityRepository::findAll is more specific than the implemented return type for Doctrine\ORM\EntityRepository::findall 'array<array-key, App\Entity\Link>' (see https://psalm.dev/166) /**
- @method Link|null find($id, $lockMode = null, $lockVersion = null)
- @method Link|null findOneBy(array $criteria, array $orderBy = null)
- @method Link[] findAll()
- @method Link[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
- @extends ServiceEntityRepository<Link> */
Psalm is emitting this because Doctrine\ORM\EntityRepository::findAll() has a return type of list<T> which ultimately is translated by psalm to array<int, Foo>. Where as the @method Link[] findAll() return type is ultimately translated by psalm to @psalm-return array<array-key, ValueType>
I believe changing @method return signatures to array<int, Link> (I cant remember if this syntax is legitimate) would squash this squawk from psalm. It does however look less appealing when you end up with:
/**
* @method Link|null find($id, $lockMode = null, $lockVersion = null)
* @method Link|null findOneBy(array $criteria, array $orderBy = null)
* @method array<int, Link>[] findAll()
* @method Link[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class LinkRepository extends ServiceEntityRepository
Then, depending on your rule set, php-cs-fixer would complain about the column alignment in that docBlock and adjust accordingly..
/**
* @method Link|null find($id, $lockMode = null, $lockVersion = null)
* @method Link|null findOneBy(array $criteria, array $orderBy = null)
* @method array<int, Link> findAll()
* @method Link[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class LinkRepository extends ServiceEntityRepository
Personally, I ignore this particular error in my psalm.xml or baseline file. That approach is not ideal but I'm not sure what the best approach to keeping psalm silent is. Open to ideas!
Perhaps a stub in https://github.com/psalm/psalm-plugin-symfony?
@ThomasLandauer @jrushlow Is there a way to define T in list<T> in our own repositories? That would solve the problem and would lead to us not needing to define @method in the first place.
@christian-kolb I'm sure there is - https://psalm.dev/docs/annotating_code/templated_annotations/ has more information on template annotations. If it is possible for us to do that in a clean manner without any adverse effects - PR's welcome..
I guess there would be changes in the ServiceEntityRepository which is part of Doctrine, isn't it?
Here is the syntax I use to be compatible with most cases:
Specify the template with by entity with @extends
Specify a signature dedicated to Psalm with @psalm-method
/**
* @extends ServiceEntityRepository<Link>
* @method Link|null find($id, $lockMode = null, $lockVersion = null)
* @method Link|null findOneBy(array $criteria, array $orderBy = null)
* @psalm-method list<Link> findAll()
* @method Link[] findAll()
* @psalm-method list<Link> findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* @method Link[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class LinkRepository extends ServiceEntityRepository
@weaverryan can we just remove these comments from the generation ?
There is no psalm error without these.
Or we can (optionally) add psalm-ones to the generation, no?
Here is the syntax I use to be compatible with most cases:
Specify the template with by entity with
@extendsSpecify a signature dedicated to Psalm with
@psalm-method/** * @extends ServiceEntityRepository<Link> * @method Link|null find($id, $lockMode = null, $lockVersion = null) * @method Link|null findOneBy(array $criteria, array $orderBy = null) * @psalm-method list<Link> findAll() * @method Link[] findAll() * @psalm-method list<Link> findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) * @method Link[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class LinkRepository extends ServiceEntityRepository
This work on level 4+, but cause InvalidDocblock error on level 3
The only method I could get down to level 1 was to add @psalm-suppress
/**
* @psalm-suppress MethodSignatureMustProvideReturnType
* @psalm-suppress LessSpecificImplementedReturnType
*
* @extends ServiceEntityRepository<Round>
*
* @method Round|null find($id, $lockMode = null, $lockVersion = null)
* @method Round|null findOneBy(array $criteria, array $orderBy = null)
* @method Round[] findAll()
* @method Round[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class RoundRepository extends ServiceEntityRepository
Ofcourse its not perfect, but it gets the job done, it will properly also be a problem when you add your own find methods, which will not be static analyzed either.