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

PHPStan 2.0 support #709

Merged
merged 16 commits into from
Nov 17, 2024
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
17 changes: 16 additions & 1 deletion .phpstan-dba-mysqli.cache

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 4 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,19 @@
"composer-runtime-api": "^2.0",
"composer/semver": "^3.2",
"doctrine/dbal": "3.*",
"phpstan/phpstan": "^1.9.4"
"phpstan/phpstan": "^2.0"
},
"require-dev": {
"ext-mysqli": "*",
"ext-pdo": "*",
"dibi/dibi": "^4.2",
"php-parallel-lint/php-parallel-lint": "^1.4",
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^8.5|^9.5",
"symplify/easy-coding-standard": "^12.3",
"tomasvotruba/unused-public": "^1.0",
"vlucas/phpdotenv": "^5.4"
},
"conflict": {
Expand Down
66 changes: 43 additions & 23 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,80 +1,100 @@
parameters:
ignoreErrors:
-
message: "#^Unresolvable Query\\: Cannot resolve query with variable type\\: non\\-empty\\-string\\.$#"
message: '#^Unresolvable Query\: Cannot resolve query with variable type\: non\-empty\-string\.$#'
identifier: dba.unresolvableQuery
count: 2
path: src/Analyzer/QueryPlanAnalyzerMysql.php

-
message: """
#^Call to deprecated method resolveQueryString\\(\\) of class staabm\\\\PHPStanDba\\\\QueryReflection\\\\QueryReflection\\:
use resolveQueryStrings\\(\\) instead$#
"""
message: '''
#^Call to deprecated method resolveQueryString\(\) of class staabm\\PHPStanDba\\QueryReflection\\QueryReflection\:
use resolveQueryStrings\(\) instead$#
'''
identifier: method.deprecated
count: 1
path: src/Extensions/DeployerRunMysqlQueryDynamicReturnTypeExtension.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#"
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#'
identifier: phpstanApi.instanceofType
count: 2
path: src/Extensions/DibiConnectionFetchDynamicReturnTypeExtension.php

-
message: "#^Strict comparison using \\=\\=\\= between 'dibi' and 'dibi' will always evaluate to true\\.$#"
message: '#^Strict comparison using \=\=\= between ''dibi'' and ''dibi'' will always evaluate to true\.$#'
identifier: identical.alwaysTrue
count: 1
path: src/QueryReflection/DbaApi.php

-
message: """
#^Call to deprecated method resolvePreparedQueryString\\(\\) of class staabm\\\\PHPStanDba\\\\QueryReflection\\\\QueryReflection\\:
use resolvePreparedQueryStrings\\(\\) instead$#
"""
message: '''
#^Call to deprecated method resolvePreparedQueryString\(\) of class staabm\\PHPStanDba\\QueryReflection\\QueryReflection\:
use resolvePreparedQueryStrings\(\) instead$#
'''
identifier: method.deprecated
count: 1
path: src/QueryReflection/QueryReflection.php

-
message: "#^Casting to \\*NEVER\\* something that's already \\*NEVER\\*\\.$#"
message: '#^Casting to \*NEVER\* something that''s already \*NEVER\*\.$#'
identifier: cast.useless
count: 1
path: src/QueryReflection/QueryReflection.php

-
message: "#^Strict comparison using \\=\\=\\= between null and null will always evaluate to true\\.$#"
message: '#^Strict comparison using \=\=\= between null and null will always evaluate to true\.$#'
identifier: identical.alwaysTrue
count: 1
path: src/QueryReflection/QueryReflection.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#"
message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#'
identifier: phpstanApi.instanceofType
count: 1
path: src/QueryReflection/QuerySimulation.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#"
message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#'
identifier: phpstanApi.instanceofType
count: 1
path: src/QueryReflection/QuerySimulation.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#"
message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#'
identifier: phpstanApi.instanceofType
count: 2
path: src/QueryReflection/QuerySimulation.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#"
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#'
identifier: phpstanApi.instanceofType
count: 1
path: src/Rules/PdoStatementExecuteMethodRule.php

-
message: """
#^Call to deprecated method resolveQueryString\\(\\) of class staabm\\\\PHPStanDba\\\\QueryReflection\\\\QueryReflection\\:
use resolveQueryStrings\\(\\) instead$#
"""
message: '''
#^Call to deprecated method resolveQueryString\(\) of class staabm\\PHPStanDba\\QueryReflection\\QueryReflection\:
use resolveQueryStrings\(\) instead$#
'''
identifier: method.deprecated
count: 1
path: src/Rules/SyntaxErrorInDibiPreparedStatementMethodRule.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#"
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#'
identifier: phpstanApi.instanceofType
count: 1
path: src/Rules/SyntaxErrorInDibiPreparedStatementMethodRule.php

-
message: "#^Only booleans are allowed in an if condition, int given\\.$#"
message: '#^Parameter \#3 \$joinCondition of class staabm\\PHPStanDba\\SchemaReflection\\Join constructor expects SqlFtw\\Sql\\Expression\\RootNode, mixed given\.$#'
identifier: argument.type
count: 1
path: src/SqlAst/ParserInference.php

-
message: '#^Only booleans are allowed in an if condition, int given\.$#'
identifier: if.condNotBoolean
count: 1
path: src/TypeMapping/MysqliTypeMapper.php
7 changes: 2 additions & 5 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@ parameters:
bootstrapFiles:
- bootstrap.php

unused_public:
methods: true
properties: true
constants: true

reportUnmatchedIgnoredErrors: false

ignoreErrors:
-
message: '#.*so it can be removed from the return type.*#' # requires https://github.com/phpstan/phpstan/issues/10312
-
message: '#^Method staabm\\PHPStanDba\\DbSchema\\SchemaHasherMysql\:\:hashDb\(\) should return string but returns float\|int\|string\.$#'
path: src/DbSchema/SchemaHasherMysql.php
Expand Down
6 changes: 3 additions & 3 deletions src/DoctrineReflection/DoctrineResultObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Doctrine\DBAL\Result;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\IsSuperTypeOfResult;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;

Expand Down Expand Up @@ -51,10 +51,10 @@ public function equals(Type $type): bool
return parent::equals($type);
}

public function isSuperTypeOf(Type $type): TrinaryLogic
public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
{
if ($type instanceof self) {
return TrinaryLogic::createFromBoolean(
return IsSuperTypeOfResult::createFromBoolean(
$type->rowType !== null
&& $this->rowType !== null
&& $type->rowType->equals($this->rowType)
Expand Down
6 changes: 3 additions & 3 deletions src/DoctrineReflection/DoctrineStatementObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Doctrine\DBAL\Statement;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\IsSuperTypeOfResult;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;

Expand Down Expand Up @@ -51,10 +51,10 @@ public function equals(Type $type): bool
return parent::equals($type);
}

public function isSuperTypeOf(Type $type): TrinaryLogic
public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
{
if ($type instanceof self) {
return TrinaryLogic::createFromBoolean(
return IsSuperTypeOfResult::createFromBoolean(
$type->rowType !== null
&& $this->rowType !== null
&& $type->rowType->equals($this->rowType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private function reduceResultType(MethodReflection $methodReflection, Type $resu
if ('fetch' === $methodName) {
return TypeCombinator::addNull($resultType);
} elseif ('fetchAll' === $methodName) {
return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $resultType));
return TypeCombinator::intersect(new ArrayType(new IntegerType(), $resultType), new AccessoryArrayListType());
} elseif ('fetchPairs' === $methodName && $resultType instanceof ConstantArrayType && 2 === \count($resultType->getValueTypes())) {
return new ArrayType($resultType->getValueTypes()[0], $resultType->getValueTypes()[1]);
} elseif ('fetchSingle' === $methodName && $resultType instanceof ConstantArrayType && 1 === \count($resultType->getValueTypes())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function specifyTypes(MethodReflection $methodReflection, MethodCall $nod
}

if (null !== $inferredType) {
return $this->typeSpecifier->create($methodCall->var, $inferredType, TypeSpecifierContext::createTruthy(), true);
return $this->typeSpecifier->create($methodCall->var, $inferredType, TypeSpecifierContext::createTruthy(), $scope)->setAlwaysOverwriteTypes();
}

return new SpecifiedTypes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function specifyTypes(MethodReflection $methodReflection, MethodCall $nod
$reducedType = $this->reduceType($methodCall, $statementType, $scope);

if (null !== $reducedType) {
return $this->typeSpecifier->create($methodCall->var, $reducedType, TypeSpecifierContext::createTruthy(), true);
return $this->typeSpecifier->create($methodCall->var, $reducedType, TypeSpecifierContext::createTruthy(), $scope)->setAlwaysOverwriteTypes();
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/MysqliReflection/MysqliResultObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace staabm\PHPStanDba\MysqliReflection;

use PHPStan\TrinaryLogic;
use PHPStan\Type\IsSuperTypeOfResult;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;

Expand Down Expand Up @@ -40,10 +40,10 @@ public function equals(Type $type): bool
return parent::equals($type);
}

public function isSuperTypeOf(Type $type): TrinaryLogic
public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
{
if ($type instanceof self) {
return TrinaryLogic::createFromBoolean(
return IsSuperTypeOfResult::createFromBoolean(
$type->rowType !== null
&& $this->rowType !== null
&& $type->rowType->equals($this->rowType)
Expand Down
6 changes: 3 additions & 3 deletions src/PdoReflection/PdoStatementObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

use PDOStatement;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BenevolentUnionType;
use PHPStan\Type\Constant\ConstantArrayTypeBuilder;
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerRangeType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IsSuperTypeOfResult;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
Expand Down Expand Up @@ -165,10 +165,10 @@ public function equals(Type $type): bool
return parent::equals($type);
}

public function isSuperTypeOf(Type $type): TrinaryLogic
public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
{
if ($type instanceof self) {
return TrinaryLogic::createFromBoolean(
return IsSuperTypeOfResult::createFromBoolean(
$type->fetchType !== null
&& $type->bothType !== null
&& $this->bothType !== null
Expand Down
8 changes: 4 additions & 4 deletions src/QueryReflection/BasePdoQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ abstract class BasePdoQueryReflector implements QueryReflector, RecordingReflect
protected const MAX_CACHE_SIZE = 50;

/**
* @var array<string, PDOException|list<ColumnMeta>|null>
* @var array<string, PDOException|array<ColumnMeta>|null>
*/
protected array $cache = [];

Expand All @@ -69,7 +69,7 @@ abstract class BasePdoQueryReflector implements QueryReflector, RecordingReflect
protected $stmt = null;

/**
* @var array<string, array<string, list<string>>>
* @var array<string, array<string, array<int, string>>>
*/
protected array $emulatedFlags = [];

Expand Down Expand Up @@ -138,7 +138,7 @@ public function getResultType(string $queryString, int $fetchType): ?Type
}

/**
* @return list<string>
* @return array<int, string>
*/
protected function emulateFlags(string $nativeType, string $tableName, string $columnName): array
{
Expand Down Expand Up @@ -175,7 +175,7 @@ public function getDatasource()
}

/**
* @return PDOException|list<ColumnMeta>|null
* @return PDOException|array<ColumnMeta>|null
*/
abstract protected function simulateQuery(string $queryString);

Expand Down
8 changes: 6 additions & 2 deletions src/QueryReflection/MysqliQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class MysqliQueryReflector implements QueryReflector, RecordingReflector
private const MAX_CACHE_SIZE = 50;

/**
* @var array<string, mysqli_sql_exception|list<object>|null>
* @var array<string, mysqli_sql_exception|array<object>|null>
*/
private array $cache = [];

Expand Down Expand Up @@ -96,9 +96,13 @@ public function getResultType(string $queryString, int $fetchType): ?Type
foreach ($result as $val) {
if (
! property_exists($val, 'name')
|| ! is_string($val->name)
|| ! property_exists($val, 'type')
|| ! is_int($val->type)
|| ! property_exists($val, 'flags')
|| ! is_int($val->flags)
|| ! property_exists($val, 'length')
|| ! is_int($val->length)
) {
throw new ShouldNotHappenException();
}
Expand Down Expand Up @@ -127,7 +131,7 @@ public function setupDbaApi(?DbaApi $dbaApi): void
}

/**
* @return mysqli_sql_exception|list<object>|null
* @return mysqli_sql_exception|array<object>|null
*/
private function simulateQuery(string $queryString)
{
Expand Down
2 changes: 1 addition & 1 deletion src/QueryReflection/PdoMysqlQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function __construct(PDO $pdo)
}

/**
* @return PDOException|list<ColumnMeta>|null
* @return PDOException|array<ColumnMeta>|null
*/
protected function simulateQuery(string $queryString)
{
Expand Down
Loading