diff --git a/Makefile b/Makefile index bc09babb..45aabda4 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,6 @@ cs-fix: phpstan: php vendor/bin/phpstan analyse -l 8 -c phpstan.neon src tests -.PHONY: phpstan-generate-baseline +.PHONY: phpstan-generate-baselmake ine phpstan-generate-baseline: php vendor/bin/phpstan analyse -l 8 -c phpstan.neon src tests -b phpstan-baseline.neon diff --git a/src/Type/Doctrine/CreateQueryDynamicReturnTypeExtension.php b/src/Type/Doctrine/CreateQueryDynamicReturnTypeExtension.php index 6384f718..91265e0b 100644 --- a/src/Type/Doctrine/CreateQueryDynamicReturnTypeExtension.php +++ b/src/Type/Doctrine/CreateQueryDynamicReturnTypeExtension.php @@ -84,6 +84,7 @@ public function getTypeFromMethodCall( $typeBuilder = new QueryResultTypeBuilder(); try { + /** @var Query $query */ $query = $em->createQuery($queryString); QueryResultTypeWalker::walk($query, $typeBuilder, $this->descriptorRegistry); } catch (ORMException | DBALException | NewDBALException | CommonException $e) { diff --git a/src/Type/Doctrine/Query/QueryResultTypeWalker.php b/src/Type/Doctrine/Query/QueryResultTypeWalker.php index 5517cb1e..6fb5db6a 100644 --- a/src/Type/Doctrine/Query/QueryResultTypeWalker.php +++ b/src/Type/Doctrine/Query/QueryResultTypeWalker.php @@ -79,7 +79,7 @@ class QueryResultTypeWalker extends SqlWalker */ private $newObjectCounter = 0; - /** @var Query */ + /** @var Query */ private $query; /** @var EntityManagerInterface */ @@ -108,7 +108,7 @@ class QueryResultTypeWalker extends SqlWalker private $hasGroupByClause; /** - * @param Query $query + * @param Query $query */ public static function walk(Query $query, QueryResultTypeBuilder $typeBuilder, DescriptorRegistry $descriptorRegistry): void { @@ -123,7 +123,7 @@ public static function walk(Query $query, QueryResultTypeBuilder $typeBuilder, D /** * {@inheritDoc} * - * @param Query $query + * @param Query $query * @param ParserResult $parserResult * @param array $queryComponents */ diff --git a/src/Type/Doctrine/QueryBuilder/QueryBuilderGetQueryDynamicReturnTypeExtension.php b/src/Type/Doctrine/QueryBuilder/QueryBuilderGetQueryDynamicReturnTypeExtension.php index c828411f..ffb15410 100644 --- a/src/Type/Doctrine/QueryBuilder/QueryBuilderGetQueryDynamicReturnTypeExtension.php +++ b/src/Type/Doctrine/QueryBuilder/QueryBuilderGetQueryDynamicReturnTypeExtension.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\DBALException; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\ORMException; +use Doctrine\ORM\Query; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Identifier; use PHPStan\Analyser\Scope; @@ -159,6 +160,7 @@ private function getQueryType(string $dql): Type $typeBuilder = new QueryResultTypeBuilder(); try { + /** @var Query $query */ $query = $em->createQuery($dql); QueryResultTypeWalker::walk($query, $typeBuilder, $this->descriptorRegistry); } catch (ORMException | DBALException | CommonException $e) { diff --git a/stubs/ORM/Query.stub b/stubs/ORM/Query.stub index d3610bb7..ce9b2964 100644 --- a/stubs/ORM/Query.stub +++ b/stubs/ORM/Query.stub @@ -3,10 +3,24 @@ namespace Doctrine\ORM; /** + * @template TKey as array-key * @template TResult The type of results returned by this query in HYDRATE_OBJECT mode * * @extends AbstractQuery */ final class Query extends AbstractQuery { + public const HYDRATE_OBJECT = 1; + + /** + * @param int|string $hydrationMode + * + * @return ($hydrationMode is self::HYDRATE_OBJECT + * ? array + * : mixed + * ) + */ + public function getResult($hydrationMode = self::HYDRATE_OBJECT) + { + } } diff --git a/stubs/ORM/QueryBuilder.stub b/stubs/ORM/QueryBuilder.stub index db14c5b2..f36db111 100644 --- a/stubs/ORM/QueryBuilder.stub +++ b/stubs/ORM/QueryBuilder.stub @@ -15,7 +15,7 @@ class QueryBuilder } /** - * @return Query + * @return Query */ public function getQuery() { diff --git a/stubs/bleedingEdge/ORM/QueryBuilder.stub b/stubs/bleedingEdge/ORM/QueryBuilder.stub index 9fb03cff..647b8ccc 100644 --- a/stubs/bleedingEdge/ORM/QueryBuilder.stub +++ b/stubs/bleedingEdge/ORM/QueryBuilder.stub @@ -8,7 +8,7 @@ class QueryBuilder { /** - * @return Query + * @return Query */ public function getQuery() { @@ -143,7 +143,7 @@ class QueryBuilder { } - + /** * @param literal-string|object|array $predicates * @return $this diff --git a/tests/Type/Doctrine/Query/QueryResultTypeWalkerTest.php b/tests/Type/Doctrine/Query/QueryResultTypeWalkerTest.php index a6b59762..b9884504 100644 --- a/tests/Type/Doctrine/Query/QueryResultTypeWalkerTest.php +++ b/tests/Type/Doctrine/Query/QueryResultTypeWalkerTest.php @@ -8,6 +8,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Query; use Doctrine\ORM\Query\AST\TypedExpression; use Doctrine\ORM\Tools\SchemaTool; use PHPStan\Testing\PHPStanTestCase; @@ -190,6 +191,7 @@ public function test(Type $expectedType, string $dql, ?string $expectedException { $em = self::$em; + /** @var Query $query */ $query = $em->createQuery($dql); $typeBuilder = new QueryResultTypeBuilder(); diff --git a/tests/Type/Doctrine/data/QueryResult/queryBuilderGetQuery.php b/tests/Type/Doctrine/data/QueryResult/queryBuilderGetQuery.php index 000f9d7e..8944aa7b 100644 --- a/tests/Type/Doctrine/data/QueryResult/queryBuilderGetQuery.php +++ b/tests/Type/Doctrine/data/QueryResult/queryBuilderGetQuery.php @@ -49,7 +49,7 @@ public function testQueryResultTypeIsMixedWhenDQLIsNotKnown(QueryBuilder $builde { $query = $builder->getQuery(); - assertType('Doctrine\ORM\Query', $query); + assertType('Doctrine\ORM\Query<(int|string), mixed>', $query); } public function testQueryResultTypeIsMixedWhenDQLIsInvalid(EntityManagerInterface $em): void diff --git a/tests/Type/Doctrine/data/QueryResult/queryResult.php b/tests/Type/Doctrine/data/QueryResult/queryResult.php index 3a1e144e..4b237e37 100644 --- a/tests/Type/Doctrine/data/QueryResult/queryResult.php +++ b/tests/Type/Doctrine/data/QueryResult/queryResult.php @@ -232,36 +232,36 @@ public function testReturnTypeOfQueryMethodsWithExplicitNonConstantHydrationMode * Test that we return the original return type when ResultType may be * VoidType * - * @param Query $query + * @param Query $query */ public function testReturnTypeOfQueryMethodsWithReturnTypeIsMixed(EntityManagerInterface $em, Query $query): void { assertType( - 'mixed', + 'array<(int|string)>', $query->getResult(AbstractQuery::HYDRATE_OBJECT) ); assertType( - 'iterable', + 'iterable<(int|string)>', $query->toIterable([], AbstractQuery::HYDRATE_OBJECT) ); assertType( - 'mixed', + 'array<(int|string)>', $query->execute(null, AbstractQuery::HYDRATE_OBJECT) ); assertType( - 'mixed', + 'array<(int|string)>', $query->executeIgnoreQueryCache(null, AbstractQuery::HYDRATE_OBJECT) ); assertType( - 'mixed', + 'array<(int|string)>', $query->executeUsingQueryCache(null, AbstractQuery::HYDRATE_OBJECT) ); assertType( - 'mixed', + '(int|string)', $query->getSingleResult(AbstractQuery::HYDRATE_OBJECT) ); assertType( - 'mixed', + 'int|string|null', $query->getOneOrNullResult(AbstractQuery::HYDRATE_OBJECT) ); }