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

Setup static analysis with Psalm #3951

Merged
merged 2 commits into from
Apr 14, 2020
Merged

Conversation

greg0ire
Copy link
Member

@greg0ire greg0ire commented Apr 14, 2020

Q A
Type improvement
BC Break no
Fixed issues n/a

Summary

This PR adds static analysis with Psalm, configured to the most lenient level, and ignores every error.
I am targeting 2.10.x, because this change does not touch code in lib, or dependencies under require.

@greg0ire
Copy link
Member Author

I think it will not show up until merged, but the result can already be preview on this PR I made in my fork

@greg0ire greg0ire requested a review from morozov April 14, 2020 16:58
@greg0ire greg0ire added the CI label Apr 14, 2020
@greg0ire greg0ire marked this pull request as ready for review April 14, 2020 16:59
@greg0ire
Copy link
Member Author

Travis fails because the version of Psalm I installed is too recent. I will add something in composer.json to make sure we install something supported on 7.2

@greg0ire greg0ire force-pushed the sa-with-psalm branch 3 times, most recently from 7bcc967 to 8cce3ab Compare April 14, 2020 17:44
Copy link
Member

@morozov morozov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised that we have so few errors to whitelist of which most are related to the DB extensions. BTW, why doesn't it report the existing mixed[][] return types?

composer.json Outdated Show resolved Hide resolved
composer.lock Show resolved Hide resolved
baseline.xml Outdated Show resolved Hide resolved
@greg0ire
Copy link
Member Author

greg0ire commented Apr 14, 2020

I'm surprised that we have so few errors to whitelist of which most are related to the DB extensions. BTW, why doesn't it report the existing mixed[][] return types?

That's probably because I went for the most lenient level (8)

EDIT: or because the tests directory is not included :P

This should make it easier to work with Composer from machines using
different versions of PHP than the lowest one we use in the CI.
@greg0ire greg0ire force-pushed the sa-with-psalm branch 2 times, most recently from b3f71e0 to 6370f83 Compare April 14, 2020 20:08
@morozov
Copy link
Member

morozov commented Apr 14, 2020

or because the tests directory is not included :P

I see. Is it because we also don't run PHPStan against tests? Do you want to add it in master? Mind that someone will have to up-merge the new dependency and update the baseline. And that someone will be you @greg0ire :-)

@greg0ire
Copy link
Member Author

It was both reasons: the issues is reported starting at level 6.

I can add psalm to all branches when doing the upmerges, But I'm not sure if that's what you meant, I'm under the impression that you would like me to add it in master and then do the upmerge, is that correct? And if yes, why?

@morozov
Copy link
Member

morozov commented Apr 14, 2020

No, once this PR gets merged, we'll need to merge 2.10.x2.11.x3.0.xmaster to get the changes propagated. And given that each of the branches is different in the underlying code, each up-merge PR may need to adjust the baseline (e.g. change the paths, include new exceptions or remove the irrelevant ones).

@greg0ire
Copy link
Member Author

Ok, I'll take care of it :)

@morozov
Copy link
Member

morozov commented Apr 14, 2020

Great work by the way, @greg0ire! I'm glad that we eventually have Psalm in the build pipeline.

@greg0ire
Copy link
Member Author

greg0ire commented Apr 14, 2020

Thanks me, too :)

@greg0ire greg0ire merged commit 72d9081 into doctrine:2.10.x Apr 14, 2020
@greg0ire greg0ire self-assigned this Apr 14, 2020
@ondrejmirtes
Copy link
Contributor

@morozov Why is baseline fine for you with Psalm, but not with PHPStan? Linking our discussion here: #3799 (comment)

@greg0ire greg0ire deleted the sa-with-psalm branch April 15, 2020 11:42
@greg0ire
Copy link
Member Author

@ondrejmirtes we do have a baseline for PHPStan:

dbal/phpstan.neon.dist

Lines 11 to 74 in 72d9081

# extension not available
- '~^(Used )?(Function|Constant) sasql_\S+ not found\.\z~i'
# removing it would be BC break
- '~^Constructor of class Doctrine\\DBAL\\Schema\\Table has an unused parameter \$idGeneratorType\.\z~'
# declaring $tableName in AbstractSchemaManager::_getPortableTableIndexesList() non-optional will be a BC break
- '~^Parameter #2 \$table of class Doctrine\\DBAL\\Event\\SchemaIndexDefinitionEventArgs constructor expects string, string\|null given\.\z~'
# changing these would be a BC break, to be done in next major
- "~^Casting to bool something that's already bool.~"
- "~^Casting to int something that's already int.~"
- '~^Method Doctrine\\DBAL\\Driver\\IBMDB2\\DB2Connection::exec\(\) should return int but returns bool\.\z~'
- '~^Property Doctrine\\DBAL\\Schema\\Table::\$_primaryKeyName \(string\) does not accept (default value of type )?false\.\z~'
- '~^Property Doctrine\\DBAL\\Schema\\Schema::\$_schemaConfig \(Doctrine\\DBAL\\Schema\\SchemaConfig\) does not accept default value of type false\.\z~'
- '~^Method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint::onEvent\(\) should return string\|null but returns false\.\z~'
- '~^Method Doctrine\\DBAL\\Schema\\(Oracle|PostgreSql|SQLServer)SchemaManager::_getPortableTableDefinition\(\) should return array but returns string\.\z~'
- '~^Method Doctrine\\DBAL\\Driver\\OCI8\\OCI8Connection::lastInsertId\(\) should return string but returns (int|false)\.\z~'
- '~^Method Doctrine\\DBAL\\Driver\\SQLSrv\\SQLSrvConnection::errorCode\(\) should return string\|null but returns false\.\z~'
# https://bugs.php.net/bug.php?id=78126
- '~^Call to an undefined method Doctrine\\DBAL\\Driver\\PDOConnection::sqliteCreateFunction\(\)\.\z~'
# https://github.com/phpstan/phpstan/issues/1847
- '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::unknownAlias\(\) expects array<string>, array<int, int\|string> given\.\z~'
- '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::nonUniqueAlias\(\) expects array<string>, array<int, int\|string> given\.\z~'
# PHPStan is too strict about preg_replace(): https://phpstan.org/r/993dc99f-0d43-4b51-868b-d01f982c1463
- '~^Method Doctrine\\DBAL\\Platforms\\AbstractPlatform::escapeStringForLike\(\) should return string but returns string\|null\.\z~'
# legacy variadic-like signature
- '~^Method Doctrine\\DBAL(\\.*)?Connection::query\(\) invoked with \d+ parameters?, 0 required\.\z~'
# some drivers actually do accept 2nd parameter...
- '~^Method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getListTableForeignKeysSQL\(\) invoked with \d+ parameters, 1 required\.\z~'
# legacy remnants from doctrine/common
- '~^Class Doctrine\\Common\\(Collections\\Collection|Persistence\\Proxy) not found\.\z~'
- '~^.+ on an unknown class Doctrine\\Common\\(Collections\\Collection|Persistence\\Proxy)\.\z~'
# inheritance variance inference issue
- '~^Method Doctrine\\DBAL\\Driver\\PDOConnection::\w+\(\) should return Doctrine\\DBAL\\Driver\\Statement but returns PDOStatement\.\z~'
# may not exist when pdo_sqlsrv is not loaded but PDO is
- '~^Access to undefined constant PDO::SQLSRV_ENCODING_BINARY\.\z~'
# weird class name, represented in stubs as OCI_(Lob|Collection)
- '~unknown class OCI-(Lob|Collection)~'
# https://github.com/JetBrains/phpstorm-stubs/pull/766
- '~^Method Doctrine\\DBAL\\Driver\\Mysqli\\MysqliStatement::_fetch\(\) never returns null so it can be removed from the return typehint\.$~'
# The ReflectionException in the case when the class does not exist is acceptable and does not need to be handled
- '~^Parameter #1 \$argument of class ReflectionClass constructor expects class-string<T of object>\|T of object, string given\.$~'
# https://github.com/phpstan/phpstan/issues/3132
-
message: '~^Call to function in_array\(\) with arguments Doctrine\\DBAL\\Schema\\Column, array<string> and true will always evaluate to false\.$~'
path: %currentWorkingDirectory%/lib/Doctrine/DBAL/Schema/Table.php
# https://github.com/phpstan/phpstan/issues/3133
-
message: '~^Cannot cast array<string>\|bool\|string\|null to int\.$~'
path: %currentWorkingDirectory%/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php

@ondrejmirtes
Copy link
Contributor

This is not a baseline in the sense we talked about in the linked discussion :) PHPStan's baseline is generated with --generate-baseline: https://phpstan.org/user-guide/baseline

@greg0ire
Copy link
Member Author

TIL :)

@morozov
Copy link
Member

morozov commented Apr 15, 2020

Why is baseline fine for you with Psalm, but not with PHPStan? Linking our discussion here: #3799 (comment)

This is a valid question. I didn't think of it because we were using the lowest possible level and the baseline was way smaller than in #3799. Although, it is getting out of hand (I don't remember seeing occurrences="93" in the very first patch).

@greg0ire before we proceed with merging it to master, let's take a pause and see if the baselined errors could be fixed (3.0 allows for BC breaks) and the non-fixable ones are suppressed manually.

@greg0ire
Copy link
Member Author

greg0ire commented Apr 15, 2020

@morozov I don't know if you noticed but the baseline is way smaller for master: https://github.com/doctrine/dbal/pull/3954/files#diff-043e2f3614861e20eb0fb277052a7693, but sure, I will have a look at 3.0.x

@greg0ire
Copy link
Member Author

The first error I noticed does not imply a BC-break, and gets us rid of ~ 100 errors, so I'm going to have a look at 2.10.x first

@morozov
Copy link
Member

morozov commented Apr 15, 2020

I noticed that but I didn't think of them as the finally required baselines. It's a good sign, on the one hand, meaning that we did a good job there. But on the other hand, we still need to get rid of those many repetitive occurrences of the same error. Otherwise, each time we modify something, we'll hit the same error again.

@greg0ire
Copy link
Member Author

greg0ire commented Apr 15, 2020

Ok so now I'm getting a crash on 2.10.x that I don't get with the deps of 3.0.x… 🤦‍♂️

Uncaught TypeError: Return value of PhpParser\Comment::getFilePos() must be of the type int, null returned in /home/greg/dev/doctrine-dbal/vendor/nikic/php-parser/lib/PhpParser/Comment.php:53
Stack trace:
#0 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Diff/ClassStatementsDiffer.php(78): PhpParser\Comment->getFilePos()
#1 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Diff/AstDiffer.php(53): Psalm\Internal\Diff\ClassStatementsDiffer::Psalm\Internal\Diff\{closure}(Object(PhpParser\Node\Stmt\ClassMethod), Object(PhpParser\Node\Stmt\ClassMethod), '<?php\n\nnamespac...', '<?php\n\nnamespac...', false)
#2 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Diff/ClassStatementsDiffer.php(45): Psalm\Internal\Diff\AstDiffer::calculateTrace(Object(Closure), Array, Array, '<?php\n\nnamespac...', '<?php\n\nnamespac...')
#3 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php(98): Psalm\Internal\Diff\ClassStatementsDiffer::diff('Doctrine\\DBAL\\S...', Array, Array, '<?php\n\nnamespac...', '<?php\n\nnamespac...')
#4 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Diff/FileStatementsDiffer.php(92): Psalm\Internal\Diff\NamespaceStatementsDiffer::diff('Doctrine\\DBAL\\S...', Array, Array, '<?php\n\nnamespac...', '<?php\n\nnamespac...')
#5 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Provider/StatementsProvider.php(179): Psalm\Internal\Diff\FileStatementsDiffer::diff(Array, Array, '<?php\n\nnamespac...', '<?php\n\nnamespac...')
#6 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/FileScanner.php(68): Psalm\Internal\Provider\StatementsProvider->getStatementsForFile('/home/greg/dev/...', Object(Psalm\Progress\DefaultProgress))
#7 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(586): Psalm\Internal\Scanner\FileScanner->scan(Object(Psalm\Codebase), Object(Psalm\Storage\FileStorage), false, Object(Psalm\Progress\DefaultProgress))
#8 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(367): Psalm\Internal\Codebase\Scanner->scanFile('/home/greg/dev/...', Array, true)
#9 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(475): Psalm\Internal\Codebase\Scanner->Psalm\Internal\Codebase\{closure}(0, '/home/greg/dev/...')
#10 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(325): Psalm\Internal\Codebase\Scanner->scanFilePaths(1)
#11 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Codebase.php(477): Psalm\Internal\Codebase\Scanner->scanFiles(Object(Psalm\Internal\Codebase\ClassLikes), 3)
#12 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(519): Psalm\Codebase->scanFiles(3)
#13 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/src/psalm.php(588): Psalm\Internal\Analyzer\ProjectAnalyzer->check('/home/greg/dev/...', false)
#14 /home/greg/dev/doctrine-dbal/vendor/vimeo/psalm/psalm(2): require_once('/home/greg/dev/...')
#15 {main}
(Psalm 3.11.2@d470903722cfcbc1cd04744c5491d3e6d13ec3d9 crashed due to an uncaught Throwable)

EDIT: Works after composer update nikic/php-parser… moving on.

rgrellmann added a commit to Rossmann-IT/dbal that referenced this pull request Apr 22, 2020
Release [2.10.2](https://github.com/doctrine/dbal/milestone/75)

2.10.2
======

- Total issues resolved: **4**
- Total pull requests resolved: **19**
- Total contributors: **10**

Improvement,Static Analysis
---------------------------

 - [3964: Mark every exception as immutable](doctrine#3964) thanks to @greg0ire

CI,Improvement,Static Analysis
------------------------------

 - [3961: Stop relying on the master version of Psalm](doctrine#3961) thanks to @greg0ire
 - [3951: Setup static analysis with Psalm](doctrine#3951) thanks to @greg0ire
 - [3799: Upgrade to PHPStan v0.12](doctrine#3799) thanks to @lcobucci

Improvement,Logging,Test Suite
------------------------------

 - [3957: Reworked LoggingTest to be able to test Statement::executeUpdate()](doctrine#3957) thanks to @morozov

CI,Code Style,Improvement,Strict Typing
---------------------------------------

 - [3955: Remove baseline](doctrine#3955) thanks to @greg0ire

Bug,SQLite,Schema Introspection,Schema Managers
-----------------------------------------------

 - [3937: Column comment incorrectly introspected on SQLite](doctrine#3937) thanks to @morozov

Bug,Documentation,Prepared Statements,Query
-------------------------------------------

 - [3896: Updated documentation for QueryBuilder::execute() return value type](doctrine#3896) thanks to @morozov

Bug,Prepared Statements
-----------------------

 - [3894: Make sure that the $types array has the same keys $params](doctrine#3894) thanks to @morozov
 - [3893: Ensure the constructor arguments are passed to custom classes](doctrine#3893) thanks to @duncan3dc
 - [3843: Fix unquoted stmt fragments backslash escaping](doctrine#3843) thanks to @morozov

Documentation,Improvement
-------------------------

 - [3886: Update readme](doctrine#3886) thanks to @greg0ire
 - [3834: Fix docblock typos in DriverManager docs](doctrine#3834) thanks to @CHItA

CI,Improvement,MariaDB,MySQL
----------------------------

 - [3884: Use Docker consistently](doctrine#3884) thanks to @greg0ire
 - [3478: Improve readiness probe stability for containerized databases on CI](doctrine#3478) thanks to @morozov

 - [3883: Fix broken build](doctrine#3883) thanks to @greg0ire

Bug,Documentation,Query,Query Limit/Offset Modification
-------------------------------------------------------

 - [3842: Fixed the QueryBuilder::setMaxResults() signature to accept NULL](doctrine#3842) thanks to @morozov

Bug,Query
---------

 - [3832: Fix JOIN with no condition bug](doctrine#3832) thanks to @BenMorel

Bug,PostgreSQL,Schema Introspection
-----------------------------------

 - [3821: &doctrine#91;pg&doctrine#93; fix getting table information if search&doctrine#95;path contains escaped schema name](doctrine#3821) thanks to @linniksa

Documentation,Improvement,Logging
---------------------------------

 - [3812: Fix DebugStack#queries docblock type](doctrine#3812) thanks to @ostrolucky

Bug,Regression,Schema
---------------------

 - [3790: fixed unqualified table name of fk constraints when using schemas](doctrine#3790) thanks to @stlrnz and @Alarich

# gpg: Signature made Mon Apr 20 19:59:36 2020
# gpg:                using DSA key 2C3A645671828132
# gpg: Can't check signature: public key not found

# Conflicts:
#	README.md
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants