From 92777f22a53e25aba20d8c6dee47686ea54a5b3b Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 6 Jan 2025 12:25:57 +0100 Subject: [PATCH] PHPStan 2.1.1 --- .github/workflows/static-analysis.yml | 4 +- composer.json | 4 +- phpstan-baseline.neon | 181 ++++++++++++++++++ phpstan.neon.dist | 22 ++- src/Driver/API/OCI/ExceptionConverter.php | 4 +- src/Event/SchemaDropTableEventArgs.php | 7 +- src/Platforms/AbstractPlatform.php | 2 +- .../Builder/CreateSchemaObjectsSQLBuilder.php | 6 +- src/Schema/Comparator.php | 2 +- 9 files changed, 210 insertions(+), 22 deletions(-) create mode 100644 phpstan-baseline.neon diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 5fdb47196dc..cea25ef1ed9 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -34,7 +34,7 @@ jobs: strategy: matrix: php-version: - - "8.3" + - "8.4" steps: - name: "Checkout code" @@ -49,6 +49,8 @@ jobs: - name: "Install dependencies with Composer" uses: "ramsey/composer-install@v3" + with: + composer-options: "--ignore-platform-req=php+" - name: "Run a static analysis with phpstan/phpstan" run: "vendor/bin/phpstan --error-format=checkstyle | cs2pr" diff --git a/composer.json b/composer.json index 3ccf38e1728..7376138ab42 100644 --- a/composer.json +++ b/composer.json @@ -43,8 +43,8 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.12.6", - "phpstan/phpstan-strict-rules": "^1.6", + "phpstan/phpstan": "2.1.1", + "phpstan/phpstan-strict-rules": "^2", "phpunit/phpunit": "9.6.22", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 00000000000..2c7c222a6a8 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,181 @@ +parameters: + ignoreErrors: + - + message: '#^@readonly property cannot have a default value\.$#' + identifier: property.readOnlyByPhpDocDefaultValue + count: 1 + path: src/Driver/AbstractException.php + + - + message: '#^Method Doctrine\\DBAL\\Driver\\OCI8\\Result\:\:fetchAllAssociative\(\) should return list\\> but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Driver/OCI8/Result.php + + - + message: '#^Method Doctrine\\DBAL\\Driver\\OCI8\\Result\:\:fetchAllNumeric\(\) should return list\\> but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Driver/OCI8/Result.php + + - + message: '#^@readonly property Doctrine\\DBAL\\Driver\\PDO\\PDOException\:\:\$sqlState is assigned outside of the constructor\.$#' + identifier: property.readOnlyByPhpDocAssignNotInConstructor + count: 1 + path: src/Driver/PDO/PDOException.php + + - + message: '#^@readonly property cannot have a default value\.$#' + identifier: property.readOnlyByPhpDocDefaultValue + count: 1 + path: src/Driver/PDO/PDOException.php + + - + message: '#^Method Doctrine\\DBAL\\Driver\\PDO\\Result\:\:fetchAll\(\) should return list\ but returns array\.$#' + identifier: return.type + count: 1 + path: src/Driver/PDO/Result.php + + - + message: '#^Method Doctrine\\DBAL\\Driver\\PgSQL\\Result\:\:fetchAllAssociative\(\) should return list\\> but returns array\\>\.$#' + identifier: return.type + count: 1 + path: src/Driver/PgSQL/Result.php + + - + message: '#^Method Doctrine\\DBAL\\Driver\\PgSQL\\Result\:\:fetchAllNumeric\(\) should return list\\> but returns array\\>\.$#' + identifier: return.type + count: 1 + path: src/Driver/PgSQL/Result.php + + - + message: '#^Method Doctrine\\DBAL\\Driver\\PgSQL\\Result\:\:fetchFirstColumn\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Driver/PgSQL/Result.php + + - + message: '#^Method Doctrine\\DBAL\\Driver\\SQLite3\\Result\:\:fetchNumeric\(\) should return list\\|false but returns array\|false\.$#' + identifier: return.type + count: 1 + path: src/Driver/SQLite3/Result.php + + - + message: '#^Method Doctrine\\DBAL\\Platforms\\AbstractMySQLPlatform\:\:getAlterTableSQL\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Platforms/AbstractMySQLPlatform.php + + - + message: '#^Parameter \#1 \$assets of method Doctrine\\DBAL\\Platforms\\AbstractMySQLPlatform\:\:indexAssetsByLowerCaseName\(\) expects list\, array\ given\.$#' + identifier: argument.type + count: 1 + path: src/Platforms/AbstractMySQLPlatform.php + + - + message: '#^Method Doctrine\\DBAL\\Platforms\\AbstractPlatform\:\:buildCreateTableSQL\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 2 + path: src/Platforms/AbstractPlatform.php + + - + message: '#^Method Doctrine\\DBAL\\Platforms\\DB2Platform\:\:getAlterTableSQL\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Platforms/DB2Platform.php + + - + message: '#^Method Doctrine\\DBAL\\Platforms\\OraclePlatform\:\:getAlterTableSQL\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Platforms/OraclePlatform.php + + - + message: '#^Method Doctrine\\DBAL\\Platforms\\PostgreSQLPlatform\:\:getAlterTableSQL\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Platforms/PostgreSQLPlatform.php + + - + message: '#^Method Doctrine\\DBAL\\Platforms\\SQLServerPlatform\:\:getAlterTableSQL\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 2 + path: src/Platforms/SQLServerPlatform.php + + - + message: '#^Method Doctrine\\DBAL\\Platforms\\SqlitePlatform\:\:getAlterTableSQL\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Platforms/SqlitePlatform.php + + - + message: '#^Method Doctrine\\DBAL\\Platforms\\SqlitePlatform\:\:getAlterTableSQL\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Platforms/SqlitePlatform.php + + - + message: '#^Parameter &\$knownAliases by\-ref type of method Doctrine\\DBAL\\Query\\QueryBuilder\:\:getSQLForJoins\(\) expects array\, non\-empty\-array\ given\.$#' + identifier: parameterByRef.type + count: 1 + path: src/Query/QueryBuilder.php + + - + message: '#^Property Doctrine\\DBAL\\Query\\QueryBuilder\:\:\$params \(array\\|string, mixed\>\) does not accept non\-empty\-array\\.$#' + identifier: assign.propertyType + count: 1 + path: src/Query/QueryBuilder.php + + - + message: '#^Parameter \#1 \$sequences of method Doctrine\\DBAL\\SQL\\Builder\\DropSchemaObjectsSQLBuilder\:\:buildSequenceStatements\(\) expects list\, array\ given\.$#' + identifier: argument.type + count: 1 + path: src/SQL/Builder/DropSchemaObjectsSQLBuilder.php + + - + message: '#^Parameter \#1 \$tables of method Doctrine\\DBAL\\SQL\\Builder\\DropSchemaObjectsSQLBuilder\:\:buildTableStatements\(\) expects list\, array\ given\.$#' + identifier: argument.type + count: 1 + path: src/SQL/Builder/DropSchemaObjectsSQLBuilder.php + + - + message: '#^Method Doctrine\\DBAL\\Schema\\AbstractSchemaManager\:\:doListTableNames\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Schema/AbstractSchemaManager.php + + - + message: '#^Template type T is declared as covariant, but occurs in invariant position in property Doctrine\\DBAL\\Schema\\AbstractSchemaManager\:\:\$_platform\.$#' + identifier: generics.variance + count: 1 + path: src/Schema/AbstractSchemaManager.php + + - + message: '#^Parameter \#1 \$tables of method Doctrine\\DBAL\\Platforms\\AbstractPlatform\:\:getDropTablesSQL\(\) expects list\, array\ given\.$#' + identifier: argument.type + count: 1 + path: src/Schema/SchemaDiff.php + + - + message: '#^Method Doctrine\\DBAL\\Schema\\SqliteSchemaManager\:\:addDetailsToTableForeignKeyColumns\(\) should return list\\> but returns array\, array\\>\.$#' + identifier: return.type + count: 1 + path: src/Schema/SqliteSchemaManager.php + + - + message: '#^Method Doctrine\\DBAL\\Schema\\TableDiff\:\:getAddedForeignKeys\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Schema/TableDiff.php + + - + message: '#^Method Doctrine\\DBAL\\Schema\\TableDiff\:\:getDroppedForeignKeys\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Schema/TableDiff.php + + - + message: '#^Method Doctrine\\DBAL\\Schema\\TableDiff\:\:getModifiedForeignKeys\(\) should return list\ but returns array\\.$#' + identifier: return.type + count: 1 + path: src/Schema/TableDiff.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index e7a2aad5461..70afdb63459 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,6 +1,6 @@ parameters: level: 8 - phpVersion: 80300 + phpVersion: 80402 paths: - src - static-analysis @@ -9,10 +9,6 @@ parameters: ignoreErrors: - identifier: missingType.generics - # https://github.com/doctrine/dbal/pull/3836 - # TODO: remove in 4.0.0 - - '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::nonUniqueAlias\(\) expects array, array given\.\z~' - # some drivers actually do accept 2nd parameter... - '~^Method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getListTableForeignKeysSQL\(\) invoked with \d+ parameters, 1 required\.\z~' @@ -131,7 +127,7 @@ parameters: # PHPStan does not understand the array shapes returned by pg_fetch_*() methods. - '~^Parameter #1 \$row of method Doctrine\\DBAL\\Driver\\PgSQL\\Result\:\:mapAssociativeRow\(\) expects array, array given\.$~' - - '~^Parameter #1 \$row of method Doctrine\\DBAL\\Driver\\PgSQL\\Result\:\:mapNumericRow\(\) expects array, array given\.$~' + - '~^Parameter #1 \$row of method Doctrine\\DBAL\\Driver\\PgSQL\\Result\:\:mapNumericRow\(\) expects list, .* given\.$~' # Ignore isset() checks in destructors. - '~^Property Doctrine\\DBAL\\Driver\\PgSQL\\Connection\:\:\$connection \(PgSql\\Connection\|resource\) in isset\(\) is not nullable\.$~' @@ -152,5 +148,19 @@ parameters: message: '#^Parameter \#2 \$callback of function array_reduce expects callable\(\(callable&TIn\)\|Closure\(mixed \$value\)\: mixed\|null, callable\(T\)\: T\)\: \(\(callable&TIn\)\|Closure\(mixed \$value\)\: mixed\|null\), Closure\(callable\|null, callable\)\: \(callable\(T\)\: T\) given\.$#' path: src/Portability/Converter.php + # The @throws annotations are part of a contract. Even if the default implementation doen't throw those + # exceptions, the child implementations might do so. + - + identifier: throws.unusedType + path: src/Types/Type.php + + # We don't narrow the return type of lastInsertId() yet. + - '/^Method Doctrine\\DBAL\\Driver\\.+\\Connection\:\:lastInsertId\(\) never returns (int|false) so it can be removed from the return type\.$/' + + # Unnecessarily strict type narrowing + - '~^Method Doctrine\\DBAL\\Driver\\PDO\\ParameterTypeMap\:\:convertParamType\(\) never returns \d+ so it can be removed from the return type\.$~' + includes: + - phpstan-baseline.neon + - phar://phpstan.phar/conf/bleedingEdge.neon - vendor/phpstan/phpstan-strict-rules/rules.neon diff --git a/src/Driver/API/OCI/ExceptionConverter.php b/src/Driver/API/OCI/ExceptionConverter.php index a979bc7832e..64dc6335e5d 100644 --- a/src/Driver/API/OCI/ExceptionConverter.php +++ b/src/Driver/API/OCI/ExceptionConverter.php @@ -32,9 +32,9 @@ final class ExceptionConverter implements ExceptionConverterInterface /** @link http://www.dba-oracle.com/t_error_code_list.htm */ public function convert(Exception $exception, ?Query $query): DriverException { - /** @psalm-var int|'HY000' $code */ + /** @psalm-var int|'HY000' $code */ // @phpstan-ignore varTag.type $code = $exception->getCode(); - /** @psalm-suppress NoInterfaceProperties */ + /** @psalm-suppress NoInterfaceProperties */ // @phpstan-ignore property.notFound, property.notFound if ($code === 'HY000' && isset($exception->errorInfo[1], $exception->errorInfo[2])) { $errorInfo = $exception->errorInfo; $exception = new PDOException($errorInfo[2], $errorInfo[1]); diff --git a/src/Event/SchemaDropTableEventArgs.php b/src/Event/SchemaDropTableEventArgs.php index f45e3a15a82..6f279e96598 100644 --- a/src/Event/SchemaDropTableEventArgs.php +++ b/src/Event/SchemaDropTableEventArgs.php @@ -4,7 +4,6 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; -use InvalidArgumentException; /** * Event Arguments used when the SQL query for dropping tables are generated inside {@see AbstractPlatform}. @@ -21,11 +20,7 @@ class SchemaDropTableEventArgs extends SchemaEventArgs /** @var string|null */ private $sql; - /** - * @param string|Table $table - * - * @throws InvalidArgumentException - */ + /** @param string|Table $table */ public function __construct($table, AbstractPlatform $platform) { $this->table = $table; diff --git a/src/Platforms/AbstractPlatform.php b/src/Platforms/AbstractPlatform.php index 928a5a02121..69c05e288fd 100644 --- a/src/Platforms/AbstractPlatform.php +++ b/src/Platforms/AbstractPlatform.php @@ -2226,7 +2226,7 @@ private function buildCreateTableSQL(Table $table, bool $createIndexes, bool $cr } /** - * @param list $tables + * @param Table[] $tables * * @return list * diff --git a/src/SQL/Builder/CreateSchemaObjectsSQLBuilder.php b/src/SQL/Builder/CreateSchemaObjectsSQLBuilder.php index 2e392e661b2..74579b3e00a 100644 --- a/src/SQL/Builder/CreateSchemaObjectsSQLBuilder.php +++ b/src/SQL/Builder/CreateSchemaObjectsSQLBuilder.php @@ -34,7 +34,7 @@ public function buildSQL(Schema $schema): array } /** - * @param list $namespaces + * @param string[] $namespaces * * @return list * @@ -54,7 +54,7 @@ private function buildNamespaceStatements(array $namespaces): array } /** - * @param list
$tables + * @param Table[] $tables * * @return list * @@ -66,7 +66,7 @@ private function buildTableStatements(array $tables): array } /** - * @param list $sequences + * @param Sequence[] $sequences * * @return list * diff --git a/src/Schema/Comparator.php b/src/Schema/Comparator.php index 28e7f2f73b2..8114ec5e258 100644 --- a/src/Schema/Comparator.php +++ b/src/Schema/Comparator.php @@ -636,7 +636,7 @@ public function diffColumn(Column $column1, Column $column2) // null != 0, null != false, null != '' etc. This affects platform's table alteration SQL generation. if ( ($properties1['default'] === null) !== ($properties2['default'] === null) - || $properties1['default'] != $properties2['default'] + || $properties1['default'] != $properties2['default'] // @phpstan-ignore notEqual.notAllowed ) { $changedProperties[] = 'default'; }