Repository navigation
|
Hello, Here is some code from the library Foundry: https://psalm.dev/r/7aa724d1ab Foundry is a lib which helps to create fixtures, mainly in Symfony's projects. we want to keep the I'm looking for a solution in our side: maybe by creating a Psalm's plugin ? that's how we've resolved the problem with PHPStan, but I didn't managed to find the solution with Psalm. Thank you for your help :) |
Replies: 5 comments 2 replies
By that do you mean that you can't know in which class that annotation will be? Otherwise, I would have suggested to try stubbing the class, but if you don't have control over it, this possibility is out |
|
Hi, thanks for your answer no, we don't know the class where is the annotation, all we know is that the class extends our abstract class I think stubs are not an option since there could be dozens of children of |
|
Indeed. So yeah, plugins may be the solution. I believe AfterClassLikeVisitInterface could be the solution, you'll have to retrieve the class storage then method storage to change those. Beware, this plugin is called only when populating cache (which means you'll have to use --no-cache during development) |
|
thanks a lot @orklah for this hint, I'm gonna test this in few days, and let you know :) |
|
Hi @orklah let's take a precise case: /**
* @template T of object
*/
abstract class Factory
{
/**
* @return Proxy<T>
*/
final public static function find($criteria): Proxyin the child class (in userland) here is how it is described: /**
* @extends Factory<Post>
*
* @method static Post|Proxy find(object|array|mixed $criteria)
*/
final class PostFactory extends FactoryPsalm reports the following error: ERROR: ImplementedReturnTypeMismatch - path/to/PostFactory.php:16:19 - The inherited return type 'Zenstruck\Foundry\Proxy<Zenstruck\Foundry\Tests\Fixtures\Entity\Post>' for Zenstruck\Foundry\Factory::find is different to the implemented return type for Zenstruck\Foundry\Factory::find 'Zenstruck\Foundry\Proxy|Zenstruck\Foundry\Tests\Fixtures\Entity\Post'seems legit: the parent returns a generic type, but the child returns an union type. By playing around with final class AfterClassLikeVisit implements AfterClassLikeVisitInterface
{
public static function afterClassLikeVisit(AfterClassLikeVisitEvent $event)
{
if (is_a($event->getStorage()->name, Factory::class, true)) {
foreach ($event->getStorage()->methods as $method) {
if ($method->cased_name === 'find') {
// what should I modify here?
}
}
}
}
}I've tried several things like that, but it's not working: $method->return_type = $method->signature_return_type = new Type\Union(
[
new Type\Atomic\TGenericObject(
Proxy::class,
[new Type\Union([new Type\Atomic\TNamedObject(Post::class)])]
),
]
);I also tried When I dump the whole The thanks for your help! |
If you're trying to acces
@method, I think they're in here instead:psalm/src/Psalm/Storage/ClassLikeStorage.php
Line 242 in 086b943
I think emptying that entire property should be enough to make Psalm be unaware of any
@methodon this class