Problem/Motivation
After some code changes in #3423310: Change !isset to ??= assignment operator: multi-line case. using ??= operator the MR faced obstructions in #3423310-#11 from phpstan: 4 = 2x2 errors: 2 files,
---------------------------------------------------------------------------------
Line core/modules/views/src/Plugin/views/display/PathPluginBase.php
---------------------------------------------------------------------------------
Ignored error pattern #^Variable \$access_plugin in isset\(\) always
exists and is not nullable\.$# in path
/builds/issue/drupal-3423310/core/modules/views/src/Plugin/views/display/PathPluginBase.php
was not matched in reported errors.
199 Variable $access_plugin on left side of ??= always exists and is not
nullable.
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
Line core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php
----------------------------------------------------------------------------------
Ignored error pattern #^Variable \$message in isset\(\) always exists
and is not nullable\.$# in path
/builds/issue/drupal-3423310/core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php
was not matched in reported errors.
309 Variable $message on left side of ??= always exists and is not
nullable.
----------------------------------------------------------------------------------
[ERROR] Found 4 errors
The two code changes are,
--- a/core/modules/views/src/Plugin/views/display/PathPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/PathPluginBase.php
@@ -195,10 +195,8 @@ protected function getRoute($view_id, $display_id) {
// Add access check parameters to the route.
$access_plugin = $this->getPlugin('access');
- if (!isset($access_plugin)) {
- // @todo Do we want to support a default plugin in getPlugin itself?
- $access_plugin = Views::pluginManager('access')->createInstance('none');
- }
+ // @todo Do we want to support a default plugin in getPlugin itself?
+ $access_plugin ??= Views::pluginManager('access')->createInstance('none');
$access_plugin->alterRouteDefinition($route);--- a/core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php
+++ b/core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php
@@ -306,9 +306,7 @@ protected function assertPreviewAJAX(int $row_count): void {
* @internal
*/
protected function assertClass(NodeElement $element, string $class, string $message = ''): void {
- if (!isset($message)) {
- $message = "Class .$class found.";
- }
+ $message ??= "Class .$class found.";
$this->assertStringContainsString($class, $element->getAttribute('class'), $message);
}
Steps to reproduce
Proposed resolution
The changed codes seem regular. Though what happens and the message are clear: the problem is not the change, but the concerned variables, $access_plugin and $message. With the changes the two files come in the scope of phpstan during the MR process. And phpstand thinks that the two variables are not nullable, since some thing is wrong in their origin. They should be explicitly declared as nullable.
- No use of ??= in this issue, only phpstan problems (see #5 and #6).
- For $message, it's an argument of the function. In the same file core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php in
* @param string $message
* (optional) A verbose message to output.
*
* @internal
*/
protected function assertClass(NodeElement $element, string $class, string $message = ''): void {change,
* @param string $message
to
* @param string|null $message
Or,
\Drupal\Tests\views_ui\FunctionalJavascript\PreviewTest::assertClass
should match
\Drupal\Tests\system\Functional\Pager\PagerTest::assertClass
to do that change
protected function assertClass(NodeElement $element, string $class, string $message = ''): void {
to
protected function assertClass(NodeElement $element, string $class, string $message = NULL): void {
in core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php. (see #6 and #14)
We use the second one.
- For $access_plugin, it isn't an argument. Since it comes from $this->getPlugin('access') and for the class,
abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInterface, DependentPluginInterface {
the right file is core/modules/views/src/Plugin/views/display/DisplayPluginInterface.php. Here, in,
/**
* Get the instance of a plugin, for example style or row.
*
* @param string $type
* The type of the plugin.
*
* @return \Drupal\views\Plugin\views\ViewsPluginInterface
*/
public function getPlugin($type);change,
* @return \Drupal\views\Plugin\views\ViewsPluginInterface
to
* @return \Drupal\views\Plugin\views\ViewsPluginInterface|null
(see #5 and #15)
- After #20 the core/phpstan-baseline.neon should be update: remove the 5 items.
- Following the messages,
in empty\(\) always exists and is not falsy
in isset\(\) always exists and is not nullablesince always exists, make some changes empty($A) to !$A and isset($A) to $A !== NULL.
(Not always, to keep the ??= transformations still possible.)
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #26 | 3424107-nr-bot.txt | 90 bytes | needs-review-queue-bot |
Issue fork drupal-3424107
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
chris64Comment #3
chris64Comment #4
dpiIf either error is true, then the line should not be converted to ??=. Nor should it be left as isset().
If the change is correct, then the code leading to it should be changed. With better typehints, for example.
I'd suggest changing the code in the other issue. Just make sure you are justifying the change clearly in documenting a issue/MR comment.See next comments
Comment #5
dpiFor PathPluginBase, \Drupal\views\Plugin\views\display\DisplayPluginInterface::getPlugin the docs say it can never return null.
However I can see there a
return void;, so lets create an issue just for this, which changes the documentation, and explicitlyreturn NULL;This issue could be used as a template: #3391355: \Drupal\Core\Config\StorageInterface::read is typehinted as possibly returning bool, but never returns true
In this case I wouldnt recommend changing the relevant lines in the ??= issue.
Comment #6
dpiFor PreviewTest.php, lets keep the change in the ??= issue.
However, lets change
\Drupal\Tests\views_ui\FunctionalJavascript\PreviewTest::assertClassso the method signature (and docs) match\Drupal\Tests\system\Functional\Pager\PagerTest::assertClass.Comment #7
chris64Comment #8
chris64@dpi, thank you for your answer, We can discuss.
Well, this case block the MR, because of the phpstan error. I face this before.
So, is not nullable, so,
is inconsistent: never go in the block. Or is nullable, and this code is okay (...and could be changed to ??=).
Comment #9
chris64@dpi, I think the problem is not
??=. The problem, as phpstan tells us, is not nullable +isset.Comment #10
chris64I push the work, since done. It can be refused.
Comment #12
chris64An error exists.
Comment #13
chris64Okay @dpi, after having a look your requests about
nullare clear for me.Comment #14
chris64About #6, on one side, in
core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php,On the other side, in
core/modules/system/tests/src/Functional/Pager/PagerTest.php,To make the two match change,
, string $message = ''): void {to
, string $message = NULL): void {Comment #15
chris64@dpi, for #6 and
$access_plugin,I believe you have in head,
in
getPluginincore/modules/views/src/Plugin/views/display/DisplayPluginBase.php. And if I follow #3391355: \Drupal\Core\Config\StorageInterface::read is typehinted as possibly returning bool, but never returns true I think the change needed should be,* @return \Drupal\views\Plugin\views\ViewsPluginInterfaceto
* @return \Drupal\views\Plugin\views\ViewsPluginInterface|nullin,
in
core/modules/views/src/Plugin/views/display/DisplayPluginInterface.phpsince,abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInterface, DependentPluginInterface {Comment #16
chris64Finally the issue perimeter could be restricted to the nullable problems,
using this issue for these problems.
Comment #17
chris64Comment #18
chris64Comment #19
chris64Comment #20
chris64Still some phpstan errors,
Comment #21
chris64Comment #22
chris64- The phpstan errors have no line number. The corresponding items should be removed from
core/phpstan-baseline.neonfile.- Following the messages,
since always exists, make some changes
empty($A)to!$Aandisset($A)to$A !== NULL. (Not always, to keep the??=transformations still possible.)Comment #23
chris64MR mergeable. NR.
Comment #24
quietone commentedThe title is also the commit message, so this should be easier to understand when searching history in the future.
Comment #25
chris64Title changed. Less detailed but more clear.
Comment #26
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #27
smustgrave commentedOn the coding standard decision #3436307: Change !isset to the null coalescing assignment operator ??=