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

Enable PHPStan strict rules #3932

Merged
merged 19 commits into from
Apr 11, 2020
Merged

Enable PHPStan strict rules #3932

merged 19 commits into from
Apr 11, 2020

Conversation

morozov
Copy link
Member

@morozov morozov commented Apr 7, 2020

Q A
Type improvement
BC Break yes

The initial work was done on top of master and then backported to 3.0.x to get the tests improved as well. This is an important addition on top of the existing code quality checks since it helps to find potential bugs and prevents the new code of questionable quality from being introduced.

Additionally, in master the test suite will be cleaned up since a lot of assertions are no longer needed thanks to the improved type system (#3348).

Fixed issues:

The analysis identified a couple of potential issues and deviations from the best practices:

  1. The constraint $name variable declared in the foreach loop overrides the table $name method argument that is used down the line. Most likely, a table with such constraints will have an invalid name:
    foreach ($options['uniqueConstraints'] as $name => $definition) {
    $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition);
    }
  2. This is unlikely a bug but usually, a loose comparison of the strpos() return value looks suspicious:
    if (strpos($dbType, 'with time zone')) {
  3. Also unlikely a bug but depending on the fetch mode, an empty value stored in the cache may be ignored:
    $data = $this->resultCache->fetch($this->cacheKey);
    if (! $data) {
  4. An empty-ish comment like "0" set on a table in Oracle may be ignored:
    if (! $comment) {
    continue;
    }
  5. This code is barely readable. The only situation when this expression evaluates to TRUE is when the counts are not equal which should have been coded explicitly:
    || substr_count($query, '(', $orderByPos) - substr_count($query, ')', $orderByPos)

Technically, BC-breaks:

  1. A zero value of the $fetchMode argument in the Statement methods is no longer ignored. Not that anyone should have used it but in order to use the default mode, it should be omitted or expressed as NULL.
  2. The empty values of the "connectstring", "host", "service" and "instancename" parameters of the oci8 and pdo_oci drivers are no longer ignored if passed explicitly.
  3. The empty value of the "port" parameter of the pdo_sqlsrv driver is no longer ignored if passed explicitly.
  4. The following QueryBuilder methods still accept null as an optional parameter but will no longer ignore another explicitly passed empty value: ::select(), ::addSelect(), ::insert(), ::update(), ::delete().
  5. Statement::execute(), QueryBuilder::groupBy() and ::addGroupBy() will no longer an explicitly passed non-array empty value.
  6. AbstractPlatform::getTrimExpression() will no longer ignore an empty value of $mode (use TrimMode::UNSPECIFIED or omit); and an empty value of $char (use false or omit).

Other empty values in various configurations are not ignored if passed explicitly

Future improvements identified

The errors suppressed in the PHPStan configuration identify the by-design issues that need to be fixed in the future:

  1. Internal data structures are represented as untyped associative arrays instead of objects (e.g. connection configuration, table/column definitions). A similar improvement was recently implemented in Introduce properties for SQL parts in QueryBuilder #3836.
  2. The AbstractSchemaManager::tryMethod() implements dynamic method calls and needs to be redesigned and internalized to DBAL.

Additional, not strictly relevant issues fixed:

  1. The comma in the regular expression pattern doesn't need to be escaped:
    if (preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) {

TODO:

Copy link
Member

@greg0ire greg0ire left a comment

Choose a reason for hiding this comment

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

Document the no longer ignored empty values.

Is this something you plan to do before merging? Approving in case it isn't

I think Scrutinizer fails because if views the change in SQLSeverSchemaManager as an increase in complexity, but to me the if is easier to understand than the ternary

@morozov
Copy link
Member Author

morozov commented Apr 10, 2020

Is this something you plan to do before merging? Approving in case it isn't

I was going to put this in the PR description, no more code changes expected.

I think Scrutinizer fails because if views the change in SQLSeverSchemaManager as an increase in complexity […]

Yes, and we can't do anything else with it than ignore it.

[…] but to me the if is easier to understand than the ternary

I agree. Furthermore, the original reason for this was to pass the option down the line only if it's explicitly set. There's no point in passing the default explicitly. Also, it makes line coverage report more accurate.

@morozov morozov merged commit 14f5f15 into doctrine:3.0.x Apr 11, 2020
@morozov morozov deleted the phpstan-stricter branch April 11, 2020 00:06
@morozov morozov added this to the 3.0.0 milestone Apr 11, 2020
@morozov morozov self-assigned this Apr 11, 2020
@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.

2 participants