A Doctrine plugin for Psalm (requires Psalm v4|v5).
Installation:
$ composer require --dev weirdan/doctrine-psalm-plugin
$ vendor/bin/psalm-plugin enable weirdan/doctrine-psalm-plugin
Testing
composer test
Stubs to let Psalm understand Doctrine better
A Doctrine plugin for Psalm (requires Psalm v4|v5).
Installation:
$ composer require --dev weirdan/doctrine-psalm-plugin
$ vendor/bin/psalm-plugin enable weirdan/doctrine-psalm-plugin
Testing
composer test
vimeo/psalm 4.8.1
weirdan/doctrine-psalm-plugin 1.0.0
/** @param Collection<int, A>|Collection<int, B> */
public function deleteItemById(Collection $collection, int $id): void
{
$matchedItems = $collection->filter(
static function ($inCollectionItem) use ($id): bool {
return $inCollectionItem->haveId($id);
}
);
if (!$matchedItems->isEmpty()) {
$collection->removeElement($matchedItems->first()); // yields PossiblyInvalidArgument
}
}
psalm: PossiblyInvalidArgument: Argument 1 of Doctrine\Common\Collections\Collection::removeElement expects A, possibly different type A|B provided
It looks false-positive to me, it's impossible to call here Collection<int, A>::removeElement(B)
.
We use the Doctrine\ORM\Query\Expr
methods in a few places when building queries. Some of these, such as orX()
and andX()
accept arbitrary numbers of arguments using func_get_args()
. The causes the following error when analysing with Psalm.
ERROR: TooManyArguments - src/Repository/UserJournalEntryRepository.php:41:17 - Too many arguments for method Doctrine\ORM\Query\Expr::orX - expecting 1 but saw 2
$qb->expr()->orX(
$qb->expr()->gt('uje.value.amount', '0'),
$qb->expr()->isNotNull('t')
)
Is it possible to stub these methods? I'm happy to create a PR but don't know how to correctly annotate methods which accept arbitrary numbers of arguments.
Docker image:
php:7.4.3-fpm-alpine
composer require --dev weirdan/doctrine-psalm-plugin
vendor/bin/psalm-plugin enable weirdan/doctrine-psalm-plugin
vendor/bin/psalm
Stacktrace:
ncaught Error: Undefined constant 'GLOB_BRACE' in /srv/api/vendor/weirdan/doctrine-psalm-plugin/Plugin.php:32
Stack trace:
#0 /srv/api/vendor/weirdan/doctrine-psalm-plugin/Plugin.php(22): Weirdan\DoctrinePsalmPlugin\Plugin->getStubFiles()
#1 /srv/api/vendor/vimeo/psalm/src/Psalm/Config.php(1161): Weirdan\DoctrinePsalmPlugin\Plugin->__invoke(Object(Psalm\PluginRegistrationSocket), NULL)
#2 /srv/api/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(493): Psalm\Config->initializePlugins(Object(Psalm\Internal\Analyzer\ProjectAnalyzer))
#3 /srv/api/vendor/vimeo/psalm/src/psalm.php(594): Psalm\Internal\Analyzer\ProjectAnalyzer->check('/srv/api/', false)
#4 /srv/api/vendor/vimeo/psalm/psalm(2): require_once('/srv/api/vendor...')
#5 {main}
Hi! Since this repo relates to doctrine it may be useful to use their coding-standard (https://github.com/doctrine/coding-standard).
Hi again. Sorry for the spamming π
Using the below snippet, I get the following error InvalidTemplateParam - ... - Extended template param TKey expects type array-key, type empty given
.
<?php
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
class Test
{
/**
* @var Collection<int, string>
*/
private $strings;
public function __construct()
{
$this->strings = new ArrayCollection();
$this->strings->filter(
function (string $s):bool {
return $s !== '';
});
}
}
The same error comes when using strings->map
, but not when using strings->exists
or strings->forAll
.
I can also prevent the error by adding a type annotation to the property initialization like this:
/** @var Collection<int, string> strings */
$this->strings = new ArrayCollection();
Any ideas what might be causing this issue?
This will be blocked by #10
I found the case when the property (code) has different type from config
class User
{
/** @var string */
private $username;
//ctor and other stuff
}
<field name="username" type="string" column="username" nullable="true"/>
the error is that in config it's nullable, but in the code it's not
weirdan/doctrine-psalm-plugin 0.11.3
vimeo/psalm 3.17.2
use Doctrine\Common\Collections\Collection;
function processCollection(Collection $collection)
{
$matched = $collection->filter(function ($collectionItem) {
return rand(0, 1) === 1;
});
if (!$matched->isEmpty()) {
$matched->first()->hi(); // PossiblyFalseReference - Cannot call method hi on possibly false value (see https://psalm.dev/105)
$collection->removeElement($matched->first()); // PossiblyFalseArgument - Argument 1 of Doctrine\Common\Collections\Collection::removeElement cannot be false, possibly false value provided (see https://psalm.dev/104)
}
}
Neither first() nor last() can't return false on Collection that is not empty.
Now that 7.4 is GA we should test with it as well (as it may allow different deps).
After installing this plugin, PhpStorm complains that multiple definitions exist for each class stub defined. Because it can't tell whether it should be using the stub.
I can't seem to find a way to make PhpStorm handle this proprly, there's an SO question and a JetBrains issue for it too.
I'm wondering what everyone else does to deal with this?
If you can point me in the general direction of how to do this (e.g. an open-source codebase that would benefit from this typing) I can create a PR
This package currently has a stub for, for example Doctrine\Common\Persistence\ObjectRepository
. Though there's a compatibility layer using class_alias()
, this class has been moved to Doctrine\Persistence\ObjectRepository
. We should ensure the stub works for both namespaces.
This project is looking for maintainers.
This package is currently outdated and supports neither newer Psalm versions (starting from v4) nor newer Doctrine versions (there should be some, but I haven't checked). I don't currently use Doctrine, so it doesn't scratch my itch anymore. Rather it has become a burden. I recognize the need for this package is still there though.
I have reasonable hopes to get tests green with the next Psalm release and release a version compatible with Psalm 4. Tests are very important to me, because it's my only way to see if things work as I don't use Doctrine myself.
After that I'd like to negotiate with Psalm's author, @muglug, to get this package under Psalm's umbrella GH org, similar to how some other plugins are managed. There I'll try to get the plugin updated to support new Doctrine versions, one last time, while simultaneously looking for people willing to maintain this. Once the package is in good shape, I will likely step down as a maintainer. I haven't fully decided yet whether I stop maintenance should I fail to find a co-maintainer, but this is a possibility. If I decide to continue, my efforts will be at the level of merging occasional PRs, but not more.
Hi, thanks for the great plugin!
I have a question - I'm getting UndefinedInterfaceMethod-errors in my symfony4-project like this:
ERROR: UndefinedInterfaceMethod - src\ControllerShop\IndexController.php:45:68 - Method Doctrine\Common\Persistence\ObjectRepository::createquerybuilder does not exist
$qb = $this->getDoctrine()->getRepository(Article::class)->createQueryBuilder('a');
ERROR: UndefinedInterfaceMethod - src\ControllerShop\IndexController.php:98:83 - Method Doctrine\Common\Persistence\ObjectRepository::findforcompany does not exist
$staffToken = $this->getDoctrine()->getRepository(StaffToken::class)->findForCompany($company, $token);
Problem seems to be, that the methods are not checked against the real repository, but the generic ObjectRepository. Is it right, that the plugin does not recognise these methods in the repositories? Am I doing something wrong here?
Thanks in advance!
Hi, I'm unable to load the stubs due to the glob in Pluing.php line 22 having two backslashes before the .php
. It works if I remove the extra slash.
Just wondering if there's any reason we do have stub for ORM QueryBuilder but don't have one for DBAL?
I could create one unless I miss something, just let me know.
the taint sink for the function executeStatement
is missing (the deprecated exec
works).
example:
$connection->executeStatement('sql '. $request->get('foo'));
Doctrine uses __call
to allow specific findOneBy*
methods - you could use MethodExistenceProviderInterface
, MethodParamsProviderInterface
and MethodReturnTypeProviderInterface
to support the functionality, I think?
Currently the $offset
argument is hinted as TKey
which is wrong, because by design the int
offset is always accepted, no matter what the key is. See https://github.com/doctrine/collections/blob/master/lib/Doctrine/Common/Collections/ArrayCollection.php#L397
Hey there,
I have entities which have own repository implementations.
These implementations are referred to with the Entity
Attribute/Annotation (using repositoryClass
option).
This plugin only provides generic support as of now.
Are you interested in having this feature part of this plugin?
I think I might find some time somewhen in the near future to implement that.
Happy to get feedback on this.
This plugin needs to be able to load doctrine configuration for functionality like checking entity types, findBy* methods, etc.
Requires:
psalm 4.19.0
weirdan/doctrine-psalm-plugin v2.2.0
Symfony 6.0.3
PHP 8.1
> ./vendor/bin/psalm --show-info=true
Target PHP version: 8.1 (inferred from composer.json)
Scanning files...
Analyzing files...
ββββββββββββββββββββββββββUncaught Exception: InvalidArgumentException Could not get class storage for doctrine\dbal\dbalexception
Emitted in /Users/dmitriyrybin/PhpstormProjects/.../app/api/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php:46
Stack trace in the forked worker:
#0 /Users/dmitriyrybin/PhpstormProjects/.../app/api/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/ClassLikes.php(628): Psalm\Internal\Provider\ClassLikeStorageProvider->get('Doctrine\\DBAL\\D...')
...
If I comment <pluginClass class="Weirdan\DoctrinePsalmPlugin\Plugin"/>
in psalm.xml or downgrading weirdan/doctrine-psalm-plugin to v2.0.1 everything works fine
Hi,
This issue was solved by manual configuration in #18 but it could be nice to deal with it for everybody at once.
PHPStan made the choice of renaming their stubs to .stub to solve this issue(phpstan/phpstan-src@b20d7b6). I think it's a great solution.
Could it be applied here as well?
Thanks
Is it expected that these are reported as INFO? Or should they not appear in psalm errors at all.
I am running Symfony 6.1.6, psalm 4.30.0 and weirdan/doctrine-psalm-plugin 2.5.0
INFO: MissingConstructor - src/Entity/SupportTicketDepartment.php:17:17 - App\Entity\SupportTicketDepartment has an uninitialized property App\Entity\SupportTicketDepartment::$id, but no constructor (see https://psalm.dev/073)
private int $id;
...
INFO: PropertyNotSetInConstructor - src/Entity/SupportTicketMailBreakLine.php:28:19 - Property App\Entity\SupportTicketMailBreakLine::$admin is not defined in constructor of App\Entity\SupportTicketMailBreakLine or in any private or final methods called in the constructor (see https://psalm.dev/074)
private Admin $admin;
https://psalm.dev/r/ae80d4ac49 false is returned from Collection::first
only when collection is empty
Thanks for this plugin. It removes a lot of false errors from my codebase β€οΈ
I wonder if we can also fix this error:
INFO: PropertyNotSetInConstructor - src/Infrastructure/Persistence/Doctrine/Repository/DoctrineSettlementRepository.php:15:13 - Property Doctrine\ORM\EntityRepository::$_entityName is not defined in constructor of Infrastructure\Persistence\Doctrine\Repository\DoctrineSettlementRepository and in any methods called in the constructor
final class DoctrineSettlementRepository extends AbstractServiceEntityRepository implements SettlementRepository
code:
final class DoctrineSettlementRepository extends AbstractServiceEntityRepository implements SettlementRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, Settlement::class);
}
We have a code where we currently extend Doctrine\ORM\EntityManger
. On error level 7 the following error pops up:
ERROR: MethodSignatureMismatch - .../EntityManager.php:X:Y - Argument 1 of Doctrine\ORM\EntityManager::find has wrong type 'string', expecting '' as defined by Doctrine\Persistence\ObjectManager::find (see https://psalm.dev/042)
class EntityManager extends DoctrineEntityManager
Once I remove native type from find()
's 1st parameter in vendor/weirdan/doctrine-psalm-plugin/stubs/EntityManagerInterface.phpstub
the error disappears. But that doesn't seem like a correct solution.
I am also wondering whether this could be a Psalm bug related to ParamNameMismatch
because ObjectManager::find()
names the parameter as $className
instead of $entityName
.
Since #94, this extension supports the scenario of checking a Collections's emptiness and then using first()
and last()
on that collection without worrying about the return type being false
. This is great, however, a Collection being empty has more effects than this, including:
toArray()
returning a non-empty-array
getKeys()
returning a non-empty-list
getValues()
returning a non-empty-list
Also, a Collection being empty could be asserted by
count()
returns a value other than 0add()
at least onceset()
at least once@psalm-assert !$collection->isEmpty()
with the collectioncontains()
returns truecurrent()
doesn't return falsekey()
doesn't return nullnext()
doesn't return falsemap()
method of another non-empty CollectionindexOf()
doesn't return falseLessSpecificImplementedReturnType - src/Repository/SomethingRepository.php:9:12 - The inherited return type 'list<App\Entity\Something>' for Doctrine\ORM\EntityRepository::findAll is more specific than the implemented return type for Doctrine\ORM\EntityRepository::findall 'array<array-key, App\Entity\Something>'
Code in my SomethingRepository:
/**
* @method Something[] findAll() (this PHPDoc was auto-generated by Symfony)
* @extends ServiceEntityRepository<Something>
*/
class SomethingRepository extends ServiceEntityRepository
{
*/
This is a snippet from Doctrine\ORM\EntityRepository
/**
* Finds all entities in the repository.
*
* @return array The entities.
*/
public function findAll()
{
return $this->findBy([]);
}
Just an array.
This is from Doctrine\Persistence\ObjectRepository that implemented by Doctrine\ORM\EntityRepository:
/**
* Contract for a Doctrine persistence layer ObjectRepository class to implement.
*
* @template T
*/
interface ObjectRepository
{
.....
/**
* Finds all objects in the repository.
*
* @return array<int, object> The objects.
*
* @psalm-return T[]
*/
public function findAll();
....
}
So it returns just T[], Something[] in my case.
Looks like there is a problem in the plugin's stub files.
weirdan/doctrine-psalm-plugin 1.0.0
vimeo/psalm 4.7.0
For any class that extends ServiceEntityRepository I got three false-positive PropertyNotSetInConstructor errors. These variables are properly set in EntityRepository class.
ERROR: PropertyNotSetInConstructor - src/Repository/RedBallRepository.php:20:7 - Property App\Repository\RedBallRepository::$_entityName is not defined in constructor of App\Repository\RedBallRepository and in any methods called in the constructor (see https://psalm.dev/074)
class RedBallRepository extends ServiceEntityRepository
ERROR: PropertyNotSetInConstructor - src/Repository/RedBallRepository.php:20:7 - Property App\Repository\RedBallRepository::$_em is not defined in constructor of App\Repository\RedBallRepository and in any methods called in the constructor (see https://psalm.dev/074)
class RedBallRepository extends ServiceEntityRepository
ERROR: PropertyNotSetInConstructor - src/Repository/RedBallRepository.php:20:7 - Property App\Repository\RedBallRepository::$_class is not defined in constructor of App\Repository\RedBallRepository and in any methods called in the constructor (see https://psalm.dev/074)
class RedBallRepository extends ServiceEntityRepository
When trying to update to 2.4.0
, composer install fails because of a conflict. In my case its doctrine/coding-standard
, but there could probably also be conflicts with other packages.
The reason is that phpstan/phpdoc-parser
was locked to ~1.5.0
(which is a relatively old version, current is 1.9.0
) in this commit: 16e8192
The commit message is not related to adding this requirement, so I'm not sure if this was added by accident.
Is locking the phpstan/phpdoc-parser
version really necessary or can this tight version constraint be removed again?
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires doctrine/coding-standard 10.0.0 -> satisfiable by doctrine/coding-standard[10.0.0].
- doctrine/coding-standard 10.0.0 requires slevomat/coding-standard ^8.2 -> satisfiable by slevomat/coding-standard[8.2.0, ..., 8.5.2].
- slevomat/coding-standard[8.2.0, ..., 8.3.0] require phpstan/phpdoc-parser ^1.6.2 -> satisfiable by phpstan/phpdoc-parser[1.6.2, ..., 1.9.0].
- slevomat/coding-standard[8.5.0, ..., 8.5.2] require phpstan/phpdoc-parser >=1.7.0 <1.9.0 -> satisfiable by phpstan/phpdoc-parser[1.7.0, 1.8.0].
- slevomat/coding-standard 8.4.0 requires phpstan/phpdoc-parser >=1.7.0 <1.8.0 -> satisfiable by phpstan/phpdoc-parser[1.7.0].
- You can only install one version of a package, so only one of these can be installed: phpstan/phpdoc-parser[1.5.0, ..., 1.9.0].
- weirdan/doctrine-psalm-plugin v2.4.0 requires phpstan/phpdoc-parser ~1.5.0 -> satisfiable by phpstan/phpdoc-parser[1.5.0, 1.5.1].
- Root composer.json requires weirdan/doctrine-psalm-plugin 2.4.0 -> satisfiable by weirdan/doctrine-psalm-plugin[v2.4.0].
$ composer require --dev weirdan/doctrine-psalm-plugin
1/1: http://repo.packagist.org/p/provider-latest$7a09c6bfb6355b10ab8adaba5751981b1496747a29a02c40c29455abac1dbb6a.json
Finished: success: 1, skipped: 0, failure: 0, total: 1
Using version ^0.4.2 for weirdan/doctrine-psalm-plugin
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing weirdan/doctrine-psalm-plugin (0.4.2): Loading from cache
Package weirdan/psalm-doctrine-collections is abandoned, you should avoid using it. Use weirdan/doctrine-psalm-plugin instead.
Writing lock file
Generating autoload files
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
phpstan/extension-installer: Extensions installed
$ vendor/bin/psalm-plugin enable weirdan/doctrine-psalm-plugin
[ERROR] Unknown plugin class weirdan/doctrine-psalm-plugin
It worked fine with weirdan/psalm-doctrine-collections
though...
$ vendor/bin/psalm-plugin show
Enabled
-------
------------------------------------ ------------------------------------
Package Class
------------------------------------ ------------------------------------
psalm/plugin-phpunit Psalm\PhpUnitPlugin\Plugin
weirdan/psalm-doctrine-collections Weirdan\DoctrinePsalmPlugin\Plugin
------------------------------------ ------------------------------------
Available
---------
! [NOTE] No plugins available
Doctrine is slowly phasing out Doctrine/Common and they deprecated Doctrine\Common\Persistence\ObjectRepository.
The replacement is Doctrine\Persistence\ObjectRepository which is the same class but in another namespace.
However, when we get rid of the depreciation by replacing imports, this plugin does not offer stubs for the new namespace.
How should we proceed on this issue?
I get this error:
ERROR: MixedReturnTypeCoercion - ProfileRepository.php:22:16 - The declared return type 'array<array-key, Profile>' for ProfileRepository::getProfiles is more specific than the inferred return type 'list<mixed>' (see https://psalm.dev/197)
* @return array<Profile>
With this Repo (simple example of using QueryBuilder):
/**
* @template-extends ServiceEntityRepository<Profile>
*/
class ProfileRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Profile::class);
}
/**
* @return array<Profile>
*/
public function getProfiles(): array
{
return $this->createQueryBuilder('p')->getQuery()->getResult();
}
}
So I'm questioning myself: Should EntityRepository->createQueryBuilder()
return a Query
with the templated type Profile
instead of mixed
? Right now Query
can be templated thanks to this plugin but the QueryBuilder
cannot pass this information to the Query
right now so it returns mixed
. But if we maybe add the template annotation to the QueryBuilder
we could pass it to Query
. I tried to update the stubs for QueryBuilder
but this was of course not sufficient. So i tried to update the plugin with an hook like the Collection hook already provided but failed to get it working. So first, i wanted to check if this route is the right before putting more work into it. So what do you think?
I need a lot of suppressions because the methods of the Query
class like getResult()
, getSingleResult()
, getOneOrNullResult()
, etc. return mixed. I've tried to create a stub for the AbstractQuery
(thats where the methods actually live), but I was only able to let it return array
(in the case of getResult()
) which causes other issues. I am not really familiar with the concepts of generics, but I think this would be the way to go here.
Any hints whether this is possible at all and maybe point me in the right direction?
Any collection which extends ArrayCollection produce error:
ERROR: MissingImmutableAnnotation - src/Sales/Domain/Collection/ReturnItemCollection.php:20:7 - Doctrine\Common\Collections\Collection::isEmpty is marked @psalm-immutable, but Doctrine\Common\Collections\ArrayCollection::isEmpty is not marked @psalm-immutable (see https://psalm.dev/213) class ReturnItemCollection extends ArrayCollection implements JsonSerializable
Psalm 3.14.2@3538fe1955d47f6ee926c0769d71af6db08aa488 + weirdan/doctrine-psalm-plugin
ERROR: NullArgument - src/Entity/Organization.php:155:13 - Argument 1 of Doctrine\Common\Collections\ArrayCollection::offsetSet cannot be null, null value provided to parameter with type int|string (see https://psalm.dev/057)
$this->staff[] = $staff;
But offsetSet can be null:
/**
* Required by interface ArrayAccess.
*
* {@inheritDoc}
*/
public function offsetSet($offset, $value)
{
if (! isset($offset)) {
$this->add($value);
return;
}
$this->set($offset, $value);
}
If I turn off the plugin, the errors are disappeared.
<?php
declare(strict_types=1);
namespace Repro;
class Conn extends \Doctrine\DBAL\Connection
{
}
Scanning files...
Analyzing files...
ERROR: MethodSignatureMismatch - src/Conn.php:6:7 - Argument 1 of Doctrine\DBAL\Connection::prepare has wrong type 'string', expecting '' as defined by Doctrine\DBAL\Driver\Connection::prepare (see https://psalm.dev/042)
class Conn extends \Doctrine\DBAL\Connection
------------------------------
1 errors found
------------------------------
Checks took 0.00 seconds and used 4.382MB of memory
No files analyzed
Psalm was unable to infer types in the codebase
Repro: https://github.com/zerkms/psalm-plugin-doctrine-issue-91
I cannot see anything particularly suspicious in the stub, so it also could be a psalm bug.
Similar to psalm/psalm-plugin-phpunit#89
The two following dependency
"doctrine/collections": "^1.0",
"doctrine/orm": "^2.6",
are not needed by this library to work.
Psalm just need an access to these library, but it can be done with the extraFiles
options and not with the vendor.
I think the Phpstan way is better:
https://github.com/phpstan/phpstan-doctrine/blob/master/composer.json
I've just updated to 0.7.0 and am getting errors reporting when passing Doctrine\ORM\Query\Expr\Comparison
objects into Doctrine\ORM\QueryBuilder::andWhere()
.
The QueryBuilder
stub defines a custom Psalm type @psalm-type _WhereExpr=Expr\Base|string
. Unfortunately Doctrine's expression classes don't all extend Doctrine\ORM\Query\Expr\Base
.
I believe the type needs changing to @psalm-type _WhereExpr=Expr\Base|Expr\Comparison|string
.
TL;DR: EntityRepository<T>::matching
has return type Collection
, should be Collection<int, T>
Code: https://psalm.dev/r/678bf40ce6
Error: The type 'Doctrine\Common\Collections\Collection' is more general than the declared return type 'Doctrine\Common\Collections\Collection<int, Entity>' for MyRepository::foo
Versions of my packages:
doctrine/collections 1.6.6
doctrine/orm v2.7.3
vimeo/psalm 3.12.2
weirdan/doctrine-psalm-plugin 0.11.3
Is it reproducible or is it just me?
matching
to the stubI started digging a bit and found that:
BUT:
Therefore I'd like to add matching
to the EntityRepository
-stub. I'm happy to provide a PR, just let me know.
Thank you for taking the time and have a nice day!
@psalm-param definitions for $query and $types are off by one on executeUpdate and executeStatement.
Connection::executeUpdate
Connection::executeStatement
Proposal:
- * @psalm-param scalar[] $params The query parameters.
+ * @psalm-param scalar[] $query The query parameters.
- * @psalm-param int[]|string[] $types The parameter types.
+ * @psalm-param int[]|string[] $params The parameter types.
public function [...](string $query, array $params = [], array $types = []): int {}
Error Output:
Argument 2 of Doctrine\DBAL\Connection::executeUpdate expects array<array-key, scalar>, array{ids: array<array-key, mixed>} provided (see https://psalm.dev/004)
array(
'ids' => $articleIDs
),
BR
Martin
I added this plugin to my large project using Doctrine and it only added two new issues. I am wondering how the stubs work, do i need to do something myself to benefit from the plugin?
I would appreciate some more docs on the features
InvalidArgument - src/Repository/SomethingRepository.php:20:29 - Argument 1 of Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository::__construct expects Doctrine\Common\Persistence\ManagerRegistry, Doctrine\Persistence\ManagerRegistry provided
Doctrine\Common\Persistence\ManagerRegistry has been moved to Doctrine\Persistence\ManagerRegistry namespace.
Plugin should add capability to infer reduced type from Collection::filter
based on assertions in a callback, similarly as Psalm currently does for array_filter
. Here is what should be supported: https://psalm.dev/r/1b5cbdc9c0
Backstory: From conversation with @muglug:
Add that to the doctrine plugin
This is the current annotation: https://github.com/doctrine/collections/blob/a4504c79efd8847cc77d10b70209ef838b10338f/lib/Doctrine/Common/Collections/Collection.php#L214-L225
thereβs basically no way to annotate that in a docblock
Hello,
I was looking into using this plugin, but notices it downloads ORM (while I am only using DBAL).
This is caused by these composer lines:
https://github.com/weirdan/doctrine-psalm-plugin/blob/d75579d076dd69fe5120bf8a401cea06f2e04919/composer.json#L16-L17
Since you are only providing stubs, I am not sure why you need this as a dependency.
Would it be possible to declare it as a dev dependency if you require it for this package or remove it if you don't have a hard dependency on it?
I currently solved the issue by copying the DBAL stubs locally.
class Test {
private Collection $collection;
/**
* @psalm-mutation-free
*/
public function test(): array
{
return $this->collection->toArray();
}
}
ImpureMethodCall: Cannot call an possibly-mutating method Doctrine\Common\Collections\Collection::toArray from a mutation-free context
doctrine/orm 2.7.4
weirdan/doctrine-psalm-plugin 0.11.3
vimeo/psalm 3.18.2
Hey there,
somehow, psalm asserts that the return type of find
is not nullable.
The generic is properly detected tho.
use Doctrine\ORM\EntityManagerInterface;
final class Foo
{
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @psalm-param positive-int $id
*/
private function status(int $leadId): ?Entity
{
return $this->entityManager->find(Entity::class, $leadId);
}
}
ERROR: LessSpecificReturnType - The inferred return type 'Entity' for Foo::status is more specific than the declared return type 'Entity|null' (see https://psalm.dev/088)
private function status(int $leadId): ?Entity
Package | Version |
---|---|
vimeo/psalm Β |
4.7.0 |
weirdan/doctrine-psalm-plugin |
1.0.0 |
doctrine/orm Β |
2.7.5 |
I've already tried to replace ?T
with T|null
locally (within the stubfile, and cleared cache afterwards) but that did not work as expected.
Hi,
According to https://psalm.dev/docs/annotating_code/type_syntax/array_types/ , the "list" type is a subtype of "array<int, Foo>" with the extra propery that "$arr === array_values($arr)"
Meanwhile, Foo[] is equivalent to array<int|string, Foo>
I believe every case of T[] in the context of Doctrine could be better represented by list
I can try to create the PR if needed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.