psalm / psalm-plugin-doctrine

Stubs to let Psalm understand Doctrine better
86 stars 43 forks source link

Parsing of entity annotations/attributes to determine repository class #98

Open boesing opened 2 years ago

boesing commented 2 years ago

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.

weirdan commented 2 years ago

Doesn't Doctrine compile those annotations to some machine-readable readable format? I guess it would be easier to work with that (with automatic recompilation, if necessary) instead of replicating the parsing / interpretation of annotations.

weirdan commented 2 years ago

I had this idea when I started this plugin, but I stopped being a Doctrine user before I got to that.

boesing commented 2 years ago

It does when the metadata cache is activated (which is usually not the case in dev environments). So actually, there is no machine-readable format for the annotations unless you are in a production environment with warmed-up metadata.

weirdan commented 2 years ago

It does when the metadata cache is activated (which is usually not the case in dev environments).

If there's a standard way to invoke it the plugin could do that at startup.

boesing commented 2 years ago

Well, I think we can use the doctrine code to generate metadata for a single file but I am unsure if that works for any edge-case. Usually, doctrine entities are provided by some kind of "entity map" which contains glob paths to point to directories with entities.

I wonder if going with nikic/php-parser (for attributes) and the phpdoc parser (for annotations) would be a more static way than executing code while analyzing?

jrcii commented 1 year ago

If you're using Doctrine attributes on your entities this gives you the repo class based on the entity:

$reflection      = new ReflectionClass($entityClass);
$attribute       = $reflection->getAttributes(Entity::class);
$repositoryClass = $attribute[0]->getArguments()['repositoryClass'];

If anyone is more familiar with Psalm plugin dev maybe they could update this https://github.com/runtothefather/doctrine-psalm-plugin to use this method too?

Ocramius commented 3 months ago

Currently looking at this to work on https://github.com/vimeo/psalm/issues/10896

My rough approach (not yet gotten anything concrete yet) is to do something like:


final class MarkEntityFieldsAsTaintSources implements AfterExpressionAnalysisInterface
{
    public static function afterExpressionAnalysis(AfterExpressionAnalysisEvent $event): ?bool
    {
        $propertyFetchCandidate = $event->getExpr();

        if (! $propertyFetchCandidate instanceof PropertyFetch) {
            return null;
        }

        $statementsSource = $event->getStatementsSource();
        $typeProvider = $statementsSource->getNodeTypeProvider();
        $entityType = $typeProvider->getType($propertyFetchCandidate->var);

        if (null === $entityType) {
            return null;
        }

        // extract atomic type from entity manager here
        $entityType->getAtomicTypes() // @TODO