Using PHPStan can improve the code quality of Drupal core.
This issue can be used to track progress on cleaning up all PHPStan errors found in Drupal Core.
PHPStan runs in different levels, the plan is to go up each level, and fix errors one level at a time.
PHPStan has a baseline to add, so we can go up a level, and by that moment disallow new errors from that level to enter the codebase, and add all the existing errors to the baseline so they can be fixed afterwards.
Start using phpstan
Add and configure phpstan in core
#3178534: Start running PHPStan on Drupal core (level 0)
#3259142: PHPStan commit check fails if a file is deleted
#3259353: Run full phpstan on composer change
#3259355: Always do a full phpstan analysis on DrupalCI
PHPStan ignored errors and files
To allow PHPStan to be added to core it was decided to ignore some files throwing problems and also ignore some errors. Those should be revisited.
excludePaths:
# Skip settings.
- ../*/settings*.php
# Skip test fixtures.
- */tests/fixtures/*.php
# Below extends on purpose a non existing class for testing.
- modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/ExtendingNonInstalledClass.php
# @todo files below need to be excluded as they prevent baseline generation.
# Fixing them is a priority.
- modules/link/tests/src/Kernel/LinkItemTest.php
ignoreErrors:
# new static() is a best practice in Drupal, so we cannot fix that.
- "#^Unsafe usage of new static#"
# Ignore common errors for now.
- "#^Access to an undefined property#"
- "#^Call to an undefined method#"
- "#^Cannot unset offset#"
- "#should return .* but return statement is missing#"
- "#Drupal calls should be avoided in classes, use dependency injection instead#"
- "#^Plugin definitions cannot be altered.#"
- "#^Missing cache backend declaration for performance.#"
- "#cache tag might be unclear and does not contain the cache key in it.#"
- "#^Class .* extends @internal class#"
#3254966: PHPStan error LinkItemTest
#3259110: Fix undefined variables where files are included
#3259109: Fix 'Cannot unset offset' PHPStan L0 errors
#3259716: Replace usages of static::class . '::methodName' to first-class callable syntax static::method(...)
Upstream issues to followup
We already found some improvements / false positives. The should be fixed upstream and updated when a new release is available for phpstan / phpstan-drupal.
* Function twig_escape_filter not found #310
message: "#^Function twig_escape_filter not found\\.$#"
count: 1
path: lib/Drupal/Core/Template/TwigExtension.php
* BrowserTestBaseDefaultThemeRule ignore InstallerExistingConfigTestBase tests #311
message: "#^Drupal\\\\Tests\\\\BrowserTestBase\\:\\:\\$defaultTheme is required\\. See https\\://www\\.drupal\\.org/node/3083055, which includes recommendations on which theme to use\\.$#"
count: 1
path: modules/quickedit/tests/src/FunctionalJavascript/QuickEditJavascriptTestBase.php
* RenderCallbackRule causes error in PlaceholderGenerator #303
message: "#^The \"\\#lazy_builder\" expects a callable array with arguments\\.$#"
count: 1
path: lib/Drupal/Core/Render/PlaceholderGenerator.php
PHPStan level 0
Review the baseline and check for issues to be created.
https://git.drupalcode.org/project/drupal/-/blob/10.0.x/core/phpstan-bas...
One of the most occuring problems in the baseline is
Call to deprecated constant REQUEST_TIME (133 of 230 lines in baseline)
#2902895: [meta][no patch] Replace uses of REQUEST_TIME and time() with time service
PHPStan level 1 (and up)
Decide when to go a level up? Does the baseline needs to be fully clean?
#3190406: Update PHPStan to level 1
Comments
Comment #2
daffie commentedComment #3
andypostComment #5
mallezieIn the child issues there is already work done, and even some subissues split off which fixed things, spotted by phpstan, even it's not running on drupal core (yet).
I think in this main meta issue we should first discuss the plan of approach here, and link the correct issues. First step offcourse is to add phpstan, and then start fixing this. To break this up in smaller chunks, i would propose the following steps to doe.
If this sounds a bit okay, i can work on cleaning up the subissues to follow this plan.
Comment #6
mondrakei think #5.1 makes sense especially now that PhpStan 1.0 is out (actually, 1.1 already).
Comment #7
mondrakeComment #8
mondrakeI suggest to start tagging 'phpstan' all issues related to this, and 'PHPStan-X' with X=level all issues specific to solving a set of a PHPStan level problems.
Comment #10
mallezieComment #11
mallezieComment #12
mallezieComment #13
mallezieComment #14
mglamanI don't have the time to open a proper issue, but here's one we need to open. Replace usages of
static::class . '::methodName'to[static::class, 'methodName']array callable versus concatenation onstatic::classThat is why we have this error:
From:
It's just a PHPStan thing where
static:classis handled a specify way for generics. So concatenating is weird. So let's use the proper array callable format for these scenarios and it will pass. See https://github.com/mglaman/phpstan-drupal/issues/301 for more background.Other example: modules/big_pipe/tests/modules/big_pipe_regression_test/src/BigPipeRegressionTestController.php
Comment #15
mglamanAfter reading the baseline, I am tracking the following three issues to resolve a few false-positives or bugs in phpstan-drupal
* Function twig_escape_filter not found #310
* BrowserTestBaseDefaultThemeRule ignore InstallerExistingConfigTestBase tests #311
* RenderCallbackRule causes error in PlaceholderGenerator #303
Comment #16
mondrakeThanks @mallezie for cleaning up this meta, it helps a lot!
IMHO not necessarily, but for sure we need to reduce the
ignoreErrorspatterns to a minimum - either solving them or moving them to baseline. Without that we will be potentially silently adding new failing code without knowing - whereas with baseline we would be able to take a picture and avoid new failures. Also for sure the baseline right now is too fat.Comment #17
mallezieAdded issue for #14
#3259716: Replace usages of static::class . '::methodName' to first-class callable syntax static::method(...)
And added some stuff to the issue summary.
For moving up i fully agree currently our baseline is too fat. I think at least following requirements should be met:
* IgnoreRules and IgnoreErrrors are removed from the config (and fixed or in the baseline)
* The baseline should contain less than X items (first wild estimate for a number should be around 50, but depends on what is in the baseline). Could be a combination between less than X items in the baseline, and less then Y different messages in the baseline.
Comment #18
mondrakeJust checked, Level 1 would add over 800 more errors ATM.
Comment #19
andypostLinked #3293933: Upgrade phpstan/phpstan to 1.8.1
Comment #20
mondrakeI suggest we close this at this stage, PHPStan is already running on level 1.