diff --git a/src/Type/Doctrine/QueryBuilder/ReturnQueryBuilderExpressionTypeResolverExtension.php b/src/Type/Doctrine/QueryBuilder/ReturnQueryBuilderExpressionTypeResolverExtension.php index ea4f8bcb..288f68a0 100644 --- a/src/Type/Doctrine/QueryBuilder/ReturnQueryBuilderExpressionTypeResolverExtension.php +++ b/src/Type/Doctrine/QueryBuilder/ReturnQueryBuilderExpressionTypeResolverExtension.php @@ -48,9 +48,22 @@ public function getType(Expr $expr, Scope $scope): ?Type return null; } - $returnType = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $methodReflection->getVariants())->getReturnType(); + $queryBuilderType = new ObjectType(QueryBuilder::class); + $variants = $methodReflection->getVariants(); + $canReturnQueryBuilder = false; + foreach ($variants as $variant) { + if (!$queryBuilderType->isSuperTypeOf($variant->getReturnType())->no()) { + $canReturnQueryBuilder = true; + break; + } + } + if (!$canReturnQueryBuilder) { + return null; + } + + $returnType = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $variants)->getReturnType(); - $returnsQueryBuilder = (new ObjectType(QueryBuilder::class))->isSuperTypeOf($returnType)->yes(); + $returnsQueryBuilder = $queryBuilderType->isSuperTypeOf($returnType)->yes(); if (!$returnsQueryBuilder) { return null; diff --git a/tests/Type/Doctrine/data/QueryResult/queryBuilderExpressionTypeResolver.php b/tests/Type/Doctrine/data/QueryResult/queryBuilderExpressionTypeResolver.php index 2a6af1d9..e8a913a8 100644 --- a/tests/Type/Doctrine/data/QueryResult/queryBuilderExpressionTypeResolver.php +++ b/tests/Type/Doctrine/data/QueryResult/queryBuilderExpressionTypeResolver.php @@ -66,6 +66,11 @@ public function testFirstClassCallableDoesNotFail(EntityManagerInterface $em): v $this->getQueryBuilder(...); } + public function testNullableQueryBuilderIsNotInferred(EntityManagerInterface $em): void + { + assertType('Doctrine\\ORM\\QueryBuilder|null', $this->getNullableQueryBuilder($em)); + } + private function adjustQueryBuilderToIndexByInt(QueryBuilder $qb): void { $qb->indexBy('m', 'm.intColumn'); @@ -100,6 +105,13 @@ private static function getStaticQueryBuilder(EntityManagerInterface $em): Query ->from(Many::class, 'm'); } + private function getNullableQueryBuilder(EntityManagerInterface $em): ?QueryBuilder + { + return $em->createQueryBuilder() + ->select('m') + ->from(Many::class, 'm'); + } + private function getBranchingQueryBuilder(EntityManagerInterface $em): QueryBuilder { $queryBuilder = $em->createQueryBuilder()