Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
409 changes: 409 additions & 0 deletions .phpstan-dba-mysqli.cache

Large diffs are not rendered by default.

96 changes: 95 additions & 1 deletion src/DoctrineReflection/DoctrineReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace staabm\PHPStanDba\DoctrineReflection;

use Doctrine\DBAL\Result;
use Doctrine\DBAL\Statement;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\ArrayType;
use PHPStan\Type\Constant\ConstantArrayType;
Expand All @@ -16,12 +18,13 @@
use PHPStan\Type\IntegerType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use staabm\PHPStanDba\QueryReflection\QueryReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflector;
use Traversable;

final class DoctrineReflection
{
public function fetchResultType(MethodReflection $methodReflection, Type $resultRowType): ?Type
public function reduceResultType(MethodReflection $methodReflection, Type $resultRowType): ?Type
{
$usedMethod = strtolower($methodReflection->getName());

Expand Down Expand Up @@ -107,4 +110,95 @@ public function fetchResultType(MethodReflection $methodReflection, Type $result

return null;
}

/**
* @param iterable<string> $queryStrings
* @param QueryReflector::FETCH_TYPE* $reflectionFetchType
*/
public function createGenericStatement(iterable $queryStrings, int $reflectionFetchType): ?Type
{
$genericObjects = [];

foreach ($queryStrings as $queryString) {
$queryReflection = new QueryReflection();

$resultType = $queryReflection->getResultType($queryString, $reflectionFetchType);
if (null === $resultType) {
return null;
}

$genericObjects[] = new GenericObjectType(Statement::class, [$resultType]);
}

if (\count($genericObjects) > 1) {
return TypeCombinator::union(...$genericObjects);
}
if (1 === \count($genericObjects)) {
return $genericObjects[0];
}

return null;
}

/**
* @param iterable<string> $queryStrings
* @param QueryReflector::FETCH_TYPE* $reflectionFetchType
*/
public function createGenericResult(iterable $queryStrings, int $reflectionFetchType): ?Type
{
$genericObjects = [];

foreach ($queryStrings as $queryString) {
$queryReflection = new QueryReflection();

$resultType = $queryReflection->getResultType($queryString, $reflectionFetchType);
if (null === $resultType) {
return null;
}

$genericObjects[] = new GenericObjectType(Result::class, [$resultType]);
}

if (\count($genericObjects) > 1) {
return TypeCombinator::union(...$genericObjects);
}
if (1 === \count($genericObjects)) {
return $genericObjects[0];
}

return null;
}

/**
* @param iterable<string> $queryStrings
*/
public function createFetchType(iterable $queryStrings, MethodReflection $methodReflection): ?Type
{
$queryReflection = new QueryReflection();

$fetchTypes = [];
foreach ($queryStrings as $queryString) {
$resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_BOTH);

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

$fetchResultType = $this->reduceResultType($methodReflection, $resultType);
if (null === $fetchResultType) {
return null;
}

$fetchTypes[] = $fetchResultType;
}

if (\count($fetchTypes) > 1) {
return TypeCombinator::union(...$fetchTypes);
}
if (1 === \count($fetchTypes)) {
return $fetchTypes[0];
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
use Composer\InstalledVersions;
use Composer\Semver\VersionParser;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Result;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use staabm\PHPStanDba\DoctrineReflection\DoctrineReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflector;

Expand Down Expand Up @@ -71,25 +70,16 @@ private function inferType(Expr $queryExpr, ?Expr $paramsExpr, Scope $scope): ?T
{
if (null === $paramsExpr) {
$queryReflection = new QueryReflection();
$queryString = $queryReflection->resolveQueryString($queryExpr, $scope);
if (null === $queryString) {
return null;
}
$queryStrings = $queryReflection->resolveQueryStrings($queryExpr, $scope);
} else {
$parameterTypes = $scope->getType($paramsExpr);

$queryReflection = new QueryReflection();
$queryString = $queryReflection->resolvePreparedQueryString($queryExpr, $parameterTypes, $scope);
if (null === $queryString) {
return null;
}
$queryStrings = $queryReflection->resolvePreparedQueryStrings($queryExpr, $parameterTypes, $scope);
}

$resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_BOTH);
if ($resultType) {
return new GenericObjectType(Result::class, [$resultType]);
}
$doctrineReflection = new DoctrineReflection();

return null;
return $doctrineReflection->createGenericResult($queryStrings, QueryReflector::FETCH_TYPE_BOTH);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
use PHPStan\Type\Type;
use staabm\PHPStanDba\DoctrineReflection\DoctrineReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflector;

final class DoctrineConnectionFetchDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
{
Expand Down Expand Up @@ -82,33 +81,16 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method

private function inferType(MethodReflection $methodReflection, Expr $queryExpr, ?Expr $paramsExpr, Scope $scope): ?Type
{
$queryReflection = new QueryReflection();
$doctrineReflection = new DoctrineReflection();

if (null === $paramsExpr) {
$queryReflection = new QueryReflection();
$queryString = $queryReflection->resolveQueryString($queryExpr, $scope);
if (null === $queryString) {
return null;
}
$queryString = $queryReflection->resolveQueryStrings($queryExpr, $scope);
} else {
$parameterTypes = $scope->getType($paramsExpr);

$queryReflection = new QueryReflection();
$queryString = $queryReflection->resolvePreparedQueryString($queryExpr, $parameterTypes, $scope);
if (null === $queryString) {
return null;
}
}

$resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_BOTH);

if ($resultType) {
$doctrineReflection = new DoctrineReflection();
$fetchResultType = $doctrineReflection->fetchResultType($methodReflection, $resultType);

if (null !== $fetchResultType) {
return $fetchResultType;
}
$queryString = $queryReflection->resolvePreparedQueryStrings($queryExpr, $parameterTypes, $scope);
}

return null;
return $doctrineReflection->createFetchType($queryString, $methodReflection);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
use Composer\InstalledVersions;
use Composer\Semver\VersionParser;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Statement;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use staabm\PHPStanDba\DoctrineReflection\DoctrineReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflector;

Expand Down Expand Up @@ -65,16 +64,10 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method
private function inferType(Expr $queryExpr, Scope $scope): ?Type
{
$queryReflection = new QueryReflection();
$queryString = $queryReflection->resolveQueryString($queryExpr, $scope);
if (null === $queryString) {
return null;
}
$queryStrings = $queryReflection->resolveQueryStrings($queryExpr, $scope);

$resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_BOTH);
if ($resultType) {
return new GenericObjectType(Statement::class, [$resultType]);
}
$doctrineReflection = new DoctrineReflection();

return null;
return $doctrineReflection->createGenericStatement($queryStrings, QueryReflector::FETCH_TYPE_BOTH);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
use Composer\InstalledVersions;
use Composer\Semver\VersionParser;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Result;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use staabm\PHPStanDba\DoctrineReflection\DoctrineReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflector;

Expand Down Expand Up @@ -65,16 +64,10 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method
private function inferType(Expr $queryExpr, Scope $scope): ?Type
{
$queryReflection = new QueryReflection();
$queryString = $queryReflection->resolveQueryString($queryExpr, $scope);
if (null === $queryString) {
return null;
}
$queryStrings = $queryReflection->resolveQueryStrings($queryExpr, $scope);

$resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_BOTH);
if ($resultType) {
return new GenericObjectType(Result::class, [$resultType]);
}
$doctrineReflection = new DoctrineReflection();

return null;
return $doctrineReflection->createGenericResult($queryStrings, QueryReflector::FETCH_TYPE_BOTH);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method
}

$doctrineReflection = new DoctrineReflection();
$fetchResultType = $doctrineReflection->fetchResultType($methodReflection, $resultRowType);
$fetchResultType = $doctrineReflection->reduceResultType($methodReflection, $resultRowType);
if (null !== $fetchResultType) {
return $fetchResultType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@

use Composer\InstalledVersions;
use Composer\Semver\VersionParser;
use Doctrine\DBAL\Result;
use Doctrine\DBAL\Statement;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\Type;
use staabm\PHPStanDba\DoctrineReflection\DoctrineReflection;
use staabm\PHPStanDba\PdoReflection\PdoStatementReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflection;
use staabm\PHPStanDba\QueryReflection\QueryReflector;
Expand Down Expand Up @@ -60,6 +59,8 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method

private function inferType(MethodReflection $methodReflection, MethodCall $methodCall, Expr $paramsExpr, Scope $scope): ?Type
{
$doctrineReflection = new DoctrineReflection();

$parameterTypes = $scope->getType($paramsExpr);

$stmtReflection = new PdoStatementReflection();
Expand All @@ -69,16 +70,8 @@ private function inferType(MethodReflection $methodReflection, MethodCall $metho
}

$queryReflection = new QueryReflection();
$queryString = $queryReflection->resolvePreparedQueryString($queryExpr, $parameterTypes, $scope);
if (null === $queryString) {
return null;
}

$resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_BOTH);
if ($resultType) {
return new GenericObjectType(Result::class, [$resultType]);
}
$queryStrings = $queryReflection->resolvePreparedQueryStrings($queryExpr, $parameterTypes, $scope);

return null;
return $doctrineReflection->createGenericResult($queryStrings, QueryReflector::FETCH_TYPE_BOTH);
}
}
Loading