Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Doctrine via stubbed templates #849

Closed
muglug opened this issue Jun 29, 2018 · 11 comments
Closed

Support Doctrine via stubbed templates #849

muglug opened this issue Jun 29, 2018 · 11 comments
Milestone

Comments

@muglug
Copy link
Collaborator

muglug commented Jun 29, 2018

<?php
namespace Doctrine\ORM {
    class EntityManager {
        /**
         * @template T
         * @template-typeof T $class_name
         * @return EntityRepository<T>
         */
        public function getRepository(string $class_name) {}
    }

    /**
     * @template T as object
     */
    class EntityRepository {
        /**
         * Finds an entity by its primary key / identifier.
         *
         * @param mixed    $id          The identifier.
         * @param int|null $lockMode    One of the \Doctrine\DBAL\LockMode::* constants
         *                              or NULL if no specific lock mode should be used
         *                              during the search.
         * @param int|null $lockVersion The lock version.
         *
         * @return T|null The entity instance or NULL if the entity can not be found.
         */
        public function find($id, $lockMode = null, $lockVersion = null)
        {
            return $this->_em->find($this->_entityName, $id, $lockMode, $lockVersion);
        }

        /**
         * Finds all entities in the repository.
         *
         * @return T[] The entities.
         */
        public function findAll()
        {
            return $this->findBy([]);
        }

        /**
         * Finds entities by a set of criteria.
         *
         * @param array      $criteria
         * @param array|null $orderBy
         * @param int|null   $limit
         * @param int|null   $offset
         *
         * @return T[] The objects.
         */
        public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
        {
            $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);

            return $persister->loadAll($criteria, $orderBy, $limit, $offset);
        }

        /**
         * Finds a single entity by a set of criteria.
         *
         * @param array      $criteria
         * @param array|null $orderBy
         *
         * @return T|null The entity instance or NULL if the entity can not be found.
         */
        public function findOneBy(array $criteria, array $orderBy = null)
        {
            $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);

            return $persister->load($criteria, null, null, [], null, 1, $orderBy);
        }
    }
}

namespace Doctrine\Common\Collections {
    /**
     * @template T
     */
    interface Collection extends Countable, IteratorAggregate, ArrayAccess
    {
        /**
         * Checks whether an element is contained in the collection.
         * This is an O(n) operation, where n is the size of the collection.
         *
         * @param T $element The element to search for.
         *
         * @return bool TRUE if the collection contains the element, FALSE otherwise.
         */
        public function contains($element);

        /**
         * Removes the element at the specified index from the collection.
         *
         * @param string|int $key The kex/index of the element to remove.
         *
         * @return T|null The removed element or NULL, if the collection did not contain the element.
         */
        public function remove($key);

        /**
         * Removes the specified element from the collection, if it is found.
         *
         * @param T $element The element to remove.
         *
         * @return bool TRUE if this collection contained the specified element, FALSE otherwise.
         */
        public function removeElement($element);

        /**
         * Gets the element at the specified key/index.
         *
         * @param string|int $key The key/index of the element to retrieve.
         *
         * @return T
         */
        public function get($key);

        /**
         * Gets all values of the collection.
         *
         * @return T[] The values of all elements in the collection, in the order they
         *               appear in the collection.
         */
        public function getValues();

        /**
         * Sets an element in the collection at the specified key/index.
         *
         * @param string|int $key   The key/index of the element to set.
         * @param T      $value The element to set.
         *
         * @return void
         */
        public function set($key, $value);

        /**
         * Gets a native PHP array representation of the collection.
         *
         * @return T[]
         */
        public function toArray();

        /**
         * Sets the internal iterator to the first element in the collection and returns this element.
         *
         * @return T
         */
        public function first();

        /**
         * Sets the internal iterator to the last element in the collection and returns this element.
         *
         * @return T
         */
        public function last();

        /**
         * Gets the element of the collection at the current iterator position.
         *
         * @return T
         */
        public function current();

        /**
         * Moves the internal iterator position to the next element and returns this element.
         *
         * @return T
         */
        public function next();

        /**
         * Partitions this collection in two collections according to a predicate.
         * Keys are preserved in the resulting collections.
         *
         * @param Closure $p The predicate on which to partition.
         *
         * @return Collection<T>[] An array with two elements. The first element contains the collection
         *                      of elements where the predicate returned TRUE, the second element
         *                      contains the collection of elements where the predicate returned FALSE.
         */
        public function partition(Closure $p);

        /**
         * Gets the index/key of a given element. The comparison of two elements is strict,
         * that means not only the value but also the type must match.
         * For objects this means reference equality.
         *
         * @param T $element The element to search for.
         *
         * @return int|string|bool The key/index of the element or FALSE if the element was not found.
         */
        public function indexOf($element);

        /**
         * Extracts a slice of $length elements starting at position $offset from the Collection.
         *
         * If $length is null it returns all elements from $offset to the end of the Collection.
         * Keys have to be preserved by this method. Calling this method will only return the
         * selected slice and NOT change the elements contained in the collection slice is called on.
         *
         * @param int      $offset The offset to start from.
         * @param int|null $length The maximum number of elements to return, or null for no limit.
         *
         * @return T[]
         */
        public function slice($offset, $length = null);
    }
}

Partial stubs like this should be importable into a given project by including the package via composer.

@dkarlovi
Copy link
Contributor

Also findBy() and findOneBy(): https://github.com/doctrine/common/blob/2.8/lib/Doctrine/Common/Persistence/ObjectRepository.php

@weirdan
Copy link
Collaborator

weirdan commented Jun 29, 2018

That would be immensely useful, especially being able to partially stub things. We have some stubs for Doctrine Collections and a couple of other libraries, it would be nice to have a way to distribute them.

@muglug
Copy link
Collaborator Author

muglug commented Jun 30, 2018

I've updated the stubs above to one that I've got working. Unfortunately I don't have a codebase that uses Doctrine ORM to test against - any suggestions?

Also @weirdan if you could post those stubs to a new repo, you could require that repo via composer and include a ref to the vendor/.../stubs.php file in your psalm config.

@muglug
Copy link
Collaborator Author

muglug commented Jun 30, 2018

I think the best thing is to require each extension repo have a stubs.php file in the root directory (which itself can require other files)

@weirdan
Copy link
Collaborator

weirdan commented Jul 1, 2018

For me, relying on the file paths is a problematic part (due to the particular setup we use, but also in general), so I'd like to relegate as much of the file structure heavy-lifting to composer. Which means I'd like to see plugins addressed by namespace/classname, not by file path.

If you're open to this idea I can draft up a kind of proposal the following week.

@muglug
Copy link
Collaborator Author

muglug commented Jul 1, 2018

@weirdan absolutely. The only thing I was thinking is that it I'd want to provide an easy way to disable extensions/plugins, which is cumbersome if you have to do it via Composer.

I was thinking something like

<extensions>
    <directory name="vendor/muglug/psalm-doctrine-ext" />
</extensions>

You may also composer require a project that itself composer requires a given Psalm extension in composer, but you don't want Psalm to use it when analysing your own code.

@weirdan
Copy link
Collaborator

weirdan commented Jul 1, 2018

The only thing I was thinking is that it I'd want to provide an easy way to disable extensions/plugins,

Sure, it's on my todo.

I was thinking something like <directory name="vendor/...."/>

That's file path, and that's what I'd like to avoid. The approach I'm working on wouldn't require any file paths (but PoC would be a bit tied to composer infrastructure, with an option to unbind it later).

You may also composer require a project that itself composer requires a given Psalm extension in composer, but you don't want Psalm to use it when analysing your own code.

It's likely to be dev-required (rather than required), and composer does not install dev-dependencies of your dependencies. Still, it's a valid point, and would be addressed.

@muglug
Copy link
Collaborator Author

muglug commented Jul 1, 2018

Still, it's a valid point, and would be addressed.

Brilliant! If you can address that, then I'm happy relying on composer. I was thinking that each package would add a registration script into autoload_files, but that'd have to be a short easy snippet.

@weirdan weirdan mentioned this issue Jul 2, 2018
9 tasks
@muglug muglug added this to the v3.0 milestone Nov 17, 2018
@muglug
Copy link
Collaborator Author

muglug commented Nov 17, 2018

@weirdan is this done in your own plugin?

@weirdan
Copy link
Collaborator

weirdan commented Nov 17, 2018

Mostly. I don't have EntityManager there, but considered adding that (and renaming to psalm-doctrine). I plan to get back to it the week after next, when I'm back in the office.

@muglug
Copy link
Collaborator Author

muglug commented Dec 9, 2018

Thanks!

@muglug muglug closed this as completed Dec 9, 2018
kkmuffme added a commit to kkmuffme/psalm that referenced this issue Nov 15, 2023
…s this didn't work correctly and lead to errors not being reported at all in many cases (since the error was reported for the stubs file and therefore suppressed)

With the previous commit "Fix for classes what vimeo#8503 fixed for functions", the stubs of classes where the actual file is in the analyzed files are ignored completely.
kkmuffme added a commit to kkmuffme/psalm that referenced this issue Nov 15, 2023
…s this didn't work correctly and lead to errors not being reported at all in many cases (since the error was reported for the stubs file and therefore suppressed)

With the previous commit "Fix for classes what vimeo#8503 fixed for functions", the stubs of classes where the actual file is in the analyzed files are ignored completely.
kkmuffme added a commit to kkmuffme/psalm that referenced this issue Nov 16, 2023
…s this didn't work correctly and lead to errors not being reported at all in many cases (since the error was reported for the stubs file and therefore suppressed)

With the previous commit "Fix for classes what vimeo#8503 fixed for functions", the stubs of classes where the actual file is in the analyzed files are ignored completely.
kkmuffme added a commit to kkmuffme/psalm that referenced this issue Nov 16, 2023
…s this didn't work correctly and lead to errors not being reported at all in many cases (since the error was reported for the stubs file and therefore suppressed)

With the previous commit "Fix for classes what vimeo#8503 fixed for functions", the stubs of classes where the actual file is in the analyzed files are ignored completely.
kkmuffme added a commit to kkmuffme/psalm that referenced this issue Nov 16, 2023
…s this didn't work correctly and lead to errors not being reported at all in many cases (since the error was reported for the stubs file and therefore suppressed)

With the previous commit "Fix for classes what vimeo#8503 fixed for functions", the stubs of classes where the actual file is in the analyzed files are ignored completely.
kkmuffme added a commit to kkmuffme/psalm that referenced this issue Nov 16, 2023
…s this didn't work correctly and lead to errors not being reported at all in many cases (since the error was reported for the stubs file and therefore suppressed)

With the previous commit "Fix for classes what vimeo#8503 fixed for functions", the stubs of classes where the actual file is in the analyzed files are ignored completely.
kkmuffme added a commit to kkmuffme/psalm that referenced this issue Nov 18, 2023
…s this didn't work correctly and lead to errors not being reported at all in many cases (since the error was reported for the stubs file and therefore suppressed)

With the previous commit "Fix for classes what vimeo#8503 fixed for functions", the stubs of classes where the actual file is in the analyzed files are ignored completely.
kkmuffme added a commit to kkmuffme/psalm that referenced this issue Nov 18, 2023
…s this didn't work correctly and lead to errors not being reported at all in many cases (since the error was reported for the stubs file and therefore suppressed)

With the previous commit "Fix for classes what vimeo#8503 fixed for functions", the stubs of classes where the actual file is in the analyzed files are ignored completely.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants