Skip to content

Conversation

@johnbillion
Copy link
Member

@johnbillion johnbillion commented Jan 4, 2021

Trac ticket: https://core.trac.wordpress.org/ticket/52217

This introduces config for PHPStan with plenty of exclusions so we can identify real issues that need to be fixed.

Changes:

Copy link
Member

@jrfnl jrfnl left a comment

Choose a reason for hiding this comment

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

While I'm not against the principle of adding more QA tools to our tooling chain, I'm not a fan of PHPStan for WordPress.

PHPStan - and Psalm as well for that matter - work best with well-typed code bases, the stricter the better.
WordPress is most definitely not such a code base, so the noise from false positives will be huge.

These are tools primarily aimed at modern PHP, not legacy codebases, and some of the results will include suggestions for modernizing code which cannot be applied to WP due to the low minimum PHP version we still have to deal with.
Also please realize that including the tooling could encourage people who are not as aware of the minimum PHP version for WP, to start sending in patches for things which cannot be applied in WP yet, causing wasted time both for the contributors who created the patches as well as for other maintainers having to explain - time and again - why the patch cannot be accepted.

I do think it's a good idea to do intermittent, ad-hoc runs with tools like PHPStan, Psalm, Exakat and other tools, but adding it as a dependency is a no-go, if for no other reason than the conflicting minimum PHP requirements.

I'm actually surprised the CI runs aren't breaking on this as it is, but haven't looked into that.

*/
global $post_type;

/** @var WP_Terms_List_Table $wp_list_table */
Copy link
Member

Choose a reason for hiding this comment

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

What value do these type of comments add (other than to satisfy PHPstan) ?
(here and everywhere else in this patch)

Copy link
Member Author

Choose a reason for hiding this comment

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

Our list tables aren't LSP compatible, so any code editor or IDE that provides intellisense (in addition to PHPStan) raises errors further down when accessing methods or properties that only exist on certain WP_List_Table sub-classes. These inline type declarations avoid those errors.

Copy link
Member

Choose a reason for hiding this comment

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

Which, in my humble opinion, is doing things the wrong way around.

The LSP violations should be fixed and @hellofromtonya and me have been discussing the problem with those in our live stream sessions recently as well.

Adding comments to avoid addressing the real problem, especially comment which are only recognized by a select set of IDEs/tooling, just doesn't make any sense whatsoever to me.

Copy link
Member Author

Choose a reason for hiding this comment

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

That is indeed the preferred and correct way to address the problem, but realistically can that be fixed? And can it be enforced in future list tables? These classes are a free-for-all due to the dynamic method names used by columns and the arbitrary methods introduced in sub-classes.

There's nothing wrong with specifying the type of a variable in a PHPDoc where it cannot be determined statically. In this case it has the same effect as directly instantiating the concrete class instead of instantiating it via the _get_list_table() wrapper (which is little more than a non-standard implementation of an autoloader).

* @param callable $admin_image_div_callback Optional. Custom image div output callback.
*/
public function __construct( $admin_header_callback = '', $admin_image_div_callback = '' ) {
public function __construct( $admin_header_callback = null, $admin_image_div_callback = null ) {
Copy link
Member

Choose a reason for hiding this comment

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

This could be considered a behavioral change, especially as the class is not final and may be extended in userland plugin/theme code.

To keep the existing behaviour, the property default values would need to be set to '' instead of changing the default values of the parameters in the constructor, but considering it is supposed to be a callable I agree that is counter-intuitive.

All the same, could you explain why the choice was made for doing it the other way around ?

Also: the places where these callables are used in the class do not use proper type checking. If anything, I'd advocate for the loose type if ( $this->admin_image_div_callback ) checks to be replaced with checks against is_callable().

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes these classes can be extended, but the default value of an untyped parameter does not affect its signature, so it's safe to change this in the parent class and cause the sub-classes to diverge. Example: https://3v4l.org/8g5df

The choice to switch to a null default value is to make the parameter a nullable callable. A default value of '' means the parameter is actually callable|string and that doesn't help anybody. I agree that the loose checking could be enhanced with is_callable() checks, but that's outside the scope of the changes I want to make here.

Copy link
Member

Choose a reason for hiding this comment

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

I understand you want to limit the scope, but the is_callable() change is actually a useful change, while this isn't.

* @param callable $admin_image_div_callback Optional. Custom image div output callback.
*/
public function __construct( $admin_header_callback, $admin_image_div_callback = '' ) {
public function __construct( $admin_header_callback, $admin_image_div_callback = null ) {
Copy link
Member

Choose a reason for hiding this comment

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

Same remark as made for src/wp-admin/includes/class-custom-background.php applies here.

* Undocumented variable
*
* @since ?.?.?
* @var float
Copy link
Member

Choose a reason for hiding this comment

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

Blank line comment line needed between the above two tags (same applies to the $error property docblock).

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks! I need to finish these.

@@ -0,0 +1,100 @@
<?php
Copy link
Member

@jrfnl jrfnl Jul 15, 2021

Choose a reason for hiding this comment

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

Why is this placed in the tests directory ? This has nothing to do with testing WP.

Note: I realize @aaronjorbin and my comments about this are at odds with each other. Maybe a more general discussion should be had about what to do with tooling config files.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure where best to put this, but static analysis is testing so I don't think it's an inappropriate location. Suggestions welcome though.

Copy link
Member

Choose a reason for hiding this comment

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

I think this belongs in the tests directory since I view static analysis as a form of testing (which seems to jive with @johnbillion since he said it just above me). I view automated testing as anything that automates a process of ensuring code quality.

@@ -0,0 +1,100 @@
<?php
// phpcs:ignoreFile

Copy link
Member

Choose a reason for hiding this comment

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

This list looks like it will quickly go out of date and add maintenance burden. Can a more dynamic solution be found for this ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point but I think the maintenance burden is low. Constants are not introduced very often and this is not a complete list of all constants, just ones which are unconditionally accessed by the files that are scanned by PHPStan.

@@ -0,0 +1,100 @@
<?php
// phpcs:ignoreFile
Copy link
Member

Choose a reason for hiding this comment

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

This file should be added to the phpcs.xml.dist file for ignoring instead of having an inline comment.

@hellofromtonya
Copy link
Contributor

hellofromtonya commented Jul 16, 2021

Problems of using PHPStan as an inline inspection tool

PHPStan - and Psalm as well for that matter - work best with well-typed code bases, the stricter the better.
WordPress is most definitely not such a code base, so the noise from false positives will be huge.

I agree. I'd like to echo and add to @jrfnl's concerns.

PHPStan will generate a huge volume of false positives. Why is this a problem?

  • Significant effort will be needed to investigate each PHPStan incident to determine if it's a valid positive AND if it's something that could or should be changed for WordPress specifically without causing a backwards-compat issue.
    I've witnessed this with the work being done in Trac ticket 51423. It's time-consuming work and the type of work that requires deep knowledge about not only PHP but also WordPress itself.

  • Risk of changing the codebase to make PHPStan happy without adding value to the codebase.

  • Bottlenecks in the workflow for contributors, maintainers, and committers.

  • Frustration pain point for contributors in figuring out how to make PHPStan happy.

Where does PHPStan fit into the project?

I do think it's a good idea to do intermittent, ad-hoc runs with tools like PHPStan, Psalm, Exakat and other tools

I agree. This tool and others can serve WordPress as a periodic auditing tool.

What about this PR?

There are valid fixes and improvements in this PR:

  • Some look like bug fixes
    These could be broken out into separate tickets for tracking, history, and isolated discussion and testing.
  • Some are potential code improvements, though many need testing to ensure each is valid and does not cause a backwards compat issue.
    These could be also be broken out from the PHPStan work as a separate ticket and PR.

By splitting out the work we can ensure these are not lost (along with the extensive code reviews) in the debate about whether to use PHPStan as an inline CI tool or not.

@johnbillion
Copy link
Member Author

@hellofromtonya I've addressed your main concern about the impact of introducing static analysis in the comments on https://core.trac.wordpress.org/ticket/52217, but in short I don't believe that it introduces the sort of significant burden and large number of false positives that you've seen on https://core.trac.wordpress.org/ticket/51423 . This ticket aims to start at level 1, whereas 51423 aims to tackle type related problems that are several steps ahead of where we are now.

@johnbillion
Copy link
Member Author

I'm going to update the description of this PR with notes about each change. I realise that it's not clear why quite a few of these changes have been made.

johnbillion and others added 5 commits July 19, 2021 22:41
@johnbillion
Copy link
Member Author

# Conflicts:
#	src/wp-includes/class-wp-http-cookie.php
#	src/wp-includes/class.wp-dependencies.php
#	src/wp-includes/widgets.php
#	src/wp-includes/wp-db.php
@johnbillion
Copy link
Member Author

@samuelsolis
Copy link

This is an interesting point and seems easy to add to the project, what can we do to push it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants